Serve with Apache and mod_wsgi¶
The development server (
manage.py runserver) is not suitable for production.
We describe here how to serve the Python backend with Apache and mod_wsgi:
mod_wsgi-express start-server varmed/wsgi.py \ --port=8887 \ --user <USERNAME> \ --server-root=./mod_wsgi-server \ --processes 2 --threads 5 \ --queue-timeout 60 --request-timeout 90
<USERNAME> is to be replaced by your own user name.
One is free to change the port number, processes and threads, or timeouts
specified in the command above.
It will behave then as a mini Apache serving locally at
Test that it works:
You can enter
http://127.0.0.1:8887/varappin your browser’s address bar and it should answer “Hello World!”. This is the URL that the frontend will call to fetch data from the server.
“varmed/wsgi.py” contains the configuration for this step, and tells the app where to find the settings file. If the settings file was moved or renamed, you must edit “varmed/wsgi.py” or set DJANGO_SETTINGS_MODULE accordingly.
“–server-root” is the directory where the wsgi/httpd configuration will be written, along with Apache control executables.
For more details, see Developer notes.
A few settings (in “varmed/settings/settings/py”) have to be changed for security:
DEBUG = False
- Change the
Typically, the settings file specific to the environment should be written and stored externally, then copied into the module before the installation to overwrite the current one.
To change settings once the app is already up and running, reinstall and restart the wsgi server:
python3 setup.py install ./mod_wsgi-server/apachectl restart
We are interested in the user/machine specific Apache config file,
commonly called httpd.conf, often located in
/etc/httpd/ or in the
N.B. mod_wsgi-express generated another one that should not be edited direcly (it would be overwritten anyway).
Here is our development config (shortened), given as example:
<VirtualHost *:80> ServerAdmin admin_name DocumentRoot /var/www/html/varapp ServerName varapp-demo.vital-it.ch ProxyPass /backend http://localhost:8887/varapp ProxyPassReverse /backend http://localhost:8887/varapp <Directory "/var/www/html/varapp"> AllowOverride All Options FollowSymLinks Order allow,deny Allow from all </Directory> </VirtualHost>
Then restart Apache:
sudo /etc/init.d/httpd restart
Depending on your system, it may be different, like
/sbin/service httpd restart, or
The ProxyPass lines are the common way to redirect
(e.g. varapp-demo.vital-it.ch/backend) to
the local wsgi server (that the client cannot access directly otherwise).
Using HTTPS (SSL)¶
Now the client accesses to Varapp through an Apache proxy. The backend itself is not reachable from the outside. Since the communication between Apache and the backend is local, it is usually not necessary to secure this communication. However, we need to encrypt data between the client and the Apache proxy.
Using SSL requires to have a certificate. The best way is to buy an official one. You can also use a self-signed certificate, but this will warn every user on first connection that they might be at risk, until they accept to make an exception in their browser. Until then, CURL will also fail with a ERR_INSECURE_RESPONSE error (use -k option when testing to bypass it).
- Add a new VirtualHost similar as above, but replacing
- Add SSL options and certificate to the config.
- Keep the ProxyPass lines just as they were before.
You config then should look like this:
<IfModule mod_ssl.c> <VirtualHost *:443> ... SSLEngine on SSLCertificateFile .../varapp.crt SSLCertificateKeyFile .../varapp.key ... ProxyPass /backend http://localhost:8887/varapp ProxyPassReverse /backend http://localhost:8887/varapp ... </VirtualHost> </IfModule>
- Edit the
BASE_URLin the settings to point to the new HTTPS address.
- Edit the
BACKEND_URLin the frontend’s
app/conf/conf.jsto point to the new HTTPS address.
I you really want to use HTTPS between Apache and the local Django backend, you will have to add a Strict-Transport-Security header in Apache, and look at Django docs to configure it in its settings.