Author: Daniel Marsh | Published: April 2, 2023
Introduction
Welcome to the tutorial on setting up a Django project on a remote server with Gunicorn and Nginx. In this step-by-step guide, we will walk you through the process of deploying a Django application on a Linux server, configuring Gunicorn as the application server, and using Nginx as a reverse proxy to handle client requests.
Throughout the tutorial, we will provide you with specific instructions and commands to be executed on your server. Please make sure to replace the placeholder values enclosed in quotation marks with the relevant information specific to your project and environment.
By following this tutorial, you will learn how to create a new user with sudo privileges, set up a basic firewall, clone a Git repository, install required packages, create a PostgreSQL database and user, create a Python virtual environment, perform the initial project setup, test the project with Gunicorn, configure systemd socket and service files, test socket activation, configure Nginx to proxy pass to Gunicorn, and secure Nginx with Let's Encrypt for HTTPS.
Whether you are a beginner or an experienced developer, this tutorial will provide you with the necessary steps to deploy your Django project in a production environment, ensuring scalability, security, and reliability.
So, let's get started with the first step: creating a user with sudo privileges.
NOTE - Throughout this tutorial, you will encounter specific words enclosed in quotation marks. It is important that you substitute these words with the appropriate information relevant to your situation. The following words require replacement:
Step 1 – Login as root and create a user with sudo privileges.
Note: Replace "your_username" with your desired username.
adduser "your_username"
usermod -aG sudo "your_username"
Explanation: This step creates a new user with administrative privileges.
Step 2 – Set up a basic firewall.
ufw allow OpenSSH
ufw enable
Explanation: This step allows incoming SSH connections and enables the firewall to secure your server.
Step 3 – Clone your git repo and create a deploy key.
Change from the root user to the user you just created.
sudo su - "your_username"
Create the new SSH key.
Note: Replace "your_email@example.com" with your GitHub email.
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
Now add the public key to your GitHub repository's deploy keys. You can view the key using the following command:
sudo cat /home/"your_username"/.ssh/id_rsa.pub
Now clone the repo.
git clone git@github.com:username/repository.git
Explanation: This step sets up SSH authentication for accessing your Git repository and clones the repository to your server.
Step 4 – Install all required packages from Ubuntu Repositories.
sudo apt update
apt list --upgradable
sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl
Explanation: This step updates the package lists, installs Python, PostgreSQL, Nginx, and other necessary packages.
Step 5 – Create the PostgreSQL Database and User.
Note: Replace "your_project" with your project's name and "your_project_user" with your desired project username.
sudo -u postgres psql
CREATE DATABASE "your_project";
CREATE USER "your_project_user" WITH PASSWORD 'password';
ALTER ROLE "your_project_user" SET client_encoding TO 'utf8';
ALTER ROLE "your_project_user" SET default_transaction_isolation TO 'read committed';
ALTER ROLE "your_project_user" SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE "your_project" TO "your_project_user";
\q
Explanation: This step creates a new PostgreSQL database and user for your Django project.
Step 6 – Create a Python virtual environment and install all required Python packages.
sudo -H pip3 install --upgrade pip
sudo -H pip3 install virtualenv
cd "your_projectdir"
virtualenv "your_projectenv"
source "your_projectenv"/bin/activate
pip install django gunicorn psycopg2-binary
pip install -r requirements.txt
Explanation: This step creates a virtual environment for your project, activates it, and installs Django, Gunicorn, and other required Python packages.
Step 7 – Complete the initial project setup.
Make the initial migrations to your new database.
python manage.py makemigrations
python manage.py migrate
Create a superuser for your project's admin login.
python manage.py createsuperuser
Collect all static content into one directory.
python manage.py collectstatic
Test that the project will run.
sudo ufw allow 8000
python manage.py runserver 0.0.0.0:8000
In your web browser, visit your server's domain name or IP address followed by ":8000".
http://server_domain_or_IP:8000
Explanation: This step performs the initial setup for your Django project, including database migrations, creating a superuser, and testing the server.
Step 8 – Test if Gunicorn can serve the project.
gunicorn --bind 0.0.0.0:8000 "your_project".wsgi
In your web browser, visit your server's domain name or IP address followed by ":8000".
http://server_domain_or_IP:8000
You can now exit the Python virtual environment.
deactivate
Explanation: This step tests if Gunicorn is able to serve your Django project and deactivates the virtual environment.
Step 9 – Creating systemd Socket and Service Files for Gunicorn.
Start by creating and opening a systemd socket file for Gunicorn with sudo privileges in your preferred text editor.
sudo nano /etc/systemd/system/gunicorn.socket
Inside, create a [Unit] section to describe the socket, a [Socket] section to define the socket location, and an [Install] section to make sure the socket is created at the right time.
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Next, create and open a systemd service file for Gunicorn with sudo privileges. The service filename should match the socket filename with the exception of the extension.
sudo nano /etc/systemd/system/gunicorn.service
Once the file has opened, add the following, making sure to change the details to match your setup.
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User= "your_username"
Group=www-data
WorkingDirectory=/home/"your_username"/"your_projectdir"
ExecStart=/home/"your_username"/"your_projectdir"/"your_projectenv"/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
"your_project".wsgi:application
[Install]
WantedBy=multi-user.target
Next, start the Gunicorn socket. This will create the socket file at /run/gunicorn.sock now and at boot.
sudo systemctl start gunicorn.socket
Then enable it so that when a connection is made to that socket, systemd will automatically start the gunicorn.service to handle it.
sudo systemctl enable gunicorn.socket
Explanation: This step sets up systemd socket and service files to manage Gunicorn as a system service.
Step 10 – Test the Socket activation.
sudo systemctl status gunicorn
To test the socket activation mechanism, send a connection to the socket through curl.
curl --unix-socket /run/gunicorn.sock localhost
You should receive the HTML output from your application in the terminal. This confirms that Gunicorn was started and able to serve your Django application.
sudo systemctl daemon-reload
Then restart the Gunicorn process.
sudo systemctl restart gunicorn
Explanation: This step tests the socket activation mechanism and restarts Gunicorn.
Step 11 – Configure Nginx to proxy pass to Gunicorn.
sudo nano /etc/nginx/sites-available/"your_domain"
Once the file opens, add the following, making sure to edit the details to match your own.
server {
listen 80;
server_name "your_server_IP" "your_domain" "www.your_domain";
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/"your_username"/"your_projectdir";
}
location /media/ {
root /home/"your_username"/"your_projectdir";
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
Save and close the file when you are finished. Now, you can enable the file by linking it to the sites-enabled directory.
sudo ln -s /etc/nginx/sites-available/"your_domain" /etc/nginx/sites-enabled
Test your Nginx configuration for syntax errors.
sudo nginx -t
If no errors are reported, go ahead and restart Nginx.
sudo systemctl restart nginx
Since you no longer need access to the development server, adjust your firewall settings by removing the rule to open port 8000.
sudo ufw delete allow 8000
Then allow normal traffic on ports 80 and 443, thereby allowing HTTP and HTTPS connections, respectively, with the following command.
sudo ufw allow 'Nginx Full'
You should now be able to go to your server's domain or IP address to view your application.
Step 12 – Secure Nginx with Let's Encrypt.
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
sudo certbot --nginx -d "your_domain" -d "www.your_domain"
sudo certbot renew --dry-run
Explanation: This step installs Let's Encrypt to obtain SSL certificates for your domain and secures Nginx with HTTPS.
Consclusion
Congratulations! You have successfully completed the tutorial on deploying a Django project with Gunicorn and Nginx on a remote server. By following the step-by-step instructions, you have learned essential concepts and commands to set up a robust production environment for your Django application.
Throughout the tutorial, you have created a new user with sudo privileges, set up a basic firewall, cloned your Git repository, installed necessary packages, created a PostgreSQL database and user, created a Python virtual environment, performed the initial project setup, tested the project with Gunicorn, configured systemd socket and service files, tested socket activation, configured Nginx as a reverse proxy, and secured Nginx with Let's Encrypt for HTTPS.
By deploying your Django project using Gunicorn and Nginx, you have achieved improved performance, scalability, and security. Gunicorn acts as a high-performance web server to handle incoming requests, while Nginx acts as a reverse proxy to efficiently distribute those requests and serve static files. Additionally, you have secured your application with SSL certificates from Let's Encrypt, enabling encrypted communication between clients and your server.
With your Django application now deployed in a production environment, you can confidently handle increased traffic, provide a seamless user experience, and ensure the stability and reliability of your application.
Remember, as your project evolves, you may need to revisit certain configurations or explore additional optimizations specific to your requirements. However, this tutorial has provided you with a strong foundation to build upon.
We hope this tutorial has been valuable to you, and we encourage you to continue exploring Django's powerful features and the vast possibilities it offers for web development.
Happy coding!
CodeBlock - Empowering Your Digital Presence