Skip to content

Instantly share code, notes, and snippets.

@royz
Forked from bradtraversy/django_deploy.md
Last active August 21, 2020 19:03
Show Gist options
  • Save royz/53cf3f50025c8c67495bca9bf21a3fde to your computer and use it in GitHub Desktop.
Save royz/53cf3f50025c8c67495bca9bf21a3fde to your computer and use it in GitHub Desktop.
Django Deployment - Digital Ocean

Django Deployment to Ubuntu 20.04

These steps should work on any previous or future version of ubuntu as well

Software

Update packages

# sudo apt update
# sudo apt upgrade

Install Python 3, Postgres & NGINX

# sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

Postgres Database & User Setup

# sudo -u postgres psql

You should now be logged into the pg shell

Create a database

CREATE DATABASE <db-name>;

Create user

CREATE USER <db-admin-name> WITH PASSWORD <db-admin-password>;

Set default encoding, tansaction isolation scheme (Recommended from Django)

ALTER ROLE <db-admin-name> SET client_encoding TO 'utf8';
ALTER ROLE <db-admin-name> SET default_transaction_isolation TO 'read committed';
ALTER ROLE <db-admin-name> SET timezone TO 'UTC';

Give User access to database

GRANT ALL PRIVILEGES ON DATABASE <db-name> TO <db-admin-name>;

Quit out of Postgres

\q

Vitrual Environment

You need to install the python3-venv package

# sudo apt install python3-venv

Create project directory

# mkdir pyapps
# cd pyapps

Create venv

# python3 -m venv ./venv

Activate the environment

# source venv/bin/activate

Git & Upload

Pip dependencies

From your local machine, create a requirements.txt with your app dependencies. Make sure you push this to your repo

$ pip freeze > requirements.txt

Create a new repo and push to it (you guys know how to do that)

Clone the project into the app folder on your server (Either HTTPS or setup SSH keys)

# git clone https://github.com/<github-username>/<project-name>.git

Install pip modules from requirements

You could manually install each one as well

# pip install -r requirements.txt

Local Settings Setup

Add code to your settings.py file and push to server

try:
    from .local_settings import *
except ImportError:
    pass

Create a file called local_settings.py on your server along side of settings.py and add the following

  • SECRET_KEY
  • ALLOWED_HOSTS
  • DATABASES
  • DEBUG
  • EMAIL_*

Run Migrations

# python manage.py makemigrations
# python manage.py migrate

Create super user

# python manage.py createsuperuser

Create static files

python manage.py collectstatic

Run Server on port 8000 for testing

# python manage.py runserver 0.0.0.0:8000

Test the site at YOUR_SERVER_IP:8000

Add some data in the admin area

Gunicorn Setup

Install gunicorn

# pip install gunicorn

Add to requirements.txt

# pip freeze > requirements.txt

Test Gunicorn serve

# gunicorn --bind 0.0.0.0:8000 <app-name>.wsgi

Your images, etc will be gone

Stop server & deactivate virtual env

ctrl-c
# deactivate

Open gunicorn.socket file

# sudo nano /etc/systemd/system/gunicorn.socket

Copy this code, paste it in and save

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Open gunicorn.service file

# sudo nano /etc/systemd/system/gunicorn.service

Copy this code, paste it in and save

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=<ubuntu-username>
Group=www-data
WorkingDirectory=/home/<ubuntu-username>/pyapps/<project-name>
ExecStart=/home/<ubuntu-username>/pyapps/venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          <app-name>.wsgi:application

[Install]
WantedBy=multi-user.target

Start and enable Gunicorn socket

# sudo systemctl start gunicorn.socket
# sudo systemctl enable gunicorn.socket

Check status of guinicorn

# sudo systemctl status gunicorn.socket

Check the existence of gunicorn.sock

# file /run/gunicorn.sock

NGINX Setup

Create project folder

# sudo nano /etc/nginx/sites-available/<project-name>

Copy this code and paste into the file

server {
    listen 80;
    server_name <server-ip-address>;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/<ubuntu-username>/pyapps/<project-name>;
    }
    
    location /media/ {
        root /home/<ubuntu-username>/pyapps/<project-name>;    
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Enable the file by linking to the sites-enabled dir

# sudo ln -s /etc/nginx/sites-available/<project-name> /etc/nginx/sites-enabled

Test NGINX config

# sudo nginx -t

Restart NGINX

# sudo systemctl restart nginx

You will probably need to up the max upload size to be able to create listings with images (optional)

Open up the nginx conf file

# sudo nano /etc/nginx/nginx.conf

Add this to the http{} area

client_max_body_size 20M;

Reload NGINX

# sudo systemctl restart nginx

Media File Issue

You may have some issues with images not showing up. I would suggest, deleting all data and starting fresh as well as removeing the "photos" folder in the "media folder"

# sudo rm -rf media/photos

Domain Setup

Go to your domain registrar and create the following a record

@  A Record  YOUR_IP_ADDRESS
www  CNAME  example.com

Go to local_settings.py on the server and change "ALLOWED_HOSTS" to include the domain

ALLOWED_HOSTS = ['<server-ip-address>', 'example.com', 'www.example.com']

Edit /etc/nginx/sites-available/

server {
    listen: 80;
    server_name <server-ip-address> example.com www.example.com;
}

Reload NGINX & Gunicorn

# sudo systemctl restart nginx
# sudo systemctl restart gunicorn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment