If you develop your project on Django, then you probably know that you need a web server like nginx to serve your static files: images, stylesheets and so on. While Django has its own ability to serve static files, you should use it only during development. In this guide you will learn how to install and configure all software required to serve your Python Django/Flask application.
Why should you use Nginx and Gunicorn
You need a web server. Django’s builtin “staticfiles” app is not suitable for production use. As mentioned in the official documentation regarding staticfiles view:
[…] this view is grossly inefficient and probably insecure. This is only intended for local development, and should never be used in production.
Source: docs.djangoproject.com
You might wonder, why to choose Nginx over Apache. The answer is simple — security and speed.
The next thing you need is a WSGI server. It’s a program, which turns your project into a real website. This is achieved by multithreading your application so it is able to process several requests at the same time. Also, it serves the app on the local port or Unix domain socket. We will use the latter case.
I tried a lot of WSGI servers and figured out that Gunicorn is the best choice. So, when you know what tech stack you will use, you can proceed to installation.
Setting up Nginx
First, update your package lists. Then install Nginx.
sudo apt update sudo apt install nginx
Next, configure your website. Write this to /etc/nginx/sites-available/website
(where “website” is the name of your website). I assume you have directory website
which contains your website in the home directory of the user named bob
. /run/gunicorn.sock
is a path to the Gunicorn socket you will create later on.
server { server_name example.com; location = /favicon.ico { access_log off; alias /home/bob/website/static/icons/favicon.ico; } location /icons/ { alias /home/bob/website/static/icons/; } location /static/ { root /home/bob/website/; } location / { rewrite ^([^.]*[^/])$ $1/ permanent; include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } listen 80; }
Enable your website by creating symbolic link from sites-available/website
to sites-enabled/website
:
sudo ln -sf /etc/nginx/sites-{available,enabled}/website
We used bash expansion here. You could write the command above as follows: sudo ln -sf /etc/nginx/sites-available/website /etc/nginx/sites-enabled/website
Optionally, you can also remove the default “It works” page from enabled websites. It is recommended to do this in production environment:
.sudo rm /etc/nginx/sites-enabled/default
Installing and configuring Gunicorn
Go to the directory of your website and activate the virtual environment:
cd /home/bob/website/ . venv/bin/activate
You could use source
command instead of dot. Next, install the Gunicorn WSGI HTTP server:
pip install gunicorn
Next, write the following to /etc/systemd/system/gunicorn.socket
to create a Systemd unit for the Gunicorn socket:
[Unit] Description=Gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target
Save the file. Next, write the follwing to /etc/systemd/system/gunicorn.service
to create a service. Replace “bob” with your username. Also, replace “website” with your project name and paths with your apps paths.
[Unit] Description=Gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=bob Group=www-data WorkingDirectory=/home/bob/website/ ExecStart=/home/bob/website/venv/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ website.wsgi:application [Install] WantedBy=multi-user.target
Enabling and starting the services
The configuration process is almost completed. Now you need to add Nginx and Gunicorn to system autostart. Use --now
option to start them now.
sudo systemctl enable --now gunicorn sudo systemctl enable --now nginx
Check if it works by visiting you website. You should see your app. If not, run these commands:
sudo systemctl daemon-reload sudo systemctl restart gunicorn.socket gunicorn.service sudo systemctl restart nginx
To see status of the website, run systemctl status gunicorn
Summary
Now you know how to setup your Python web application for production use. I did not include the Django settings.py
configuration, you should do it by referring to official documentation on this topic. To setup Nginx and Gunicorn for Python Django web project, you need to do this:
- Install and configure Nginx to serve static files.
- Install Gunicorn, configure systemd unit and socket to multithread your app to improve performance.
- Enable and start Gunicorn and Nginx.