This guide provides step-by-step instructions for deploying a Django project on a VPS using Gunicorn, Nginx, and PostgreSQL.
It also includes optional setup for auto deployment with GitHub Actions.
- A VPS (Hostinger in this example)
- A Django project on GitHub
- Basic knowledge of Linux commands
ssh-keygen -t ed25519 -C "your_email@example.com"- Leave the passphrase empty.
- Public key:
~/.ssh/id_ed25519.pub→ add to your VPS. - Private key:
~/.ssh/id_ed25519→ store in GitHub Actions repository secretVPS_SSH_KEY.
ssh root@123.123.123.123
⚠️ For security, it’s recommended to create a non-root user for deployment.
curl -LsSf https://astral.sh/uv/install.sh | shAfter installation, run exit and reconnect to your VPS.
sudo mkdir -p /var/www
sudo chown -R $USER:$USER /var/www
cd /var/wwwgit clone https://github.com/prave-com/deploy-django
cd deploy-django
uv sync
source .venv/bin/activatecp .env.example .env
sudo nano .envSet the following:
DEBUG=FalseSECRET_KEY→ generate with:python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'ALLOWED_HOSTS→ your domain or VPS IP
Create service file:
sudo nano /etc/systemd/system/deploy-django.serviceAdd:
[Unit]
Description=Gunicorn instance for Deploy Django
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/var/www/deploy-django
Environment="PATH=/var/www/deploy-django/.venv/bin"
ExecStart=/var/www/deploy-django/.venv/bin/gunicorn --workers 3 --bind unix:/var/www/deploy-django/deploy-django.sock config.wsgi:application
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
⚠️ In this configuration, there isconfig.wsgi:applicationinExecStart. Change theconfigwith your directory name, where thewsgi.pylocated.
Create config file, change example.com with your domain or VPS IP address:
sudo nano /etc/nginx/sites-available/example.comExample configuration:
server {
listen 80;
server_name example.com;
location /static/ {
alias /var/www/deploy-django/staticfiles/;
}
location /media/ {
alias /var/www/deploy-django/media/;
}
location / {
proxy_pass http://unix:/var/www/deploy-django/deploy-django.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Enable the site:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/To enable HTTPS with Let’s Encrypt, if you don't have domain, skip this:
sudo certbot --nginx -d example.comReload Nginx:
sudo systemctl reload nginxIn settings.py:
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"sudo apt install wget ca-certificates -y
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O /etc/apt/trusted.gpg.d/postgresql.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
sudo apt update
sudo apt install postgresql-16 postgresql-client-16 -ysudo -u postgres psqlCREATE DATABASE deploy_django;
CREATE USER deploy_django_user WITH PASSWORD 'your_password';
ALTER ROLE deploy_django_user SET client_encoding TO 'utf8';
ALTER ROLE deploy_django_user SET default_transaction_isolation TO 'read committed';
ALTER ROLE deploy_django_user SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE deploy_django TO deploy_django_user;\c deploy_djangoGRANT ALL ON SCHEMA public TO deploy_django_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO deploy_django_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO deploy_django_user;DB_HOST=localhost
DB_PORT=5432
DB_NAME=deploy_django
DB_USER=deploy_django_user
DB_PASSWORD=your_password
python manage.py migrate
python manage.py collectstatic
python manage.py createsuperuser # optionalsudo systemctl daemon-reload
sudo systemctl enable deploy-django
sudo systemctl start deploy-django-
Add GitHub repository secrets:
VPS_HOST→ VPS IPVPS_USER→ SSH userVPS_SSH_KEY→ private key in your local computer (~/.ssh/id_ed25519)
Add to GitHub repository secrets https://github.com/prave-com/deploy-django/settings/secrets/actions.
-
Generate deploy key:
Paste public key to https://github.com/prave-com/deploy-django/settings/keys.
ssh-keygen -t rsa -b 4096 -C "deploy@deploy-django" -f ~/.ssh/github_deploy_django_rsa
cat ~/.ssh/github_deploy_django_rsa.pub
chmod 600 ~/.ssh/github_deploy_django_rsa- Configure SSH:
sudo nano ~/.ssh/configHost deploy-django
HostName github.com
User git
IdentityFile ~/.ssh/github_deploy_django_rsa
IdentitiesOnly yes
- Update remote repository:
git remote set-url origin git@deploy-django:prave-com/deploy-django.git- Add GitHub to known hosts:
ssh-keyscan github.com >> ~/.ssh/known_hosts- Test connection:
ssh -T git@deploy-django✅ Your Django project should now be running in production on your VPS.