Deploying a Django application on Ubuntu

Do you need complete control over your production environment? If so, you might want to skip the Platform as a Service (PaaS) offerings and deploy to your own server instead. This article describes deploying a Django application to an Ubuntu server at Linode.

Using a PaaS like Heroku or Netlify is cool, but using tools like these comes at the cost of flexibility. You can’t choose the firewall you want, and all your data will be stored in the PaaS provider’s database. Additionally, the PaaS provider may not provide support for a particular tool.

There is a way to have flexibility, security, and increased compatibility and integration with other tools: deploy your application to a server.

In this tutorial, I will show you how to get a Linux server from Linode, set it up with the security configuration, and then deploy the Django application. You will be building a lead management application for this tutorial, but if you already have an application, you can skip this step.

You can find the final product on GitHub.


  • An understanding of basic Linux commands.
  • A basic understanding of Django.

Build a Django Application

We will primarily use the Django admin, so the lead management application will only have a model. For authentication, we will use the inbuilt Django authentication system.

Create a folder for your project and enter it using cd to get going. To begin a project and a Django app, enter the following command:

django-admin startproject lead . && python3 startapp app

Now, update the INSTALLED_APPS in the file to include the app you just created.


The Lead model will have the name, email, lead_owner and some other fields that you will see in the following code. The lead_owner file will have a foreign key to the Django user authentication model. Therefore, if we create a superuser, we will be able to use it to create new leads and test the application. Open the file app/ and paste the following code:

from django.db import models
from django.contrib.auth.models import User

class Lead(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(max_length=100, unique=True)
    details = models.CharField(max_length=500, blank=False)
    lead_owner = models.ForeignKey(
        User, related_name="lead", on_delete=models.CASCADE, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

Next, you’ll need to update the file so that you can access the models you just created in the admin panel. You can do this by pasting the following code into the app/

from django.contrib import admin
from .models import Lead

Get an Ubuntu 20.04 Server from Linode

Linode is one of the most popular providers of Linux cloud solutions and services. We will get the Ubuntu 20.04 server we need for this tutorial from them. If you don’t have an account, go ahead and create one, and you will be given a $50 credit to get started with their services.

After authentication, click the “Create Linode" button.

Now, select server configurations based on requirements, but make sure the “Distribution” is Ubuntu 20.04. Vultr has a tutorial on how to generate SSH keys. Then, click the “Create Linode" button.

Your server will run in a minute, and you will be provided with the details of how to access it.

Linux server running

We will connect to the server we just created using Secure Shell (SSH). The SSH protocol provides a secure way to connect to other servers over a network.

To access your remote server, run the following command. Replace root@ with the IP address you were given by Linode.

ssh root@

When asked, “Are you sure you want to continue connecting (yes/no/[fingerprint])?”, type "yes” and press the “Enter” key.

Deploy a Django App to a Remote Server

Deployment, in this case, just means we will copy our Django application folder to a folder on the remote server. We will use the scp (secure copy) command to securely copy the content of the folder that houses the whole application (django-linode-ubuntu). On your local machine, run the command below to copy the application to the remote server. Don’t forget to change in the command below to the IP address of your remote server.

scp -r django-linode-ubuntu root@

The command above first creates a new directory named project in the remote server and then pastes the contents of django-linode-ubuntu.

Set Up a Deployed Application on a Ubuntu Server

In this section, you will do everything necessary to make your application work properly on the remote server. Then, you will be able to access the application on your browser. You will first set up the firewall for network security, use NGINX to reverse host to the IP address of your remote server, and then run your application on the server.

Set Up a Firewall for Network Security

Setting up a firewall on your server provides protection for your server network and sets rules for incoming and outgoing requests to your server. We will use Uncomplicated Firewall (UFW) in this tutorial; it’s easy to set up, and you don't need to install anything new on your server.

UFW comes with Ubuntu by default, but its activity is disabled. You can enable UFW on your server by running the following command:

Note: Make sure that you have SSH into your remote server.

ufw enable

Allow all outgoing ports by running the command below. You can allow all outgoing requests because it doesn’t pose a threat from external sources.

ufw default allow outgoing

Run the command below to prevent access to your server from the outside world.

ufw default deny incoming

When you ran the command above, you also blocked SSH requests. To continue using SSH to access our server, you must enable SSH. To do this, run the following command:

ufw allow ssh

Allow http/tcp traffic on the firewall so that your browser can access your app.

sudo ufw allow http/tcp

Set Up NGINX as a Reverse Proxy

In this section, you will need NGINX for reverse proxy, which allows your server to listen for the application running and then redirect requests to your remote IP address.

To do this, install NGINX by running the following command:

apt-get install nginx

Remove the default configuration file provided by the NGINX installation so that we can create our own.

rm /etc/nginx/sites-enabled/default

Run nano /etc/nginx/sites-enabled/project to create and open a new NGINX configuration file and paste the NGINX script below; then, save the file. The code below will send requests to your IP address at http://localhost:8000 because it is the host where your application will run. If you have a domain name, you can replace the IP address in the script.

        listen 80;

        location / {
                proxy_pass http://localhost:8000;
                include /etc/nginx/proxy_params;
                proxy_redirect off;

Now, restart NGINX to set the new configurations you just created.

sudo systemctl restart nginx

Running the Application

Next, you’ll need to add your IP address to the ALLOWED_HOSTS in the file so that Django can recognize it. We will do this in the server by running the command below to open the file, edit ALLOWED_HOSTS, and then save.

nano project/lead/

Editing file

Django is not installed on the server yet, but you can install it by running the following command:

pip install django==3.2

Now, run the migration commands so that you can create a superuser and start working with the models you created for the application. Make sure that you have inserted cd into the root of your project (/project).

python3 makemigrations && python3 migrate

Create a superuser by running the command below and filling in the prompt:

python3 createsuperuser

Now, you can use the credentials inputted above to access the admin of your application ( Once that is done, you can run your application by running this command:

python3 runserver

You will now be able to access your application with the IP address of your server.

Django application running


In this tutorial, you built a lead management application. Then, you learned how to get a Linux server from Linode, set up the security configuration, set reverse proxy with NGINX, and run your Django application on a server.

You can build on what you’ve learned in this tutorial by going through the Django deployment checklist and trying to find solutions to each of the items.

What to do next:
  1. Try Honeybadger for FREE
    Honeybadger helps you find and fix errors before your users can even report them. Get set up in minutes and check monitoring off your to-do list.
    Start free trial
    Easy 5-minute setup — No credit card required
  2. Get the Honeybadger newsletter
    Each month we share news, best practices, and stories from the DevOps & monitoring community—exclusively for developers like you.
    author photo

    Muhammed Ali

    Muhammed is a Software Developer with a passion for technical writing and open source contribution. His areas of expertise are full-stack web development and DevOps.

    More articles by Muhammed Ali
    Stop wasting time manually checking logs for errors!

    Try the only application health monitoring tool that allows you to track application errors, uptime, and cron jobs in one simple platform.

    • Know when critical errors occur, and which customers are affected.
    • Respond instantly when your systems go down.
    • Improve the health of your systems over time.
    • Fix problems before your customers can report them!

    As developers ourselves, we hated wasting time tracking down errors—so we built the system we always wanted.

    Honeybadger tracks everything you need and nothing you don't, creating one simple solution to keep your application running and error free so you can do what you do best—release new code. Try it free and see for yourself.

    Start free trial
    Simple 5-minute setup — No credit card required

    Learn more

    "We've looked at a lot of error management systems. Honeybadger is head and shoulders above the rest and somehow gets better with every new release."
    — Michael Smith, Cofounder & CTO of YvesBlue

    Honeybadger is trusted by top companies like:

    “Everyone is in love with Honeybadger ... the UI is spot on.”
    Molly Struve, Sr. Site Reliability Engineer, Netflix
    Start free trial
    Are you using Sentry, Rollbar, Bugsnag, or Airbrake for your monitoring? Honeybadger includes error tracking with a whole suite of amazing monitoring tools — all for probably less than you're paying now. Discover why so many companies are switching to Honeybadger here.
    Start free trial
    Stop digging through chat logs to find the bug-fix someone mentioned last month. Honeybadger's built-in issue tracker keeps discussion central to each error, so that if it pops up again you'll be able to pick up right where you left off.
    Start free trial