skip to Main Content

Django – NGINX: deploy your Django project on a production server

DjangoNGINX is a popular and well tested combination used to deploy web applications in production. In this post I will explain the steps needed to have your Django project deployed on a production server using Ubuntu 18.04.

If you are looking for a cheap and powerful cloud provider to host your project I highly suggest DigitalOcean. It is very flexible and powerful, the price is very good for what they offer and you’ll get no surprises on your billing at the end of the month! Join by using this link and you’ll get a 100$ free credit to use in 60 days.

To have DjangoNGINX deployed on your production server follow these simple steps.

1. Install required packages using apt

sudo apt install nginx uwsgi uwsgi-plugin-python3

Why do you need uWSGI? In very simple terms NGINX on its own cannot run a Python process to host your application, for this you’ll need a so called application server that will host a Python process running your Django project. NGINX and uWSGI will “talk” each other using the uwsgi protocol.

2. Create directories for your static and media files

Static files are “not-python” files needed by your Django project, for example Javascript, CSS and images. Media files will be the files uploaded by the users of your application. Not every application will let users upload files, but it’s a very common scenario. Django will not serve static and media files by itself. We’ll leverage NGINX to serve them.

First of all you have to create the directories. Here I assume that you are currently using the user ubuntu with the default home directory /home/ubuntu:

mkdir -p /home/ubuntu/static /home/ubuntu/media
sudo chown www-data.www-data /home/ubuntu/media

The second command will make the user named www-data the owner of the /home/ubuntu/media directory. www-data will be the user running your Python process in uWSGI, and that user should be able to write in the media directory to correctly save user uploaded files.

3. Setup your Django project and install requirements

This step really depends on your particular Django application, for the purpose of this tutorial I will assume that your Django project is installed in the directory /home/ubuntu/django_project/ with the following structure:

├── app1
│   ├──
│   ├──
│   ├── migrations
│   │   └──
│   ├──
│   ├──
│   ├──
└── project
    ├── settings
    │   └──
    │   └──
    │   └──

Also I will assume that you installed all your Python requirements, for example using apt or pip.

I always follow a best practice when starting a new Django project, by splitting the monolithic file in different files, one for each deploy environment (local, test, production, …). You can read a more in depth explanation of this approach if you aren’t used to it.

In our case Django will use the module project/settings/ for his settings. Here we set the STATIC_ROOT and MEDIA_ROOT variables to the directories we created at step 2:

from .base import *

ALLOWED_HOSTS = [ '' ] # customize with your domain name

    'default': { ... } # here the configuration for your database

STATIC_ROOT = '/home/ubuntu/static'
MEDIA_ROOT = '/home/ubuntu/media'

4. Collect static files

Run the following command to collect all static files for your Django project:

./ collectstatic

This command will copy all static files (Javascript, CSS, images) for all your Django apps in the STATIC_ROOT directory configured in For instance /home/ubuntu/static.

5. Configure uWSGI to host your Django project

Create a file named django.ini in the /etc/uwsgi/apps-enabled/ directory. The content of the file should be something like this:

chdir = /home/ubuntu/django_project # customize with your django installation directory
env = DJANGO_SETTINGS_MODULE=project.settings.production # customize with your settings module
wsgi-file = project/ # customize with the relative path to your file
workers = 1

Restart uWSGI with:

service uwsgi restart

You should find the uWSGI logs in /var/log/uwsgi/apps/django.log. Therefore you can check them to see if the Python process started correctly or there are issues.

6. Configure NGINX to serve your application

Create a file named django in the /etc/nginx/sites-enabled/ directory. The content of the file should be something like this:

server {
    listen 80;
    server_name; # customize with your domain name

    location / {
        # django running in uWSGI
        uwsgi_pass unix:///run/uwsgi/app/django/socket;
        include uwsgi_params;
        uwsgi_read_timeout 300s;
        client_max_body_size 32m;

    location /static/ {
       # static files
       alias /home/ubuntu/static/; # ending slash is required

    location /media/ {
        # media files, uploaded by users
        alias /home/ubuntu/media/; # ending slash is required

Restart NGINX with:

service nginx restart

7. Enjoy your Django application

Point the browser to your domain, and you should see your Django application in all of its glory!

8. Extra step: automate all these steps with Ansible!

If you have to manage many different Django projects on many different servers, certainly you’ll find that automating stuff is always a good idea.

Read my post on How to deploy a Django project in 15 minutes with Ansible to automate all the steps described here.


In conclusion, I hope that this post helped you with configuring Django – NGINX to deploy your Django project on a production server. Please let me know if you have questions leaving a comment in the area below or contacting me by email or social account.


Freelance developer and sysadmin

This Post Has 8 Comments
  1. Hi, I do not understand, env = DJANGO_SETTINGS_MODULE=project.settings.production # customize with your settings module, where I get this from I don’t quite understand.
    I thank you in advance

    1. If you started your Django project with:

      django-admin startproject foo

      then you should use:


      I use different settings for different deploy environments, as described here. So in that case the complete Django settings module shoud be:


      for your production environment.

  2. In the nginx configuration, there’s a reference to the socket `unix:///run/uwsgi/app/django/socket`. Where does this come from? Can this be configured somewhere in the uWSGI process description? I’m asking because in my context, there may have several django applications running on the same server.

    Also, what does the `include uwsgi_params;` directive mean?

    1. The socket name corresponds to the file name you put in the /etc/uwsgi/apps-enabled/ directory.

      If your file is named django.ini (as it is in this example) your uwsgi socket will be /run/uwsgi/app/django/socket.

      If your uwsgi configuration file was /etc/uwsgi/apps-enabled/foo.ini, your socket should be in /run/uwsgi/app/foo/socket.

      IIRC this is how the uwsgi package works on Debian based distros.

  3. Hello,

    What if I dont have any domain ? Right now my djagno is installed on EC2 and after starting a temporary server with ( ./ runserver ) I can browse it using my public IP. I just want to browse in the same manner but using nginx. How can I ?

    Please help me

    1. Even if you didn’t assigned a domain yourself, you can use the domain that AWS assigned automatically to your EC2 instance.
      You’ll find it in the instance details on AWS Console. It will be similar to this:

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top