How to deploy a Django application on Ubuntu

Before deploying a Django application, there are several concepts that need to be understood and several decisions that need to be made.

The prerequisites for deploying a Django application are the following:

  • You will need an environment that can run your Django code.
  • You will need an environment that can serve static files.
  • Run some pre-deployment management commands.

For this guide, we will help you deploy a Django app on a single server using NGINX for handling traffic and serving static files and gunicorn to run your Django app.

Setting up the server

First, you need to make sure you have at least Python 3, nginx and postgres installed:

sudo apt update
sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

To check that the dependencies were installed successfully, you can run the following commands:

python --version
sudo service postgresql status
sudo service nginx status

Install the Python dependencies

It is a good practice to keep your dependencies in a requirements.txt file near your code, committed with the rest of the code. To install the dependencies from a requirements file, run the command

pip install -r requirements.txt

or alternatively, you can install your dependencies one by one:

pip install django psycopg2 ...

Creating the PostgreSQL database and user

Before we setup our Django app, we need to make sure we have a database our app will connect to. By default, the PostgreSQL installation comes with a single postgres database, and it is advised to not use it for application specific data. Instead, we should create a new database and add a new user just for Django to connect with:

# connect with the default postgres user created, with no password.
# it is possible to connect with this user only from the same instance the server
# is installed on (so the connection must come from 127.0.0.1)
sudo -u postgres psql

Then, a postgres command prompt will appear, where we can execute SQL statements directly:

CREATE DATABASE mydjangoapp;
CREATE USER djangouser WITH PASSWORD 'securepassword';

Make sure you setup a secure password for your app. Weak credentials can expose your app to hackers.

Then, we need to update some settings for the created user, to follow the recommendations of the Django project

ALTER ROLE djangouser SET client_encoding TO 'utf8';
ALTER ROLE djangouser SET default_transaction_isolation TO 'read committed';
ALTER ROLE djangouser SET timezone TO 'UTC';

Then, we need to give administration permissions to the new account, because Django will use it to manage the tables (create tables, add/remove columns) through migrations.

GRANT ALL PRIVILEGES ON DATABASE mydjangoapp TO djangouser;

After all the steps are completed, we can exit the postgresql command prompt and continue with our setup.

\q

Preparing the Django project

First, we need to bring the code locally. It is highly recommended to use a version control system such as git to manage your app's code. You can use Gitlab or Github to host your code for free.

After you copy your code locally, you'll need to update your <projct_name>/settings.py file to instruct the app to connect to the local postgres database.

Search the DATABASES section of your settings.py and add the following configuration:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'mydjangpapp',
        'USER': 'djangouser',
        'PASSWORD': 'securepassword',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

Then, you need to synchronize the database by running the migrations:

python manage.py makemigrations
python manage.py migrate

Now the database should be initialized with the tables Django needs to function.

Preparing nginx

We need to prepare nginx to serve our static files from Django and proxy the traffic from the user to our app. We could allow the users to connect directly to our Djano app, but having it behind a nginx reverse proxy has several advantages:

  • a single exposed port for serving the Django app traffic and the static files
  • the possibility to scale our Django app horizontally (adding more instances) so we can serve more traffic.

For that, we need to add a new file to the path /etc/nginx/sites-available/mydjangoapp:

server {
    listen 80;
    server_name server_name_or_ip;

    location /static/ {
        root <paht_to_the_project>/static;
    }

    location / {
        include proxy_params;
        proxy_pass http://localhost:8000/;
    }
}

The first location section will serve the static files directly from our application directory, and the second block will forward the traffic directly to our Django application.

There are two more commands you need to run:

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
sudo nginx -t
sudo service nginx restart

Configuring static files from Django

Static files are the kind of files that are sent to the client as they are, without going through Django's views.

You need to update the settings.py file once again to make sure the static files are prefixed correctly:

STATIC_URL = '/static/';
STATICFILES_DIRS = ['media/']

The next step is to gather all the files inside the location specified in STATICFILES_DIRS:

python manage.py collectstatic

This will copy all the static files from the static folders inside each app to one central location, from where nginx will serve them when requested.

Start the Django project

We will use gunicorn for this, so we need to make sure it is installed

pip instsall gunicorn

To start the django application, we will use the command

gunicorn --workers 3 --bind 0.0.0.0:8000 <project_name>.wsgi:application

If your settings.py is inside a directory called myproject, the command will become

gunicorn --workers 3 --bind 127.0.0.1:8000 myproject.wsgi:application

After that, the Django server should have started, and serve traffic at localhost:8000. To check, you can use the curl tool:

curl http://localhost:8000

Check that everything works fine

Now, everything should be up and running. To check that everything is working as expected, you can access in your browser the nginx application at http://SERVER_IP_OR_NAME. Make sure the SERVER_IP_OR_NAME you enter in the browser is the same specified in the server_name section of the nginx configuration. That's how nginx knows how to route the requests, and if the server name doesn't match, your traffic is not being forwarded properly

Note: to do that, the server you use should have a public IP. If not, there is no way to access your application from the internet. Most cloud providers such as AWS, Google Cloud or Scaleway offer public IP addresses for your servers.


We are offering a way to deploy your apps without all the configuration steps, but a single amethyst.yaml file placed in your project.

Deploy your applications in minutes

If you want to be among the first that can use the service, leave us an email and we'll get right back to you when the private beta starts!

Or contact us directly at contact@amethystplatform.com.