How to Set Up Django with PostgreSQL, Nginx, and Gunicorn on Ubuntu VPS Server

Last updated 1 month ago · 10 min read

Welcome! Today, we will discuss how you can host your website on any VPS server. First of all, before thinking about hosting your website, it's important to know that the website we are hosting today is built using Django. We have already developed our Django website, and we are going to be hosting it on a VPS server. We will set it up to work with the PostgreSQL Database, Nginx server, and Gunicorn on Ubuntu 24.04 (LTS).

What you need before hosting your website

  1. You need a Django website ready to be shipped to production.
  2. Buy a VPS server
  3. Buy your domain name
If you have yet to get your domain name, you can use Dynadot Domains or NameCheap Domains. I will be using Dynadot and Namecheap for this tutorial as I am affiliated with them. And if you don't have your server yet, in this tutorial, we're going to be hosting our website on Linode. However, there are other options like DigitalOcean, Vultr , Namecheap VPS , and even Google Cloud. There are several other great cloud providers, but today, we will walk you through the process using Linode. If you're unsure which VPS server to choose, I recommend checking out our detailed guide on the top 5 VPS servers. Explore the best and most affordable options here - Top 5 VPS Servers. The same steps can be applied on DigitalOcean, Namecheap VPS, Vultr, or any VPS server that provides root access and an IP address. So, without wasting much time, let's dive right in! So, firstly, make sure you have your Django website in a file and keep it organized in a separate folder. Also, have your domain name written down somewhere for easy reference. Now, go to the Linode and create an account. Once you are on your dashboard, click on the Linode and create Linode. Check the pictures below. Select your server location, OS, and OS version, in our case Ubuntu 24.04. Select your Linode plan depending on your use case. Add a label and password for your Linode. Check and recheck everything and scroll down to create Linode. Wait until it's fully booted, you will get an IP address dedicated to your server. Next, grab your new IP address and remember your password. There's also an option to use an SSH key to access your server. However, in this tutorial, we're going to be using our password for simplicity. You can change to SSH keys anytime you want. Our servers are called "Linodes" and on DigitalOcean, the servers are called "Droplets," while on other platforms like Vultr, they are often referred to as "Virtual Machines" (VMs). If you are using Digital Ocean, go to the DigitalOcean create page for your Droplet. This is where you'll set up your server. The same thing applies to other platforms, follow their steps until you have your IP address and password.

Accessing Our Server With an SSH Client

Now, we need to get an SSH client. Some options include PuTTY, or you can even use your command line or PowerShell. There's also a powerful SSH client called MobaXterm. For this tutorial, we will be using MobaXterm. If you don't have MobileXterm installed on your system, head to their website, download it and install it. Use this link Okay, so once you are done with the installation of MobaXterm. Open your MobaXterm application. Click on the Session button, it will pop up a session setting box. Click on SSH and add your IP address in the Remote host field > Check the Specify Name and add root in the field. Trace the ok button below and click it. You will be prompted to enter the password you used while creating your server. Enter the password and hit Enter. Since this is your first time logging into the server, it will prompt you to... It will prompt you, to ask if you want to connect to this server. You can hit Enter. Now we have successfully logged in to our new server, we need to start installing the relevant tools to run our server. In our case, we are setting up the environment to power our Django website. This website will use Nginx as the web server, PostgreSQL as our database, and Python as our programming language. So, we need to install Python, PostgreSQL, and Nginx on the server. First, we have to update our server, let's copy the code below and run it. sudo apt update Then let's type in the following command: sudo apt install python3-dev python3.12-venv libpq-dev postgresql postgresql-contrib nginx curl Let's wait for a moment while all our software is installed. It's time to create our database, let's run the code below: sudo -u postgres psql Now we will be inside the PostgreSQL database. It's time to create our database. CREATE DATABASE mydb; Don't forget to end all the SQL statements with a semicolon, please. We are supposed to create a database user to connect with Django. But in the new Django and PostgreSQL setup, there's a permission error that can restrict you when trying to make migrations from your Django app to the database if you are using a newly created user. So, we are going to skip creating a new user. Instead, we will use the existing "postgres" user, which is the main user of the database. This error doesn't affect the PostgreSQL user but can impact new users created for a database. What we will do is create a password for our PostgreSQL user and use that user as our database user for the Django app. Okay, let's type "\password" and it will prompt us to add a password for the PostgreSQL user. We enter our desired password, confirm it by entering it again, and then hit Enter. Now, our PostgreSQL user has a password.
Now our database user is "postgres" and our password is the new password we created.
Okay, so now it's time to create our Django project. We already have our Django project locally. In MobaXterm, you can't directly upload a folder.
So, let's start the Django project again here.
We need to move to the root directory of our Ubuntu server. Then, create a home folder if it doesn't already exist. cd /.. Will move use to the root directory. mkdir home to create our home folder.

Note: the command cd (change directory) is used to navigate the command line interface. If you want to move one-inch backward use "cd ..", to move frontward use cd then the name of the available folder Ex: "cd home" or "cd home/mywebsite", but make sure the folder(s) exist there before trying to move to it. You can check the available folders with "ls" command. You can also move to the root directory one touch using the "cd /.." command.

Now we have created our home and project folder, let's create our virtual environment. python3 -m venv myvitname
Let's wait for a moment. Once the virtual environment is created, we need to activate it. source myvitname/bin/activate
Once we've activated our virtual environment, it's time to install some packages. We need Django, Gunicorn, Psycopg, pillow, etc. pip install django gunicorn psycopg[binary] pillow Now is the time to create our Django project. django-admin startproject mynewproject Once you have created your Django project, move straight to the settings.py and open it.
MobaXterm has a file editor, you can use that to edit your files or right-click on the file and select "open with" It will show you multiple options, and you can select VS code.
Now, remember your domain name and your IP address. In the settings.py file, you'll find the "ALLOWED_HOSTS" section. You may have omitted this in your local development environment, but now it's time to fill that in for your Django project.
In the "ALLOWED_HOSTS," add the domain name you bought from Dynadot or Namecheap. Include both the www version and the non-www version. Our domain will not work yet, but let's have them there, for now, only the IP address will work at this point.
Then, copy the IP address from your server and add it to the list. If you fail to add all of them to the list Django will not allow them to serve your website. So we also need to add localhost to our list since our PostgreSQL database is available on our local server.
This is how our ALLOWED_HOST will look like: ALLOWED_HOSTS = ['18.28.00.15', 'withubb.com', 'www.withubb.com', 'localhost'] Let's move down to the place where we have the database settings, it has sqlite3 database by default change it to our PostgreSQL database. DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": "mydatabase", "USER": "mydatabaseuser", "PASSWORD": "mypassword", "HOST": "localhost", "PORT": "", } } Scroll down to where we have the media and static root and add the configuration below so Django can serve your static and media root. STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'static/' MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'mediafiles/' Run the following commands to create the initial migrations and apply them to your PostgreSQL database: python manage.py makemigrations python manage.py migrate To create an admin user, run: python manage.py createsuperuser You will be prompted to enter a username, email, and password. Gather all static content by running: python manage.py collectstatic Confirm the operation when prompted, and the static files will be placed in the `static` directory. Enable your fire wall and allow traffic on port 8000 to test the development server: sudo ufw allow 8000 sudo ufw enable Test your project by starting the development server: python manage.py runserver 0.0.0.0:8000 Visit your server's IP or domain followed by `:8000. For the admin interface, append `/admin` to the URL and log in using your admin credentials. Test Gunicorn's ability to serve your project, move to the project and run: gunicorn --bind 0.0.0.0:8000 mywebsite.wsgi The admin interface will not have styling at this point, as Gunicorn doesn't serve static files. Press `CTRL+C` to stop the server. Exit your virtual environment by typing: deactivate To automate Gunicorn startup, create a systemd socket and service: Create the socket file: sudo nano /etc/systemd/system/gunicorn.socket Add the following: [Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target Next, create the service file: sudo nano /etc/systemd/system/gunicorn.service Add this content: [Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=root Group=www-data WorkingDirectory=/home/mywebsite/ ExecStart=/home/mywebsite/myvitname/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ mywebsite.wsgi:application [Install] WantedBy=multi-user.target Enable and start the Gunicorn socket: sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socket Verify the gunicorn socket is active: sudo systemctl status gunicorn.socket To use Nginx as a reverse proxy, create a server block: sudo nano /etc/nginx/sites-available/mywebsite Add the following: server { server_name mywebsite.com, www.mywebsite.com, my_server_IP; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/mywebsite/mywebsite ; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } } Enable the configuration: sudo ln -s /etc/nginx/sites-available/mywebsite /etc/nginx/sites-enabled sudo nginx -t sudo systemctl restart nginx ufw is our firewall, you need to check the status first: sudo ufw status If inactive, you need to enable it and add rules so you don't lock yourself out. sudo ufw enable It will prompt you if you want to override existing rules, input Y, and enter. Open port 80 for Nginx and remove the development server rule: sudo ufw delete allow 8000 sudo ufw allow openSSH sudo ufw allow 'Nginx Full'

At this stage, your application should be live and accessible via your server's domain or IP address. You've done an amazing job following along! In the next chapter, we'll cover advanced Nginx configurations, securing your website with Certbot's free SSL certificate, and setting up DNS records for your domain name.

More Articles

10 Coding Projects to Elevate Your Portfolio

Top 10 Coding Projects to Elevate Your Portfolio

2 days, 20 hours ago · 8 min read
Top 7 Programming Languages to Learn for Web Development

7 best programming Languages to Learn in 2024

5 days, 15 hours ago · 6 min read
Essential tools for building a responsive business website

5 essential tools for building a responsive business website

5 days, 15 hours ago · 5 min read
Website development trends you cannot ignore in 2024

Top 10 website development trends 2024

2 weeks, 2 days ago · 10 min read
Steps to Designing a Website for a Small Business on a Budget

How to Design a Website for a Small Business on a Budget

2 weeks, 2 days ago · 7 min read
Remote vs. Non-Remote Jobs: Which is Best for You?

Remote vs. Non-Remote Jobs: Which is Best for You?

3 weeks, 1 day ago · 9 min read
20 different types of websites with examples

Types of websites with examples

4 weeks, 2 days ago · 10 min read
Top 5 best and cheapest VPS server

Top 5 best cheapest and fastest VPS hosting providers

1 month ago · 7 min read
Top 15 E-commerce Platforms for Building Your Business

Best E-commerce platforms for business websites in 2024

1 month ago · 14 min read
Top 5 Web Design Tools for Professionals in 2024

Web Design Tools for Professionals in 2024

1 month ago · 6 min read