Skip to content

Instantly share code, notes, and snippets.

@michael-halim
Last active March 15, 2023 06:05
Show Gist options
  • Save michael-halim/fa9bceddd559ea8c77301f2317419859 to your computer and use it in GitHub Desktop.
Save michael-halim/fa9bceddd559ea8c77301f2317419859 to your computer and use it in GitHub Desktop.
Deploy Django with PostgreSQL on Virtual Private Server (Ubuntu 22.10) Using Gunicorn and Nginx

Version

  • Ubuntu 22.10
  • Django 4.1.2
  • Gunicorn 20.1.0
  • Nginx 1.22.0 (Ubuntu)
  • PostgreSQL 14.7

References

# Login to VPS
ssh <username>@<ip_address>

# Get All Dependencies
sudo apt update
sudo apt upgrade

# Install Dependencies
sudo apt-get install python3-pip
sudo apt-get install postgresql postgresql-contrib
cd /home/<user>
git clone <repo_name>
cd /home/<user>/<repo_name>
sudo pip3 install -r requirements.txt
sudo apt-get install libpq-dev python3-dev

# Change User to 'postgres' because PostgreSQL has default username 
sudo -i -u postgres

# Open PostgreSQL and Change Password (Must Do This for Security Purposes)
psql
CREATE DATABASE <db_name>;
ALTER USER postgres WITH PASSWORD '<new_password>';
exit

# Apply Migrations and Migrate
cd /home/<user>/<repo_name>
python3 manage.py makemigrations
python3 manage.py migrate

# Change PostgreSQL Settings to Open Remotely from 3rd Party App like pgAdmin, HeidiSQL, etc
# /14/ is depends on the version of PostgreSQL
echo "
host 	all		all		0.0.0.0/0		md5
host	all		all		 ::/0	      md5
" | sudo tee -a /etc/postgresql/14/main/pg_hba.conf

# Change Listen Addresses in /etc/postgresql/14/main/postgresql.conf to '*'
nano /etc/postgresql/14/main/postgresql.conf
listen_addresses = '*'

# Connect to Gunicorn
cd /home/<user>/<repo_name>/
gunicorn --bind 0.0.0.0:80 hybridrecsys.wsgi
sudo mkdir /var/log/gunicorn

# Add Gunicorn Socket
echo "
[Unit]
Description=gunicorn socket
   
[Socket]
ListenStream=/run/gunicorn.lock

[Install]
WantedBy=sockets.target
" | sudo tee -a /etc/systemd/system/gunicorn.socket

# Add Gunicorn Service
echo "
[Unit]
Desciption=gunicorn daemon
After=network.target

[Service]
User=root
Group=www-data
WorkingDirectory=/home/<user>/<repo_name>
ExecStart=/usr/local/bin/gunicorn \
    	   --access-logfile - \
	       --workers 3 \
	        --bind unix:/run/gunicorn.sock \
	        hybridrecsys.wsgi:application

[Install]
WantedBy=multi-user.target
" | sudo tee -a /etc/systemd/system/gunicorn.service

# Start Gunicorn Socket
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

# Check Gunicorn Socket Status
sudo systemctl status gunicorn.socket

# Check Gunicorn Log if There's Error
sudo journalctl -u gunicorn

# Connect to Nginx
sudo apt-get install nginx
cd /home/<user>/<repo_name>
python3 manage.py collectstatic

# Add Settings in Nginx
echo "
server {
    listen 80;
    server_name <ip_address>;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /staticfiles/ {
        root /home/<user>/<repo_name>;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
} " | sudo tee -a /etc/nginx/sites-available/hybridrecsys

# Check Nginx Status (Must Print Out 'ok' and 'successful')
sudo ln -s /etc/nginx/sites-available/hybridrecsys /etc/nginx/sites-enabled
sudo nginx -t

# Restart Nginx 
sudo systemctl restart nginx

# Allow Firewall Nginx
sudo ufw allow 'Nginx Full'

# Domain Settings (Skip This Part If You Have No Domain)
echo "
server {
    listen 80;
    server_name <domain_name>.com www.<domain_name>.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /staticfiles/ {
        root /home/<user>/<repo_name>;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
} " | sudo tee -a /etc/nginx/sites-available/<main_django_folder>

# Add Domain in your VPS provider
add record <domain_name>.com
add record @ => <domain_name>.com
add record www => <domain_name>.com

# Add DNS Record in your Domain Provider 
Name = @
Type = A
TTL  = 14400
RDATA = <ip_address>

# Create SSL Certificate (to change HTTP to HTTPS)
sudo apt-get install python3-certbot-nginx
sudo certbot --nginx -d <domain_name>.com -d www.<domain_name>.com

If There Are Changes in Your Django Folder, Refresh Using This

# Copy all 3 and pasted
sudo systemctl daemon-reload
sudo systemctl restart gunicorn
sudo nginx -t && sudo systemctl restart nginx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment