Python (WSGI/ASGI)
Overview
Section titled “Overview”OpenLiteSpeed can serve Python web applications through two approaches:
- LSAPI — LiteSpeed’s native Python LSAPI module (best performance)
- Reverse proxy — OLS proxies to Gunicorn, uWSGI, or Uvicorn (more flexible)
Method 1: Python LSAPI
Section titled “Method 1: Python LSAPI”LiteSpeed provides a Python LSAPI module that communicates with OLS using the same high-performance protocol used by lsphp.
Install Python LSAPI
Section titled “Install Python LSAPI”pip install lswsgiDjango with LSAPI
Section titled “Django with LSAPI”Configure the external application in httpd_config.conf:
extprocessor python { type lsapi address uds://tmp/lshttpd/python.sock maxConns 10 initTimeout 60 retryTimeout 0 persistConn 1 respBuffer 0 autoStart 1 path /usr/bin/python3 backlog 100 instances 1 env PYTHONPATH=/var/www/myproject env LSAPI_CHILDREN=10}Create a wsgi_entry.py at your project root (or use Django’s default wsgi.py):
import osos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
from django.core.wsgi import get_wsgi_applicationapplication = get_wsgi_application()Flask with LSAPI
Section titled “Flask with LSAPI”from myapp import app as applicationScript Handler and Context
Section titled “Script Handler and Context”context / { type lsapi handler python addDefaultCharset off}Method 2: Reverse Proxy to Gunicorn
Section titled “Method 2: Reverse Proxy to Gunicorn”Install and Run Gunicorn
Section titled “Install and Run Gunicorn”pip install gunicorn
# Djangocd /var/www/myprojectgunicorn myproject.wsgi:application --bind 127.0.0.1:8000 --workers 4
# Flaskgunicorn myapp:app --bind 127.0.0.1:8000 --workers 4Gunicorn systemd Service
Section titled “Gunicorn systemd Service”[Unit]Description=Gunicorn Django ServerAfter=network.target
[Service]User=nobodyGroup=nobodyWorkingDirectory=/var/www/myprojectExecStart=/usr/local/bin/gunicorn myproject.wsgi:application \ --bind unix:/run/gunicorn/gunicorn.sock \ --workers 4 \ --timeout 120Restart=alwaysRestartSec=5
[Install]WantedBy=multi-user.targetmkdir -p /run/gunicornchown nobody:nobody /run/gunicornsystemctl enable --now gunicornOLS Proxy Configuration
Section titled “OLS Proxy Configuration”extprocessor gunicorn { type proxy address uds://run/gunicorn/gunicorn.sock maxConns 100 initTimeout 60 retryTimeout 0 persistConn 1 respBuffer 0}Virtual host context:
# Serve static files directlycontext /static/ { location /var/www/myproject/static/ allowBrowse 1 extraHeaders { set Cache-Control "public, max-age=31536000" }}
context /media/ { location /var/www/myproject/media/ allowBrowse 1}
# Proxy dynamic requestscontext / { type proxy handler gunicorn addDefaultCharset off}Method 3: Reverse Proxy to uWSGI
Section titled “Method 3: Reverse Proxy to uWSGI”Install and Run uWSGI
Section titled “Install and Run uWSGI”pip install uwsgi
uwsgi --http-socket 127.0.0.1:8000 \ --wsgi-file myproject/wsgi.py \ --master \ --processes 4 \ --threads 2OLS Configuration
Section titled “OLS Configuration”extprocessor uwsgi_app { type proxy address 127.0.0.1:8000 maxConns 100 initTimeout 60 retryTimeout 0 persistConn 1 respBuffer 0}ASGI Applications (Django Channels, FastAPI)
Section titled “ASGI Applications (Django Channels, FastAPI)”For async Python frameworks, use Uvicorn or Daphne behind OLS.
FastAPI with Uvicorn
Section titled “FastAPI with Uvicorn”pip install fastapi uvicorn
uvicorn main:app --host 127.0.0.1 --port 8000 --workers 4Django Channels with Daphne
Section titled “Django Channels with Daphne”pip install daphnedaphne -b 127.0.0.1 -p 8000 myproject.asgi:applicationConfigure OLS the same way as any reverse proxy:
extprocessor asgi_app { type proxy address 127.0.0.1:8000 maxConns 100 initTimeout 60 retryTimeout 0 persistConn 1 respBuffer 0}
# In vhconf.confcontext / { type proxy handler asgi_app addDefaultCharset off}WebSocket support works automatically through the proxy context.
Django Static Files
Section titled “Django Static Files”Collect static files and serve them directly through OLS:
python manage.py collectstaticEnsure STATIC_ROOT in Django settings points to a directory OLS can serve:
STATIC_URL = '/static/'STATIC_ROOT = '/var/www/myproject/static/'Troubleshooting
Section titled “Troubleshooting”ModuleNotFoundError in LSAPI mode:
- Set the
PYTHONPATHenvironment variable in the extprocessor config - Ensure the virtual environment is activated or its site-packages are in
PYTHONPATH
502 Bad Gateway:
- Verify the Python process is running
- Check socket permissions for Unix socket connections
- Review OLS error log at
/usr/local/lsws/logs/error.log
Static files returning 404:
- Run
python manage.py collectstatic - Verify the OLS context path matches
STATIC_URL