Pubblicare un sito Django su VPS (Ubuntu, Nginx, uWSGI)

Vediamo nel dettaglio come effettuare il deploy di una app Django su un VPS. Questa guida è stata testata con le seguenti versioni:

Preparazione

Collegarsi al server via ssh

Una volta collegati, creare un nuovo utente con permessi sudo

# Creare un nuovo utente
adduser luca

# Dare all'utente appena creato permessi sudo
usermod -aG sudo luca

D'ora in poi utilizzeremo solamente l'utente che abbiamo appena creato.

Aggiorniamo il sistema:

sudo apt-get update

sudo apt-get upgrade

Configurazione di Python, pip e Django

La versione 18.04 di Ubuntu dovrebbe avere Python 3.6 già preinstallato

# controllare se python è installato
python3.6 --version
==> Python 3.6.9

Installiamo pip

sudo apt install python3-pip

# Controlliamo che sia installato correttamente
pip3 --version
==> pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)

Ora possiamo installare virtualenv.Virtualenv crea un ambiente virtuale per i nostri eseguibili e le dipendenze. Questo renderà il nostro progetto isolato dagli altri progetti e dalla installazione globale di Python

# Installa GLOBALMENTE
sudo -H pip3 install virtualenv

Andiamo nella directory home e creiamo una nuova cartella per il nostro progetto

Quando lavoriamo nella nostra cartella home, non abbiamo bisogno del comando sudo
# con cd andiamo in /home/luca/
cd

# creiamo la directory
mkdir progetto

# spostiamoci dentro la directory appena creata
cd progetto

Creiamo ed attiviamo virtualenv

# Il nostro ambiente virtuale si chiamerà venv
python3 -m venv venv
# Attiviamo il nuovo ambiente virtuale
source venv/bin/activate

Installiamo Django e creiamo un progetto base

(venv) pip install django
(venv) django-admin startproject progetto
(venv) cd progetto
(venv) python manage.py migrate
(venv) python manage.py runserver 0.0.0.0:8000
==> Starting development server at http://0.0.0.0:8000/

Ora dovremmo essere in grado di vedere la pagina di benvenuto di Django andando su IPdelVPS:8000. Nel caso ci sia un errore, aprire il file settings.py nel progetto Django ed inserire l'indirizzo IP nelle opzioni "allowed hosts". (Oppure inserire l'asterisco, permettendo quindi tutti gli host)

uWSGI

A questo punto, se chiudiamo la connessione SSH, il sito Django smetterà di funzionare. Per fare in modo che il sito funzioni sempre, dobbiamo utilizzare l'application server uWSGI

Installare uWSGI globalmente

# Disattivare virtualenv
deactivate
sudo -H pip3 install uwsgi

# Controllare se è stato installato correttamente
uwsgi --version
==> 2.0.18

Ora è possibile lanciare il nostro sito utilizzando uwsgi, ma per farlo dobbiamo specificare alcuni parameetri:

  • http: Con questo parametro comunichiamo a uwsgi di usare http e aggiungiamo l'inidirizzo IP e la porta come argomeenti
  • home: il percorso del nostro ambiente virtualenv
  • chdir: il percorso della root del nostro progetto Django
  • wsgi-file: il percorso del file wsgi.py dentro al nostro progetto Django

Possiamo avviare il server con questo comando:

sudo uwsgi --http 0.0.0.0:8000 --home /home/luca/progetto/venv --chdir /home/luca/progetto/progetto --wsgi-file /home/luca/progetto/progetto/progetto/wsgi.py

Controlliamo che il sito funzioni andando su IPdelVPS:8000

PEr semplificare, creiamo un file .ini

# Può essere installato ovunque, io lo installo nella home dell'utente
cd

Creare la cartella uwsgi
mkdir uwsgi
cd uwsgi

Creare la cartella siti
mkdir siti
cd siti

Creare il file .ini
nano progetto.ini

Dentro al file progetto.ini scriviamo:

[uwsgi]
home = /home/luca/progetto/venv
chdir = /home/luca/progetto/progetto
wsgi-file = /home/luca/progetto/progetto/progetto/wsgi.py

http = 0.0.0.0:8000

Testiamo il funzionamento del file .ini utilizzando questo file per lanciare il sito

sudo uwsgi progetto.ini
Controllare che il sito sia online su IPdelVPS:8000

Invece di http utilizziamo i socket di Unix. Modificare il file progetto.ini in questo modo:

[uwsgi]
home = /home/luca/progetto/venv
chdir = /home/luca/progetto/progetto
wsgi-file = /home/luca/progetto/progetto/progetto/wsgi.py
socket = /home/luca/uwsgi/progetto.sock
vacuum = true
chown-socket = luca:www-data
chmod-socket = 660

Per far sì che uWSGI si avvii automaticamente al boot, possiamo utilizzare systemd o upstart. Utilizzeremo systemd.

cd /etc/systemd/system/
sudo nano uwsgi.service

E creiamo il file uwsgi.service:

[Unit]
Description=uWSGI Emperor service

[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown luca:www-data /run/uwsgi'
ExecStart=/usr/local/bin/uwsgi --emperor /home/luca/uwsgi/siti
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target

Nginx

Installiamo Nginx

sudo apt-get install nginx

# controlliamo se è stato installato correttamente
sudo nginx -v
==> nginx version: nginx/1.14.0 (Ubuntu)

Creiamo il file di configurazione per il nostro sito:

cd /etc/nginx/sites-available
sudo nano progetto

Dentro al file progetto scriviamo:

server {
    listen 8000;
    server_name [IPdelVPS];
    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/luca/uwsgi/progetto.sock;
    }
}

Dobbiamo poi creare un link simbolico (symlink) per il nostro file progetto dentro alla cartella sites-enabled:

sudo ln -s /etc/nginx/sites-available/progetto /etc/nginx/sites-enabled

Controlliamo che tutto sia corretto, e abilitiammo sia Nginx che uWSGI ad avviarsi al boot del sistema. Poi riavviamo il VPS:

# controlliamo che la sintassi sia corretta
sudo nginx -t

# abilitiamo nginx e uwsgi all'avvio al boot
sudo systemctl enable nginx
sudo systemctl enable uwsgi

# riavviamo il VPS
sudo reboot

# Check if website is up on [YourVPSIpAddress]:8000

Ora il sito è funzionante