{"title":"How to use Django with Apache and mod_wsgi","version":"3.1","locale":"en","docname":"howto/deployment/wsgi/modwsgi","url":"/en/3.1/howto/deployment/wsgi/modwsgi/","canonical":"https://djangodocs.dev/en/3.1/howto/deployment/wsgi/modwsgi/","summary":"Deploying Django with Apache and mod_wsgi is a tried and tested way to get Django into production. mod_wsgi is an Apache module which can host any Python WSGI…","html":"<h1>How to use Django with Apache and <code class=\"docutils literal notranslate\"><span class=\"pre\">mod_wsgi</span></code><a class=\"heading-anchor\" href=\"#how-to-use-django-with-apache-and-mod-wsgi\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Deploying Django with <a class=\"reference external\" href=\"https://httpd.apache.org/\">Apache</a> and <a class=\"reference external\" href=\"https://modwsgi.readthedocs.io/en/develop/\">mod_wsgi</a> is a tried and tested way to get\nDjango into production.</p>\n<p>mod_wsgi is an Apache module which can host any Python <a class=\"reference external\" href=\"https://wsgi.readthedocs.io/en/latest/\">WSGI</a> application,\nincluding Django. Django will work with any version of Apache which supports\nmod_wsgi.</p>\n<p>The <a class=\"reference external\" href=\"https://modwsgi.readthedocs.io/\">official mod_wsgi documentation</a> is your source for all the details about\nhow to use mod_wsgi. You’ll probably want to start with the <a class=\"reference external\" href=\"https://modwsgi.readthedocs.io/en/develop/installation.html\">installation and\nconfiguration documentation</a>.</p>\n<section id=\"basic-configuration\">\n<h2>Basic configuration<a class=\"heading-anchor\" href=\"#basic-configuration\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Once you’ve got mod_wsgi installed and activated, edit your Apache server’s\n<a class=\"reference external\" href=\"https://wiki.apache.org/httpd/DistrosDefaultLayout\">httpd.conf</a> file and add the following.</p>\n<div class=\"code-block\" data-language=\"apache\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Apache</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Apache code\"><code><span class=\"nb\">WSGIScriptAlias</span><span class=\"w\"> </span>/<span class=\"w\"> </span><span class=\"sx\">/path/to/mysite.com/mysite/wsgi.py</span>\n<span class=\"nb\">WSGIPythonHome</span><span class=\"w\"> </span><span class=\"sx\">/path/to/venv</span>\n<span class=\"nb\">WSGIPythonPath</span><span class=\"w\"> </span><span class=\"sx\">/path/to/mysite.com</span>\n\n<span class=\"nt\">&lt;Directory</span><span class=\"w\"> </span><span class=\"s\">/path/to/mysite.com/mysite</span><span class=\"nt\">&gt;</span>\n<span class=\"nt\">&lt;Files</span><span class=\"w\"> </span><span class=\"s\">wsgi.py</span><span class=\"nt\">&gt;</span>\n<span class=\"nb\">Require</span><span class=\"w\"> </span><span class=\"k\">all</span><span class=\"w\"> </span>granted\n<span class=\"nt\">&lt;/Files&gt;</span>\n<span class=\"nt\">&lt;/Directory&gt;</span>\n</code></pre></div>\n<p>The first bit in the <code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIScriptAlias</span></code> line is the base URL path you want to\nserve your application at (<code class=\"docutils literal notranslate\"><span class=\"pre\">/</span></code> indicates the root url), and the second is the\nlocation of a “WSGI file” – see below – on your system, usually inside of\nyour project package (<code class=\"docutils literal notranslate\"><span class=\"pre\">mysite</span></code> in this example). This tells Apache to serve\nany request below the given URL using the WSGI application defined in that\nfile.</p>\n<p>If you install your project’s Python dependencies inside a <a class=\"reference external\" href=\"https://docs.python.org/3/library/venv.html#module-venv\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">virtual</span>\n<span class=\"pre\">environment</span></code></a>, add the path using <code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIPythonHome</span></code>. See the <a class=\"reference external\" href=\"https://modwsgi.readthedocs.io/en/develop/user-guides/virtual-environments.html\">mod_wsgi\nvirtual environment guide</a> for more details.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIPythonPath</span></code> line ensures that your project package is available for\nimport on the Python path; in other words, that <code class=\"docutils literal notranslate\"><span class=\"pre\">import</span> <span class=\"pre\">mysite</span></code> works.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;Directory&gt;</span></code> piece ensures that Apache can access your <code class=\"file docutils literal notranslate\"><span class=\"pre\">wsgi.py</span></code>\nfile.</p>\n<p>Next we’ll need to ensure this <code class=\"file docutils literal notranslate\"><span class=\"pre\">wsgi.py</span></code> with a WSGI application object\nexists. As of Django version 1.4, <a class=\"reference internal\" href=\"/en/3.1/ref/django-admin/#django-admin-startproject\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">startproject</span></code></a> will have created one\nfor you; otherwise, you’ll need to create it. See the <a class=\"reference internal\" href=\"/en/3.1/howto/deployment/wsgi/\"><span class=\"doc\">WSGI overview\ndocumentation</span></a> for the default contents you\nshould put in this file, and what else you can add to it.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>If multiple Django sites are run in a single mod_wsgi process, all of them\nwill use the settings of whichever one happens to run first. This can be\nsolved by changing:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">setdefault</span><span class=\"p\">(</span><span class=\"s2\">&quot;DJANGO_SETTINGS_MODULE&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;{{ project_name }}.settings&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>in <code class=\"docutils literal notranslate\"><span class=\"pre\">wsgi.py</span></code>, to:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"p\">[</span><span class=\"s2\">&quot;DJANGO_SETTINGS_MODULE&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;{{ project_name }}.settings&quot;</span>\n</code></pre></div>\n<p>or by <a class=\"reference internal\" href=\"#daemon-mode\"><span class=\"std std-ref\">using mod_wsgi daemon mode</span></a> and ensuring that each\nsite runs in its own daemon process.</p>\n</aside>\n<aside class=\"admonition-fixing-unicodeencodeerror-for-file-uploads admonition\">\n<p class=\"admonition-title\">Fixing <code class=\"docutils literal notranslate\"><span class=\"pre\">UnicodeEncodeError</span></code> for file uploads</p>\n<p>If you get a <code class=\"docutils literal notranslate\"><span class=\"pre\">UnicodeEncodeError</span></code> when uploading files with file names\nthat contain non-ASCII characters, make sure Apache is configured to accept\nnon-ASCII file names:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">export</span> <span class=\"n\">LANG</span><span class=\"o\">=</span><span class=\"s1\">&#39;en_US.UTF-8&#39;</span>\n<span class=\"n\">export</span> <span class=\"n\">LC_ALL</span><span class=\"o\">=</span><span class=\"s1\">&#39;en_US.UTF-8&#39;</span>\n</code></pre></div>\n<p>A common location to put this configuration is <code class=\"docutils literal notranslate\"><span class=\"pre\">/etc/apache2/envvars</span></code>.</p>\n<p>See the <a class=\"reference internal\" href=\"/en/3.1/ref/unicode/#unicode-files\"><span class=\"std std-ref\">Files</span></a> section of the Unicode reference guide for\ndetails.</p>\n</aside>\n</section>\n<section id=\"using-mod-wsgi-daemon-mode\">\n<span id=\"daemon-mode\"></span><h2>Using <code class=\"docutils literal notranslate\"><span class=\"pre\">mod_wsgi</span></code> daemon mode<a class=\"heading-anchor\" href=\"#using-mod-wsgi-daemon-mode\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>“Daemon mode” is the recommended mode for running mod_wsgi (on non-Windows\nplatforms). To create the required daemon process group and delegate the\nDjango instance to run in it, you will need to add appropriate\n<code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIDaemonProcess</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIProcessGroup</span></code> directives. A further change\nrequired to the above configuration if you use daemon mode is that you can’t\nuse <code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIPythonPath</span></code>; instead you should use the <code class=\"docutils literal notranslate\"><span class=\"pre\">python-path</span></code> option to\n<code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIDaemonProcess</span></code>, for example:</p>\n<div class=\"code-block\" data-language=\"apache\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Apache</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Apache code\"><code><span class=\"nb\">WSGIDaemonProcess</span><span class=\"w\"> </span>example.com<span class=\"w\"> </span>python-home=/path/to/venv<span class=\"w\"> </span>python-path=/path/to/mysite.com\n<span class=\"nb\">WSGIProcessGroup</span><span class=\"w\"> </span>example.com\n</code></pre></div>\n<p>If you want to serve your project in a subdirectory\n(<code class=\"docutils literal notranslate\"><span class=\"pre\">https://example.com/mysite</span></code> in this example), you can add <code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIScriptAlias</span></code>\nto the configuration above:</p>\n<div class=\"code-block\" data-language=\"apache\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Apache</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Apache code\"><code><span class=\"nb\">WSGIScriptAlias</span><span class=\"w\"> </span><span class=\"sx\">/mysite</span><span class=\"w\"> </span><span class=\"sx\">/path/to/mysite.com/mysite/wsgi.py</span><span class=\"w\"> </span>process-group=example.com\n</code></pre></div>\n<p>See the official mod_wsgi documentation for <a class=\"reference external\" href=\"https://modwsgi.readthedocs.io/en/develop/user-guides/quick-configuration-guide.html#delegation-to-daemon-process\">details on setting up daemon\nmode</a>.</p>\n</section>\n<section id=\"serving-files\">\n<span id=\"id1\"></span><h2>Serving files<a class=\"heading-anchor\" href=\"#serving-files\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django doesn’t serve files itself; it leaves that job to whichever Web\nserver you choose.</p>\n<p>We recommend using a separate Web server – i.e., one that’s not also running\nDjango – for serving media. Here are some good choices:</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference external\" href=\"https://nginx.org/en/\">Nginx</a></p></li>\n<li><p>A stripped-down version of <a class=\"reference external\" href=\"https://httpd.apache.org/\">Apache</a></p></li>\n</ul>\n<p>If, however, you have no option but to serve media files on the same Apache\n<code class=\"docutils literal notranslate\"><span class=\"pre\">VirtualHost</span></code> as Django, you can set up Apache to serve some URLs as\nstatic media, and others using the mod_wsgi interface to Django.</p>\n<p>This example sets up Django at the site root, but serves <code class=\"docutils literal notranslate\"><span class=\"pre\">robots.txt</span></code>,\n<code class=\"docutils literal notranslate\"><span class=\"pre\">favicon.ico</span></code>, and anything in the <code class=\"docutils literal notranslate\"><span class=\"pre\">/static/</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">/media/</span></code> URL space as\na static file. All other URLs will be served using mod_wsgi:</p>\n<div class=\"code-block\" data-language=\"apache\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Apache</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Apache code\"><code><span class=\"nb\">Alias</span><span class=\"w\"> </span><span class=\"sx\">/robots.txt</span><span class=\"w\"> </span><span class=\"sx\">/path/to/mysite.com/static/robots.txt</span>\n<span class=\"nb\">Alias</span><span class=\"w\"> </span><span class=\"sx\">/favicon.ico</span><span class=\"w\"> </span><span class=\"sx\">/path/to/mysite.com/static/favicon.ico</span>\n\n<span class=\"nb\">Alias</span><span class=\"w\"> </span><span class=\"sx\">/media/</span><span class=\"w\"> </span><span class=\"sx\">/path/to/mysite.com/media/</span>\n<span class=\"nb\">Alias</span><span class=\"w\"> </span><span class=\"sx\">/static/</span><span class=\"w\"> </span><span class=\"sx\">/path/to/mysite.com/static/</span>\n\n<span class=\"nt\">&lt;Directory</span><span class=\"w\"> </span><span class=\"s\">/path/to/mysite.com/static</span><span class=\"nt\">&gt;</span>\n<span class=\"nb\">Require</span><span class=\"w\"> </span><span class=\"k\">all</span><span class=\"w\"> </span>granted\n<span class=\"nt\">&lt;/Directory&gt;</span>\n\n<span class=\"nt\">&lt;Directory</span><span class=\"w\"> </span><span class=\"s\">/path/to/mysite.com/media</span><span class=\"nt\">&gt;</span>\n<span class=\"nb\">Require</span><span class=\"w\"> </span><span class=\"k\">all</span><span class=\"w\"> </span>granted\n<span class=\"nt\">&lt;/Directory&gt;</span>\n\n<span class=\"nb\">WSGIScriptAlias</span><span class=\"w\"> </span>/<span class=\"w\"> </span><span class=\"sx\">/path/to/mysite.com/mysite/wsgi.py</span>\n\n<span class=\"nt\">&lt;Directory</span><span class=\"w\"> </span><span class=\"s\">/path/to/mysite.com/mysite</span><span class=\"nt\">&gt;</span>\n<span class=\"nt\">&lt;Files</span><span class=\"w\"> </span><span class=\"s\">wsgi.py</span><span class=\"nt\">&gt;</span>\n<span class=\"nb\">Require</span><span class=\"w\"> </span><span class=\"k\">all</span><span class=\"w\"> </span>granted\n<span class=\"nt\">&lt;/Files&gt;</span>\n<span class=\"nt\">&lt;/Directory&gt;</span>\n</code></pre></div>\n</section>\n<section id=\"serving-the-admin-files\">\n<span id=\"id3\"></span><h2>Serving the admin files<a class=\"heading-anchor\" href=\"#serving-the-admin-files\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>When <a class=\"reference internal\" href=\"/en/3.1/ref/contrib/staticfiles/#module-django.contrib.staticfiles\" title=\"django.contrib.staticfiles: An app for handling static files.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.staticfiles</span></code></a> is in <a class=\"reference internal\" href=\"/en/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>, the\nDjango development server automatically serves the static files of the\nadmin app (and any other installed apps). This is however not the case when you\nuse any other server arrangement. You’re responsible for setting up Apache, or\nwhichever Web server you’re using, to serve the admin files.</p>\n<p>The admin files live in (<code class=\"file docutils literal notranslate\"><span class=\"pre\">django/contrib/admin/static/admin</span></code>) of the\nDjango distribution.</p>\n<p>We <strong>strongly</strong> recommend using <a class=\"reference internal\" href=\"/en/3.1/ref/contrib/staticfiles/#module-django.contrib.staticfiles\" title=\"django.contrib.staticfiles: An app for handling static files.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.staticfiles</span></code></a> to handle the\nadmin files (along with a Web server as outlined in the previous section; this\nmeans using the <a class=\"reference internal\" href=\"/en/3.1/ref/contrib/staticfiles/#django-admin-collectstatic\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">collectstatic</span></code></a> management command to collect the\nstatic files in <a class=\"reference internal\" href=\"/en/3.1/ref/settings/#std-setting-STATIC_ROOT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">STATIC_ROOT</span></code></a>, and then configuring your Web server to\nserve <a class=\"reference internal\" href=\"/en/3.1/ref/settings/#std-setting-STATIC_ROOT\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">STATIC_ROOT</span></code></a> at <a class=\"reference internal\" href=\"/en/3.1/ref/settings/#std-setting-STATIC_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">STATIC_URL</span></code></a>), but here are three\nother approaches:</p>\n<ol class=\"arabic simple\">\n<li><p>Create a symbolic link to the admin static files from within your\ndocument root (this may require <code class=\"docutils literal notranslate\"><span class=\"pre\">+FollowSymLinks</span></code> in your Apache\nconfiguration).</p></li>\n<li><p>Use an <code class=\"docutils literal notranslate\"><span class=\"pre\">Alias</span></code> directive, as demonstrated above, to alias the appropriate\nURL (probably <a class=\"reference internal\" href=\"/en/3.1/ref/settings/#std-setting-STATIC_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">STATIC_URL</span></code></a> + <code class=\"docutils literal notranslate\"><span class=\"pre\">admin/</span></code>) to the actual location of\nthe admin files.</p></li>\n<li><p>Copy the admin static files so that they live within your Apache\ndocument root.</p></li>\n</ol>\n</section>\n<section id=\"authenticating-against-django-s-user-database-from-apache\">\n<h2>Authenticating against Django’s user database from Apache<a class=\"heading-anchor\" href=\"#authenticating-against-django-s-user-database-from-apache\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django provides a handler to allow Apache to authenticate users directly\nagainst Django’s authentication backends. See the <a class=\"reference internal\" href=\"/en/3.1/howto/deployment/wsgi/apache-auth/\"><span class=\"doc\">mod_wsgi authentication\ndocumentation</span></a>.</p>\n</section>","rootId":"how-to-use-django-with-apache-and-mod-wsgi","toc":[{"title":"Basic configuration","anchor":"basic-configuration","children":[]},{"title":"Using mod_wsgi daemon mode","anchor":"using-mod-wsgi-daemon-mode","children":[]},{"title":"Serving files","anchor":"serving-files","children":[]},{"title":"Serving the admin files","anchor":"serving-the-admin-files","children":[]},{"title":"Authenticating against Django’s user database from Apache","anchor":"authenticating-against-django-s-user-database-from-apache","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"“How-to” guides","url":"/en/3.1/howto/"},{"docname":"howto/deployment/index","title":"Deploying Django","url":"/en/3.1/howto/deployment/"},{"docname":"howto/deployment/wsgi/index","title":"How to deploy with WSGI","url":"/en/3.1/howto/deployment/wsgi/"}],"prev":{"docname":"howto/deployment/wsgi/uwsgi","title":"How to use Django with uWSGI","url":"/en/3.1/howto/deployment/wsgi/uwsgi/"},"next":{"docname":"howto/deployment/wsgi/apache-auth","title":"Authenticating against Django’s user database from Apache","url":"/en/3.1/howto/deployment/wsgi/apache-auth/"},"formats":{"html":"/en/3.1/howto/deployment/wsgi/modwsgi/","markdown":"/en/3.1/howto/deployment/wsgi/modwsgi.md","json":"/en/3.1/howto/deployment/wsgi/modwsgi.json"},"source":"https://github.com/django/django/blob/stable/3.1.x/docs/howto/deployment/wsgi/modwsgi.txt","official":"https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/modwsgi/","inVersions":["dev","6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9","1.8"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}