Skip to content

Instantly share code, notes, and snippets.

@eloc0n
Last active October 10, 2023 08:29
Show Gist options
  • Save eloc0n/c9f61958e6734a06f7ce77904f0a14d4 to your computer and use it in GitHub Desktop.
Save eloc0n/c9f61958e6734a06f7ce77904f0a14d4 to your computer and use it in GitHub Desktop.
Deployment with uWSGI

This is not a complete guide to deploying Django with nginx & uwsgi. There are plenty parts that you either have to skip or include. It's up to you, depending on your project. Don't follow this blindly. Use your brain, stackoverflow and google the shit out of it!


Creating SSH keys (Optional)

You can choose to create SSH keys to login if you want. If not, you will get the password sent to your email to login via SSH

To generate a key on your local machine

$ ssh-keygen

Hit enter all the way through and it will create a public and private key at

~/.ssh/id_rsa
~/.ssh/id_rsa.pub

You want to copy the public key (.pub file)

$ cat ~/.ssh/id_rsa.pub

Copy the entire output and add as an SSH key for your Host provider

Login To Your Server

If you setup SSH keys correctly the command below will let you right in. If you did not use SSH keys, it will ask for a password. This is the one that was mailed to you

$ ssh root@YOUR_SERVER_IP

Create a new user

It will ask for a password, use something secure. You can just hit enter through all the fields. I used the user "djangoadmin" but you can use anything

adduser djangoadmin

Give root privileges

usermod -aG sudo djangoadmin

SSH keys for the new user

Now we need to setup SSH keys for the new user. You will need to get them from your local machine

Exit the server

You need to copy the key from your local machine so either exit or open a new terminal

exit

You can generate a different key if you want but we will use the same one so lets output it, select it and copy it

$ cat ~/.ssh/id_rsa.pub

Log back into the server

$ ssh root@YOUR_SERVER_IP

Add SSH key for new user

Navigate to the new users home folder and create a file at '.ssh/authorized_keys' and paste in the key

cd /home/djangoadmin
mkdir .ssh
cd .ssh
nano authorized_keys
Paste the key and hit "ctrl-x", hit "y" to save and "enter" to exit

Login as new user

You should now get let in as the new user

$ ssh djangoadmin@YOUR_SERVER_IP

Disable root login

sudo nano /etc/ssh/sshd_config

Change the following

PermitRootLogin no
PasswordAuthentication no

Reload sshd service

sudo systemctl reload sshd

Simple Firewall Setup

See which apps are registered with the firewall

sudo ufw app list

Allow OpenSSH

sudo ufw allow OpenSSH

Enable firewall

sudo ufw enable

To check status

sudo ufw status

We are now done with access and security and will move on to installing software

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 [database_name];

Create user

CREATE USER [database_user] WITH PASSWORD '[postgres_password]!';

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

ALTER ROLE [database_user] SET client_encoding TO 'utf8';
ALTER ROLE [database_user] SET default_transaction_isolation TO 'read committed';
ALTER ROLE [database_user] SET timezone TO 'UTC';

Give User access to database

GRANT ALL PRIVILEGES ON DATABASE [postgres_password] TO [database_user];

Quit out of Postgres

\q

Vitrual Environment

You need to install the python3-venv package

sudo apt install python3-venv

Create project directory

mkdir [prodject_name]
cd [prodject_name]

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

git clone https://github.com/yourgithubname/yourgithubproject.git django

Create venv

python3 -m venv ./venv

Activate the environment

source venv/bin/activate

Install pip modules from requirements

You could manually install each one as well

pip install -r requirements.txt

Import dump postgres database

psql -d [database_name]_db -f [database_name].psql

Run Migrations

python manage.py migrate

Create super user

python manage.py createsuperuser

Create static files

python manage.py collectstatic

Install uwsgi

pip install uwsgi

Test uWSGI

uwsgi --http :8000 --module project/core.wsgi

Basic nginx

Install nginx

sudo apt-get install nginx
sudo /etc/init.d/nginx start    # start nginx

Configure nginx for your site

# mysite_nginx.conf

# the upstream component nginx needs to connect to
upstream django {
    # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

Configure DNS

Add A record IP

configuration of the nginx.conf server

server {
    if ( $host !~* ^(milkshakesanddreams.com)$ ) {return 444;}
    server_name     milkshakesanddreams.com;

    access_log      /home/milkshakes/milkshakes/logs/milkshakesanddreams.com/nginx_access.log;
    error_log       /home/milkshakes/milkshakes/logs/milkshakesanddreams.com/nginx_error.log;

    root html;
    proxy_read_timeout 300;
    proxy_connect_timeout 300;
    proxy_send_timeout 300; 
    client_max_body_size 20m;

    location / {
        uwsgi_pass unix://home/milkshakes/milkshakes/deploy/sockets/milkshakesanddreams.com.sock;
        include uwsgi_params;

        #limit_req zone=default burst=10 nodelay;
    }

    location /static/ {
        alias           /home/milkshakes/milkshakes/public/milkshakesanddreams.com/static/;
        log_not_found   off;
        expires 365d;
    }

    location /media/ {
        alias           /home/milkshakes/milkshakes/public/milkshakesanddreams.com/media/;
        log_not_found   off;
        expires 365d;
    }

    location = /robots.txt {
        alias           /home/milkshakes/milkshakes/public/milkshakesanddreams.com/robots.txt;
        access_log      off;
        log_not_found   off;
    }

    location = /favicon.ico {
        alias           /home/milkshakes/milkshakes/public/milkshakesanddreams.com/static/favicon.ico;
        access_log      off;
        log_not_found   off;
        expires 365d;
    }

    location ~ /\. {
      deny all;
    }

    listen          80;


}

Configuration of uwsgi.ini

[uwsgi]
root_folder = milkshakes
project_folder = project
root_app = core
username = milkshakes
domain = milkshakesanddreams.com
base = /home/%(username)
plugins = python3

chdir = %(base)/%(root_folder)
home = %(base)/%(root_folder)/virtualenv
pythonpath = %(base)/%(root_folder)/%(project_folder)
module = %(root_app).wsgi:application

master = true
processes = 3

socket = %(base)/%(root_folder)/deploy/sockets/%(domain).sock
chown-socket = www-data:www-data
chmod-socket = 770
vacuum = true

uid = %(username)
gid = %(username)
logto = %(base)/%(root_folder)/logs/%(domain)/uwsgi.log
logfile-chown = true

Symlink to this file from /etc/nginx/sites-enabled so nginx can see it

sudo ln -s /mysite/deploy/test.gr/nginx.conf /etc/nginx/conf.d/test.gr.conf

Create nginx_access.log

cd /home/milkshakes/milkshakes/logs/milkshakesanddreams.com/
sudo touch nginx_access.log

Give permissions nginx_access.log

chown -R www-data:root /home/milkshakes/milkshakes/logs/milkshakesanddreams.com/nginx_access.log;

Create nginx_error.log

cd /home/milkshakes/milkshakes/logs/milkshakesanddreams.com/
sudo touch nginx_error.log

Give permissions nginx_error.log

chown -R www-data:root /home/milkshakes/milkshakes/logs/milkshakesanddreams.com/nginx_error.log;

Create uwsgi.log

cd /home/milkshakes/milkshakes/logs/milkshakesanddreams.com/
su milkshakes
touch uwsgi.log

Symlink to this file from /etc/uwsgi/vassals so uwsgi can see it

sudo ln -s /mysite/deploy/test.gr/uwsgi.ini /etc/uwsgi/vassals/test.gr.ini

Touch uwsgi.ini

su milkshakes
cd /home/milkshakes/milkshakes/
touch deploy/milkshakesanddreams.com/uwsgi.ini

FOR MORE DETAILS ABOUT UWSGI REFER TO THE DOCUMENTATION

https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment