Running mod_wsgi-express
mod_wsgi-express is the admin command installed alongside the
mod_wsgi Python package. It builds the mod_wsgi Apache module
against the Apache and Python on your host, generates a
self-contained Apache configuration tuned for hosting a single
WSGI application, and starts an Apache instance owned by your
user.
This page picks up from Getting Started, which already
covers the first-run “Hello world” with mod_wsgi-express
start-server. Here the focus is on the operational shape:
common options, running on privileged ports, dealing with
non-standard Apache layouts, Django and Flask integration, and using
mod_wsgi-express under a process supervisor or in a
container.
For installing the mod_wsgi package itself, see
Installation From PyPI.
Subcommands
mod_wsgi-express is invoked as mod_wsgi-express <command>.
The commands fall into two groups.
For running an Apache instance hosting your WSGI application:
start-serverruns an Apache instance in the foreground, hosting the WSGI script you supply. This is the common case during development and the typical entry point under a process supervisor.setup-serverwrites out the same configuration plus a generatedapachectlwrapper, but does not start Apache. Used for daemonised init-script style deployments where Apache is started and stopped separately. See Running on a privileged port below.
For wiring the pip-built mod_wsgi module into a system Apache:
module-configprints theLoadModuleandWSGIPythonHomelines needed to reference the module from inside the Python install.install-modulecopies the module into Apache’s modules directory and prints the correspondingLoadModuleline.module-locationprints just the filesystem path to the built module.
The module-config and install-module paths are covered in
detail under “Connecting the pip-built module to system Apache”
in Installation From PyPI.
Verifying the installation
The mod_wsgi.diagnostics submodule ships two minimal WSGI
applications usable as quick install checks before pointing
mod_wsgi-express at a real application:
mod_wsgi-express start-server --application-type module \
mod_wsgi.diagnostics.environ
This serves the diagnostic page at http://localhost:8000/. A
successful request confirms that the Python interpreter, the
built mod_wsgi.so, the generated Apache configuration, and
the request path through to the WSGI handler all line up.
The bundled applications are:
mod_wsgi.diagnostics.environDiagnostic page showing the WSGI
environdictionary, the process and host environment, mod_wsgi process and server metrics, Apache build details, and the Python interpreter’s locale and path settings.mod_wsgi.diagnostics.helloThe smallest possible “Hello World!” WSGI application. Useful when the diagnostic page is too noisy and the goal is just to confirm that an HTTP response makes it back from a WSGI application running under
mod_wsgi-express.
Common options
The full option list is large; mod_wsgi-express start-server
--help is the canonical reference. The options most likely to
come up are:
--port NUMBERPort to listen on. Defaults to 8000.
--host IP-ADDRESSHost interface to bind. Defaults to all interfaces.
--processes NUMBERNumber of daemon-mode worker processes. Defaults to 1.
--threads NUMBERThreads per worker process. Defaults to 5.
--user USERNAME/--group GROUPUser and group the daemon process should run as. Required when starting as root, ignored otherwise. See Running on a privileged port.
--reload-on-changesRestart the daemon process whenever any Python source file that the WSGI application has imported is modified, not just the WSGI entrypoint script itself. A background monitor thread polls
sys.modulesonce a second, stat()s every loaded module’s source file, and triggers a restart on the first change it sees. For development use only. It is not safe in production: every loaded module is stat()’d on every poll cycle (so cost scales with the size of the application), and any in-flight requests are interrupted when the daemon is restarted. Without this option, daemon-mode reloading still picks up changes to the WSGI entrypoint script file alone (the default mod_wsgi behaviour). See Reloading Source Code for the broader reloading model.--log-to-terminalWrite Apache’s access and error logs to standard output and standard error rather than to files under the server root. Required when running under a process supervisor or in a container that expects logs on the terminal.
--server-root DIRECTORY-PATHWhere the generated configuration files and runtime state live. Defaults to a directory under
/tmp. Override this forsetup-serverso the configuration persists across reboots.--application-type TYPEDefaults to
script(a WSGI script file specified by filesystem path). Can also bemodule(a Python module name imported through the standard import mechanism) orstatic(serve a directory of static files only).
Hosting static files
For applications that do not have static-file routing wired
up by their framework, mod_wsgi-express can serve static
assets directly from Apache rather than routing them through
the WSGI application. The --url-alias option maps a URL
prefix to a file or directory on disk; it is the express
equivalent of Apache’s Alias directive.
To serve a directory of CSS, JavaScript, and image assets at
the /static/ URL:
mod_wsgi-express start-server wsgi.py \
--url-alias /static/ /srv/myapp/static/
A GET /static/site.css request is now served by Apache
directly out of /srv/myapp/static/site.css without
entering the WSGI application.
The option is repeatable, and the second argument can be either a directory or a single file. A typical mix:
mod_wsgi-express start-server wsgi.py \
--url-alias /static/ /srv/myapp/static/ \
--url-alias /media/ /srv/myapp/media/ \
--url-alias /favicon.ico /srv/myapp/static/favicon.ico \
--url-alias /robots.txt /srv/myapp/static/robots.txt
The single-file form (the last two lines above) maps just
that one file to the exact URL given. Apache requires
longer/more-specific URL prefixes to be configured before
shorter ones, but mod_wsgi-express sorts the aliases
internally so the order on the command line does not
matter.
A separate --document-root option sets Apache’s
DocumentRoot directly. Files inside the document root
are reachable at their corresponding URL paths without
needing an alias. This is most useful when the WSGI
application is mounted at a sub-URL via --mount-point
and the document root holds the rest of the site:
mod_wsgi-express start-server wsgi.py \
--mount-point /api/ \
--document-root /srv/myapp/public/
In this example the WSGI application handles requests under
/api/... while Apache serves the contents of
/srv/myapp/public/ at all other URLs. The default for
--mount-point is /, which is the typical “WSGI
application at the root, static assets at sub-URLs” shape
and is what the --url-alias examples above assume.
When mod_wsgi-express runs behind a reverse proxy,
static files served this way are subject to the same
Location header rewriting and HTML-body URL leakage
caveats as the WSGI application itself; see
Running Behind A Reverse Proxy.
Other static-file options
Beyond --url-alias and --document-root, a few
options shape how Apache handles requests that map to
the document root or to --url-alias-mapped
directories:
--directory-index FILE-NAMEName of the index resource Apache serves when a request maps to a directory rather than a file (for example
index.html). Equivalent to Apache’sDirectoryIndex. Without it, a directory request is passed through to the WSGI application or, if the document root is the static target, returns 404.--directory-listingEnable Apache’s automatic directory listing when a request maps to a directory and no
--directory-indexmatch is found. Off by default. Most useful with--application-type static; rarely useful when a WSGI application is also mounted.--allow-override DIRECTIVE-TYPEPermit
.htaccessfiles inside the document root or--url-alias-mapped directories to override the named Apache directive types. Defaults toNone(.htaccessignored). Repeatable to list more than one directive type. Equivalent to Apache’sAllowOverride.--error-document STATUS URL-PATHReplace Apache’s default error page for the given HTTP status code with a static resource at the named URL. Repeatable. Equivalent to Apache’s
ErrorDocument:mod_wsgi-express start-server wsgi.py \ --error-document 404 /errors/404.html \ --error-document 500 /errors/500.html
The named URL paths typically resolve to files served from the document root or from a
--url-alias-mapped directory.--error-overrideMake Apache’s error documents replace the WSGI application’s error responses. Without this flag the WSGI application’s response body is sent through to the client as-is; with it, Apache substitutes the matching
ErrorDocumentpage. Useful when the deployment should present a uniform error experience across the WSGI application and any co-hosted static content. Daemon mode only; has no effect under--embedded-mode.
Per-extension handlers and CGI scripts
Two options route requests for files with specific extensions away from the WSGI application and into dedicated handlers.
--add-handler EXTENSION SCRIPT-PATHMap files matching
EXTENSIONunder the document root to a Python WSGI handler atSCRIPT-PATH.EXTENSIONincludes the leading dot (for example.tmpl). The handler module must define a WSGI callable namedapplication, or alternatively a function namedhandle_request; optionallyreload_required(resource)to control source reloading. Repeatable. Handlers run in the same WSGI execution context as the main application: the same daemon process group in default daemon mode, the Apache child workers under--embedded-mode. The matched file’s path is exposed to the handler viaenviron['SCRIPT_NAME']:mod_wsgi-express start-server wsgi.py \ --document-root /srv/myapp/public \ --add-handler .tmpl /srv/myapp/render_tmpl.py
--with-cgiEnable plain Apache CGI handling for
.cgifiles under the document root. Loads Apache’smod_cgid(ormod_cgiwheremod_cgidis unavailable) and emitsAddHandler cgi-script .cgi. Files with the.cgiextension that are also marked executable on the filesystem run as standalone CGI scripts in any language, following the standard CGI contract. This is not WSGI: each invocation forks a fresh process and exits when it finishes, independent of the WSGI application’s daemon pool.
The two mechanisms are complementary.
--add-handler is for in-process Python handling
of specific file types. --with-cgi is for legacy
.cgi scripts that already exist in the document
root and are not worth rewriting.
Server name and virtual hosts
By default mod_wsgi-express accepts requests on
the configured port regardless of the host header.
The following options shape its name-based
virtual-host behaviour, which matters when the
express instance is fronted by a reverse proxy that
routes by hostname, or when the same instance hosts
more than one hostname.
--server-name HOSTNAMEThe primary host name the server identifies as. Generates the Apache
ServerNamedirective. WhenHOSTNAMEbegins withwww.,mod_wsgi-expressalso adds an automatic redirect from the parent domain (withoutwww.) to thewww.form.--server-alias HOSTNAMEAdditional host name served by the same WSGI application. Generates the Apache
ServerAliasdirective. Repeatable, and wildcard patterns (*.example.com) are accepted.--allow-localhostAllow
localhost(and127.0.0.1) to reach the WSGI application even when--server-nameis set to a different public hostname. By default the name-based virtual-host gate rejects requests that do not match the server name; this flag keeps a side door open for health checks, sidecars, and other on-host clients that connect by loopback.
Process and application groups
Most users do not need to set either of these
options. The defaults (<host>:<port> for the
daemon process group name, %{GLOBAL} for the
application group, placing the application in the
Python main interpreter) are correct for normal
single-application deployments. Both options exist
for testing, experimentation, and the cases below.
--process-group NAMEOverride the WSGI daemon process group name used in the generated configuration. The default uses the listening host and port as the group name. Has no effect under
--embedded-mode. Useful when a stable, recognisable name is wanted for signal-driven recycling: with--process-group myappset, the daemon appears as(wsgi:myapp)inpsoutput, sopkill -USR1 -f wsgi:myapptargets it directly without needing to know its host/port-derived default name.--application-group NAMEOverride the WSGI application group used by the generated handler directives. The default is
%{GLOBAL}(the Python main interpreter); a name routes the application into a named sub-interpreter instead. The mod_wsgi%{ENV:VARIABLE}token is accepted as a value, in which case the application group is determined per request from an environment variable set by other means (typically aWSGIDispatchScript).
Combining --application-group %{ENV:VARIABLE}
with a WSGIDispatchScript and the
WSGIPerInterpreterGIL
directive enabled via --include-file is the basis
for experimenting with load-balancing requests across
multiple sub-interpreters that each hold their own
GIL. mod_wsgi-express does not have first-class
options for the dispatch script or
WSGIPerInterpreterGIL, so both are wired up
through --include-file alongside the dispatch
script source file. See the
WSGIPerInterpreterGIL
directive page for a worked example.
Free-threaded Python
A single option opts the express instance into running Python with the GIL disabled (PEP 703). See GIL Modes and Free-Threading for the broader context, including when free-threading is the right choice and how it compares to per-interpreter GIL.
--free-threadingEmit a top-level WSGIFreeThreading
Onin the generated configuration so the Python interpreter runs without the GIL (PEP 703). Applies to both the single daemon process group Express creates and the embedded interpreter the Apache child uses for any auth or dispatch scripts.Requires a Python build configured with
--disable-gil(typically distributed aspython3.13t,python3.14t, and so on). If the running Python is not such a build,mod_wsgi-expressexits at configuration time with an explanatory error rather than emitting a directive that the Apache process would warn about and ignore.For finer-grained scoping (free-threading for one process only, or for the embedded interpreter only), use
--include-filewith an explicit<WSGIInterpreterOptions process-group=...>container; see GIL Modes and Free-Threading for the full set of recipes and a comparison with the per-interpreter GIL alternative.
Environment plumbing
Several options shape the runtime environment the WSGI application sees, both at process startup and per request.
--working-directory DIRECTORY-PATHThe current working directory of the WSGI application. Defaults to the directory the
mod_wsgi-expresscommand was run from, which can be a surprising value (the user’s home, the directorysystemdplaced the unit in, the directorycronran the job from). Set this explicitly. The directory is also searched for Python imports unless the application later changes its working directory.--python-path DIRECTORY-PATHAdditional directory added to
sys.path. Repeatable..pthfiles in these directories are not processed; if.pthprocessing is needed, setPYTHONPATHvia an--envvars-scriptinstead.--python-eggs DIRECTORY-PATHDirectory used for unpacking Python eggs. Defaults to a sub-directory of the server root. Override when the server root is on a tmpfs or transient filesystem and the egg cache should persist across restarts.
--python-warnings SPECAdd an entry to the Python warnings filter, using the standard
-Wsyntax (action:message:category:module:lineno). Repeatable; each occurrence is emitted as a separate WSGIPythonWarnings directive in the generated configuration. The most common form is just an action:--python-warnings errorconverts every warning into an exception, useful for catching deprecation regressions in CI.--locale NAMELocale for the WSGI process, equivalent to setting
LC_ALL. If unset and the inherited locale isCorPOSIX,mod_wsgi-expresstriesen_US.UTF-8, thenC.UTF-8, falling back to the inherited locale if neither is available. The fallback chain avoids the silent ASCII-only behaviour that follows from running underC.--setenv KEY VALUEAdd a name/value pair to every request’s WSGI
environdictionary. Repeatable. Useful for static configuration the application reads fromenvironrather than from the OS process environment.--passenv KEYPass a named OS process environment variable into every request’s WSGI
environdictionary as a name/value pair. Repeatable. The express invocation must already have the variable in its process environment (typically via the supervisor unit, the container runtime, or the user’s shell).
Compression
--compress-responsesEnable compression of common text-based response types (plain text, HTML, XML, CSS, JavaScript). Off by default. Generates the Apache
mod_deflateconfiguration that compresses responses for clients advertisingAccept-Encoding: gzipordeflate.
When mod_wsgi-express runs behind a front-end
proxy, response compression is more often handled at
the proxy than at the back-end. Using both is
wasteful (double compression and decompression at
the proxy), so enable this flag only when the
express instance is the front-line server.
Telemetry
mod_wsgi can stream per-process telemetry to a local ingester for live monitoring. Express has two ways to wire this up: the manual form (point the WSGI processes at an ingester running somewhere else) and the all-in-one shortcut (express runs the ingester alongside the WSGI application). See The External Telemetry Service for the protocol, sample format and ingester architecture.
--enable-telemetryBundle the ingester and its web UI into the express instance. Express generates a service script under the server root that runs the ingester (via the
mod_wsgi-telemetrypackage) in aWSGIDaemonProcess threads=0service daemon, emits the matchingWSGITelemetryServicedirective so the WSGI processes report into the auto-derived socket, and exposes the web UI on127.0.0.1at the port given by--telemetry-ui-port.Requires the
mod_wsgi-telemetrypackage to be installed. Mutually exclusive with--telemetry-serviceand with a user-supplied--service-script telemetry ....--telemetry-ui-port NUMBERHTTP port the telemetry web UI binds to on
127.0.0.1when--enable-telemetryis set. Defaults to8888. Distinct values are needed when running more than one telemetry- enabled express instance on the same host.--telemetry-service TARGETManual form: point the WSGI processes at an ingester that is not supervised by this express instance.
TARGETis aunix:/path/to/socketvalue; remote UDP targets are not supported. Mutually exclusive with--enable-telemetry.--telemetry-interval SECONDSReporter sampling interval. Defaults to
1.0. Applies to both forms.--slow-requests SECONDSThreshold above which a still-running request is reported. Requires either
--telemetry-serviceor--enable-telemetryto also be set.--telemetry-options ARGSCapture toggles passed verbatim to a
WSGITelemetryOptionsdirective in the generated configuration. Repeatable. See the directive page for the full set of toggles.
Running on a privileged port
To listen on a privileged port such as 80 or 443,
mod_wsgi-express needs to be started as root. Apache’s
parent process binds the listening socket as root and then
drops privileges; the --user and --group options say
which account the daemon process should switch to. Most Linux
distributions predefine a service account for Apache (e.g.
www-data on Debian/Ubuntu, apache on RHEL/Fedora) which
can be reused, or you can use any other dedicated account.
There are two patterns, depending on whether the running process is supervised externally or expected to daemonise itself.
Foreground under a process supervisor
For systemd, supervisord, or a container init that expects a
foreground process, use start-server directly with
--user and --group:
sudo mod_wsgi-express start-server wsgi.py --port=80 \
--user www-data --group www-data \
--log-to-terminal
The supervisor handles restart on failure; mod_wsgi-express itself stays in the foreground and writes logs to the terminal.
Daemonised with a generated apachectl
For a traditional init-script deployment where separate
start / stop / restart commands are expected and
the running process is meant to daemonise, use setup-server
instead. It writes out the configuration and a wrapper
apachectl script but does not start Apache:
sudo mod_wsgi-express setup-server wsgi.py --port=80 \
--user www-data --group www-data \
--server-root=/etc/mod_wsgi-express-80
Apache is then started, stopped, and restarted through the generated wrapper:
/etc/mod_wsgi-express-80/apachectl start
/etc/mod_wsgi-express-80/apachectl stop
/etc/mod_wsgi-express-80/apachectl restart
The original setup-server options are cached inside the
server root, so subsequent apachectl invocations reuse the
same configuration. To change options, re-run setup-server
with the new options.
SELinux
On RHEL, Fedora, AlmaLinux, and Rocky Linux, SELinux is enforcing
by default. The bundled SELinux policy expects Apache to start
from a specific binary path and to read configuration from
specific paths. Starting Apache through mod_wsgi-express will
not match those expectations out of the box, and may fail with
Permission denied errors that are not visible in the Apache
error log because SELinux blocks them at the kernel boundary.
Two workarounds:
Move the directory specified with
--server-rootto a location SELinux already permits Apache to read.Adjust the SELinux policy to permit the
--server-rootlocation.
For brief experiments, setenforce 0 will disable SELinux
enforcement until reboot, but is not appropriate for any kind of
production use.
Non-standard Apache layouts
Several Linux distributions rename the Apache binary, or replace
it with a shell script that performs additional setup before
exec’ing the real binary. mod_wsgi-express looks for an
executable called httpd by default, so a renamed binary
will fail to start with a “command not found” style error.
Use --httpd-executable to point at the real binary:
mod_wsgi-express start-server wsgi.py \
--httpd-executable=/usr/sbin/apache2
If the distribution has wrapped httpd with a shell script and
the shell script is interfering with mod_wsgi-express (for
example, by requiring root privileges to perform other setup
steps), point --httpd-executable at whichever binary the
shell script ultimately exec’s.
Django integration
mod_wsgi-express can be invoked through Django’s
manage.py so that it picks up the Django project’s settings
and static files automatically.
Add mod_wsgi.express to INSTALLED_APPS in the Django
settings module:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mod_wsgi.express',
]
Collect static assets into the directory the Django settings designate for them:
python manage.py collectstatic
Then start the server through Django:
python manage.py runmodwsgi
This is equivalent to mod_wsgi-express start-server against
the Django project’s wsgi.py, with static-file URLs and
asset roots wired up from the Django settings.
For development, --reload-on-changes makes the daemon
restart whenever any Python file the application has imported is
modified (not just the WSGI script):
python manage.py runmodwsgi --reload-on-changes
Use this only during development; see the option description above for why it is not appropriate for production.
For the daemonised root deployment described above, the
equivalent of setup-server is --setup-only:
python manage.py runmodwsgi --setup-only --port=80 \
--user www-data --group www-data \
--server-root=/etc/mod_wsgi-express-80
The generated apachectl is then used in the same way as for
the standalone setup-server flow.
Flask integration
Flask applications work with mod_wsgi-express the same way
any other WSGI application does, with one convention difference:
the WSGI callable on a Flask application is conventionally named
app rather than application. mod_wsgi-express defaults
to looking up application on the loaded module, so a Flask
application needs the --callable-object option to point at
the right attribute:
mod_wsgi-express start-server app.py --callable-object app
This is the mod_wsgi-express equivalent of setting
WSGICallableObject app in a hand-written Apache configuration.
Either rename the Flask object to application in the source
file, or pass --callable-object app (or
WSGICallableObject app in manual configuration) to keep the
Flask-conventional name.
Process supervisors and containers
When mod_wsgi-express runs under a process supervisor
(systemd, supervisord, runit, s6) or as the main process inside
a container, two things change relative to running it
interactively:
Logs need to go to standard output and standard error rather than to files under the server root, so the supervisor or container runtime can collect them. Pass
--log-to-terminal.Apache must remain in the foreground so the supervisor sees it as a running process.
start-serveralready runs in the foreground, so no additional flag is needed.
For a Dockerfile walkthrough including base-image package requirements, the PID 1 reaping behaviour, and running as a non-root user inside the container, see Installing With Docker.
Logging
By default mod_wsgi-express writes its Apache error
log to a file under the server root and does not write
an access log at all. Several options shape what gets
logged and where it goes.
--log-to-terminalSend Apache’s access and error logs to standard output / standard error rather than to files. Used under a process supervisor or in a container; see Process supervisors and containers. When
--log-directoryis also set,--log-directorywins.--access-logEnable the Apache access log. Off by default; enabling it adds a
CustomLogdirective to the generated configuration. The destination is governed by--log-to-terminal,--log-directoryand--access-log-name.--startup-logEnable a separate startup log file capturing Apache’s own startup-phase output. Off by default; enable when troubleshooting startup failures.
--log-directory DIRECTORY-PATHDirectory the log files are written to. Defaults to the server root. Override to redirect logs to a persistent or distinct location.
--log-level NAMEApache
LogLevelvalue. Defaults towarn. Raise toinfoordebugonly when troubleshooting; verbose levels emit per-request detail and grow the log quickly.--access-log-name FILE-NAME/--error-log-name FILE-NAME/--startup-log-name FILE-NAMEFile names for the access, error and startup logs when they are written to the log directory. Defaults are
access_log,error_logandstartup_logrespectively.--access-log-format FORMATFormat string for access log records. The values
commonandcombinedare recognised as Apache log-format nicknames; any other value is used verbatim as theLogFormatdirective value.--error-log-format FORMATFormat string for error log records. Used verbatim as the Apache
ErrorLogFormatdirective value.--rotate-logsPipe log output through Apache’s
rotatelogshelper so files rotate at a size threshold. Off by default. Has no effect when--log-to-terminalis on, since rotation is meaningless against standard streams.--max-log-size MBSize threshold in megabytes for log rotation when
--rotate-logsis on. Defaults to 5.--rotatelogs-executable FILE-PATHPath to the
rotatelogsbinary. Defaults to the one discovered alongside the system Apache; set whenrotatelogsis in a non-standard location or has been renamed.
Custom Apache configuration
mod_wsgi-express generates a complete Apache
configuration from its options, but a few escape
hatches allow hand-written Apache directives or
shell-level setup to be injected without giving up
the mod_wsgi-express flow:
--include-file FILE-PATHPath to a file of additional Apache directives appended at the end of the generated configuration. Use for directives that have no
mod_wsgi-expressoption of their own (security headers, customLocationblocks, third-party module configuration). Repeatable.--rewrite-rules FILE-PATHPath to a file of
mod_rewriterules included inside the generated configuration. Defaults torewrite.confunder the server root if such a file exists. Override when the rules live alongside the application source rather than inside the generated server root.--envvars-script FILE-PATHPath to a shell script sourced before Apache starts. Use to set process-level environment variables (
DATABASE_URL,OAUTH_CLIENT_SECRET,PYTHONPATH) that the WSGI application reads at import time, or that other Apache modules consult during startup. Defaults toenvvarsunder the server root if such a file exists.
Auxiliary service processes
mod_wsgi-express can run a long-lived auxiliary
process alongside the WSGI application, supervised by
the same Apache parent. Typical uses are a queue
consumer, a metrics emitter, a periodic batch worker,
or a WebSocket sidecar reached via
--proxy-mount-point. The mechanism is the
service script: a Python script imported into a
dedicated daemon process group that runs forever
rather than handling HTTP requests.
--service-script SERVICE SCRIPT-PATHDeclare a service named
SERVICEand start it by importing the script atSCRIPT-PATHinto a dedicated daemon process group. The script’s top-level code runs as the daemon process body; if it never returns (because it enters an event loop, for example) the daemon process simply runs that code until Apache shuts it down. Repeatable to declare more than one service.--service-user SERVICE USERNAMEUser the named service runs as. Required when starting as root; ignored otherwise. Analogous to
--user, but per service.--service-group SERVICE GROUPGroup the named service runs as. Analogous to
--group, per service.--service-log-file SERVICE FILE-NAMESend the named service’s log output to a separate file rather than the shared error log. Useful when the service is verbose and would otherwise crowd out the WSGI application’s error log.
For a worked example covering the
WSGIDaemonProcess and WSGIImportScript pair
the --service-script option translates into, the
service-script lifecycle (no recycling triggers, only
restart on Apache restart or external signal), and a
running aiohttp-based metrics dashboard, see
Hosting WebSocket Applications.
Where to go next
Configuration and the WSGIDaemonProcess directive for what
mod_wsgi-expressis generating under the hood.Configuration Guidelines for richer configuration examples once you outgrow
mod_wsgi-expressand move to a hand-written Apache configuration.Processes And Threading for choosing values for
--processesand--threads.Debugging Techniques and Application Issues when things go wrong.