Overview
In this guide, we’ll walk through the complete process of deploying a Django application on a VPS using Gunicorn as the application server and Nginx as the reverse proxy. You’ll learn how to configure your server, set up Gunicorn to serve your Django project, and use Nginx to handle client requests efficiently. By the end, you’ll have a production-ready setup that is secure, scalable, and optimized for performance.
Prequisities
Have your project pushed to GitHub/GitLab or any other version control platform. I will include GitHub for this post; the configuration is relevant for all of the platforms.
1. Install required packages
We will require Python to be installed on the server, along with pip to manage Python packages. The venv Python package is a virtual environment management tool that allows us to configure an isolated environment for our project.
sudo apt update
sudo apt install python3 python3-pip python3-venv nginx git2. Clone Your Django Project using SSH
Generate SSH Key: This creates two files:
~/.ssh/github(private key) and~/.ssh/github.pub(public key)
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/github
#It wil ask for passphrase: Enter a secure passphrase (optional but recommended)Start the SSH Agent and Add the Key.
# Start the ssh-agent
eval "$(ssh-agent -s)"
# Add your custom-named SSH key to the agent
ssh-add ~/.ssh/githubCopy Your Public Key
cat ~/.ssh/github.pubAdd the Public key to GitHub: Go to the GitHub settings, find SSH and GPG keys in the sidebar, add a new SSH Key, and paste the public key. Ensure you paste without hitting Enter and save it.
Configure SSH for GitHub in VPS.
# Create/edit SSH config
nano ~/.ssh/configAdd this configuration to it.
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github
IdentitiesOnly yesSet Permissions to the SSH files
chmod 600 ~/.ssh/github
chmod 644 ~/.ssh/github.pub
chmod 600 ~/.ssh/configClone the project with GitHub SSH.
cd /var/www/
sudo git clone [email protected]:yourusername/yourproject.git
# Give ownership of the directory to the current user.
sudo chown -R $USER:$USER yourproject3. Create a Virtual Environment & Install Dependencies
cd yourproject
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt4. Configure Django for Production
# In settings.py
DEBUG = False
ALLOWED_HOSTS = ['your_domain.com', 'www.your_domain.com']# Migrate the migration files
python manage.py migrate# Configure to serve the Static and Media files
STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/yourproject/staticfiles'
MEDIA_URL = '/media/'
MEDIA_ROOT = '/var/www/yourpoject/media'# Collect static
python manage.py collectstatic5. Install & Configure Gunicorn
pip install gunicorn
gunicorn --bind 0.0.0.0:8000 yourproject.wsgiIf it’s served successfully, check it on the browser ip:8000, then press Ctrl + C If it’s working properly.
6. Create Gunicorn Systemd Service
sudo nano /etc/systemd/system/gunicorn.service[Unit]
Description=Gunicorn daemon for a Django project
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/yourproject
ExecStart=/usr/bin/gunicorn --access-logfile - --workers 3 --bind unix:/var/www/yourproject/gunicorn.sock yourproject.wsgi:application
[Install]
WantedBy=multi-user.targetEnable and start service:
sudo systemctl enable gunicorn
sudo systemctl start gunicorn
sudo systemctl daemon-reload7. Nginx Configuration
File: /etc/nginx/sites-available/your_domain.com
server {
listen 80;
server_name your_domain.com www.your_domain.com;
# Static files
location /static/ {
alias /var/www/youproject/collect_static/;
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Media files
location /media/ {
alias /var/www/yourproject/media/;
}
location / {
include proxy_params;
proxy_pass http://unix:/var/www/yourproject/gunicorn.sock;
}8. Fix Socket Permissions
When running Gunicorn with Nginx, the correct user must have ownership and access to the project directory and the socket file it creates. By default, Nginx runs under the www-data user on Ubuntu/Debian systems.
sudo chown -R www-data:www-data /var/www/yourproject/
sudo chmod 770 /var/www/yourproject/9. Enable the site and reload Nginx
sudo ln -s /etc/nginx/sites-available/your_domain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx10. Set Up SSL (HTTPS)
To enable HTTPS, you need to obtain an SSL certificate, which can be issued for free via Let’s Encrypt.
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your_domain.com -d www.your_domain.comAuto-renew certificate
sudo systemctl enable certbot.timer11. Access the Site
Enter the domain your_domain.com in the browser and check if everything works perfectly.
For any issues that occur, check the error log of Nginx
sudo tail -n 30 /var/log/nginx/error.logIf static files are not working, ensure the permission that Nginx has permission to access the files.
sudo chown -R www-data:www-data /var/www/yourproject/staticfiles
sudo chmod -R 755 /var/www/yourproject/staticfilesHappy Coding.