A previous version of this tutorial was written by Kathleen Juell.
Introduzione
In questa guida, costruirai un’applicazione Python utilizzando il microframework Flask su Ubuntu 22.04. La maggior parte di questo tutorial sarà su come configurare il server dell’applicazione Gunicorn e su come avviare l’applicazione e configurare Nginx per agire come un proxy inverso front-end.
Prerequisiti
Prima di iniziare questa guida, dovresti avere:
-
Un server con Ubuntu 22.04 installato e un utente non root con privilegi sudo. Segui la nostra guida all’impostazione iniziale del server per orientamento.
-
Nginx installato, seguendo i Passaggi 1 e 2 di Come Installare Nginx su Ubuntu 22.04.
-
Un nome di dominio configurato per puntare al tuo server. Puoi acquistarne uno su Namecheap o ottenerne uno gratuitamente su Freenom. Puoi imparare come puntare i domini su DigitalOcean seguendo la relativa documentazione su domini e DNS. Assicurati di creare i seguenti record DNS:
- Un record A con
il_tuo_dominio
puntato all’indirizzo IP pubblico del tuo server. - Un record A con
www.il_tuo_dominio
puntato all’indirizzo IP pubblico del tuo server.
- Un record A con
-
Familiarità con la specifica WSGI, che il server Gunicorn utilizzerà per comunicare con la tua applicazione Flask. Questa discussione approfondisce ulteriormente il WSGI.
Passaggio 1 — Installazione dei Componenti dai Repository di Ubuntu
Il primo passaggio sarà quello di installare tutti i componenti richiesti dai repository di Ubuntu. Questo include pip
, il gestore dei pacchetti Python, che gestirà i componenti Python. Otterrai anche i file di sviluppo di Python necessari per compilare alcuni dei componenti di Gunicorn.
Prima di tutto, aggiorna l’indice dei pacchetti locali e installa i pacchetti che ti consentiranno di creare il tuo ambiente Python. Questi includeranno python3-pip
, insieme a alcuni altri pacchetti e strumenti di sviluppo necessari per un ambiente di programmazione robusto:
Con questi pacchetti in posizione, il passo successivo è creare un ambiente virtuale per il tuo progetto.
Passaggio 2 — Creazione di un Ambiente Virtuale Python
Successivamente, configurerai un ambiente virtuale per isolare l’applicazione Flask dagli altri file Python sul tuo sistema.
Inizia installando il pacchetto python3-venv
, che installerà il modulo venv
:
Successivo, crea una directory principale per il tuo progetto Flask. Spostati nella directory con il comando cd
dopo averla creata:
Crea un ambiente virtuale per memorizzare i requisiti Python del tuo progetto Flask digitando:
Questo installerà una copia locale di Python e pip
in una directory chiamata myprojectenv
all’interno della tua directory del progetto.
Prima di installare le applicazioni all’interno dell’ambiente virtuale, devi attivarlo. Fallo digitando:
Il prompt cambierà per indicare che stai ora operando all’interno dell’ambiente virtuale. Apparirà qualcosa del genere: (myprojectenv)user@host:~/myproject$
.
Passaggio 3 — Configurazione di un’applicazione Flask
Ora che sei nel tuo ambiente virtuale, puoi installare Flask e Gunicorn e iniziare a progettare la tua applicazione.
Prima, installa wheel
con l’istanza locale di pip
per garantire che i tuoi pacchetti si installino anche se mancano archivi wheel:
Nota
Indipendentemente dalla versione di Python che stai utilizzando, quando l’ambiente virtuale è attivato, dovresti usare il comando pip
(non pip3
).
Successivamente, installa Flask e Gunicorn:
Creazione di un’applicazione di esempio
Ora che hai Flask disponibile, puoi creare un’applicazione semplice. Flask è un microframework. Non include molti degli strumenti che potrebbero essere presenti in framework più completi e esiste principalmente come un modulo che puoi importare nei tuoi progetti per aiutarti nell’inizializzazione di un’applicazione web.
Anche se la tua applicazione potrebbe essere più complessa, creeremo la nostra app Flask in un singolo file, chiamato myproject.py
:
Il codice dell’applicazione risiederà in questo file. Importerà Flask e istanzierà un oggetto Flask. Puoi usare questo per definire le funzioni che devono essere eseguite quando viene richiesta una specifica route:
Questo definisce fondamentalmente quale contenuto presentare quando viene accesso il dominio radice. Salva e chiudi il file quando hai finito.
Se hai seguito la guida iniziale alla configurazione del server, dovresti avere un firewall UFW abilitato. Per testare l’applicazione, devi consentire l’accesso alla porta 5000
:
Ora puoi testare la tua app Flask digitando:
Vedrai un output simile al seguente, incluso un avviso utile che ti ricorda di non utilizzare questa configurazione del server in produzione:
Output* Serving Flask app "myproject" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Visita l’indirizzo IP del tuo server seguito da :5000
nel tuo browser web:
http://your_server_ip:5000
Dovresti vedere qualcosa del genere:
Quando hai finito, premi CTRL-C
nella finestra del terminale per interrompere il server di sviluppo Flask.
Creazione del Punto di Accesso WSGI
Successivamente, crea un file che fungerà da punto di accesso per la tua applicazione. Questo dirà al server Gunicorn come interagire con l’applicazione.
Chiamalo wsgi.py
:
In questo file, importa l’istanza Flask dalla nostra applicazione e poi avviala:
Salva e chiudi il file quando hai finito.
Passaggio 4 — Configurazione di Gunicorn
Ora la tua applicazione è stata scritta con un punto di accesso stabilito. Ora puoi passare alla configurazione di Gunicorn.
Prima di procedere, verifica che Gunicorn possa servire correttamente l’applicazione.
Puoi farlo passandogli il nome del punto di accesso dell’applicazione. Questo è costruito come il nome del modulo (senza l’estensione .py
), più il nome della chiamata all’interno dell’applicazione. In questo caso, è wsgi:app
.
Specifica anche l’interfaccia e la porta a cui collegarsi usando l’argomento 0.0.0.0:5000
in modo che l’applicazione venga avviata su un’interfaccia disponibile pubblicamente:
Dovresti vedere un output simile al seguente:
Output[2020-05-20 14:13:00 +0000] [46419] [INFO] Starting gunicorn 20.0.4
[2020-05-20 14:13:00 +0000] [46419] [INFO] Listening at: http://0.0.0.0:5000 (46419)
[2020-05-20 14:13:00 +0000] [46419] [INFO] Using worker: sync
[2020-05-20 14:13:00 +0000] [46421] [INFO] Booting worker with pid: 46421
Visita di nuovo l’indirizzo IP del tuo server con :5000
aggiunto alla fine nel tuo browser web:
http://your_server_ip:5000
Dovresti vedere l’output dell’applicazione:
Una volta confermato che funziona correttamente, premi CTRL-C
nella finestra del terminale.
Quando hai finito di usare l’ambiente virtuale, puoi disattivarlo:
Qualsiasi comando Python userà nuovamente l’ambiente Python di sistema.
Successivamente, crea il file dell’unità di servizio systemd. Creare un file dell’unità di servizio permetterà al sistema init di Ubuntu di avviare automaticamente Gunicorn e servire l’applicazione Flask ogni volta che il server si avvia.
Crea un file di unità che termini con .service
all’interno della directory /etc/systemd/system
per iniziare:
All’interno, inizia con la sezione [Unit]
, che viene utilizzata per specificare metadati e dipendenze. Aggiungi una descrizione del tuo servizio qui e indica al sistema init di avviare questo solo dopo che il target di rete è stato raggiunto:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
Successivamente, aggiungi una sezione [Service]
. Questo specifica l’utente e il gruppo sotto cui desideri eseguire il processo. Assegna il possesso del processo al tuo account utente normale poiché possiede tutti i file rilevanti. Assegna anche il possesso al gruppo www-data
in modo che Nginx possa comunicare facilmente con i processi Gunicorn. Ricorda di sostituire il nome utente qui con il tuo nome utente:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
Successivamente, mappa la directory di lavoro e imposta la variabile ambientale PATH
in modo che il sistema di inizializzazione sappia che gli eseguibili del processo sono situati all’interno del nostro ambiente virtuale. Specifica anche il comando per avviare il servizio. Questo comando farà quanto segue:
- Avvia 3 processi worker (anche se dovresti adattare questo se necessario)
- Crea e collegati a un file socket Unix,
myproject.sock
, all’interno della nostra directory di progetto. Imposteremo un valore diumask
di007
in modo che il file socket sia creato dando accesso al proprietario e al gruppo, mentre si limita l’accesso ad altri - Specifica il nome del file di ingresso WSGI, insieme alla funzione Python all’interno di tale file (
wsgi:app
)
Systemd richiede che tu fornisca il percorso completo dell’eseguibile Gunicorn, che è installato all’interno del tuo ambiente virtuale.
Ricorda di sostituire il nome utente e i percorsi del progetto con le tue informazioni:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
Infine, aggiungi una sezione [Install]
. Questo dirà a systemd a cosa collegare questo servizio se lo abiliti per l’avvio automatico. Vorrai che questo servizio si avvii quando il sistema multi-utente regolare è attivo e in esecuzione:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target
Con questo, il file di servizio di systemd è completo. Salvalo e chiudilo ora.
Ora puoi avviare il servizio Gunicorn che hai creato e abilitarlo in modo che si avvii all’avvio:
Controlliamo lo stato:
Dovresti vedere un output simile a questo:
Output● myproject.service - Gunicorn instance to serve myproject
Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2022-05-10 19:40:41 UTC; 9s ago
Main PID: 17300 (gunicorn)
Tasks: 4 (limit: 2327)
Memory: 56.0M
CPU: 514ms
CGroup: /system.slice/myproject.service
├─17300 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17301 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17302 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
└─17303 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
May 10 19:40:41 r systemd[1]: Started Gunicorn instance to serve myproject.
. . .
Se visualizzi degli errori, assicurati di risolverli prima di continuare con il tutorial.
Passaggio 5 — Configurazione di Nginx per Instradare le Richieste
Il server dell’applicazione Gunicorn dovrebbe essere ora attivo e in esecuzione, in attesa di richieste sul file socket nella directory del progetto. Ora puoi configurare Nginx per inoltrare le richieste web a quel socket apportando alcune piccole modifiche al suo file di configurazione.
Inizia creando un nuovo file di configurazione del blocco server nella directory sites-available
di Nginx. Chiamalo myproject
per mantenerti in linea con il resto della guida:
Apri un blocco server e indica a Nginx di ascoltare sulla porta predefinita 80
. Indica anche di utilizzare questo blocco per le richieste del nome di dominio del nostro server:
server {
listen 80;
server_name your_domain www.your_domain;
}
In seguito, aggiungi un blocco di posizione che corrisponda a ogni richiesta. All’interno di questo blocco, includerai il file proxy_params
che specifica alcuni parametri di inoltro generale che devono essere impostati. Successivamente, passerai le richieste al socket che hai definito utilizzando la direttiva proxy_pass
:
server {
listen 80;
server_name your_domain www.your_domain;
location / {
include proxy_params;
proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
}
}
Salva e chiudi il file quando hai finito.
Per abilitare la configurazione del blocco server di Nginx che hai appena creato, collega il file alla directory sites-enabled
:
Con il file in quella directory, puoi testare eventuali errori di sintassi:
Se questo ritorna senza indicare problemi, riavvia il processo Nginx per leggere la nuova configurazione:
Finalmente, aggiusta nuovamente il firewall. Non è più necessario l’accesso tramite la porta 5000
, quindi puoi rimuovere quella regola. Puoi quindi consentire l’accesso completo al server Nginx:
Ora dovresti essere in grado di navigare sul nome di dominio del tuo server nel browser web:
http://your_domain
Dovresti vedere l’output della tua applicazione:
Nota: Riceverai un errore di gateway HTTP 502 se Nginx non può accedere al file socket di Gunicorn. Di solito questo accade perché la directory home dell’utente non permette ad altri utenti di accedere ai file al suo interno.
Se il tuo file socket si chiama /home/sammy/myproject/myproject.sock
, assicurati che /home/sammy
abbia almeno le autorizzazioni 0755
. Puoi usare uno strumento come chmod
per cambiare le autorizzazioni in questo modo:
Poi ricarica la pagina per vedere se l’errore HTTP 502 scompare.
Se incontri errori, prova a controllare quanto segue:
sudo less /var/log/nginx/error.log
: controlla i log degli errori di Nginx.sudo less /var/log/nginx/access.log
: controlla i log degli accessi di Nginx.sudo journalctl -u nginx
: controlla i log del processo Nginx.sudo journalctl -u myproject
: controlla i log di Gunicorn della tua applicazione Flask.
Passaggio 6 — Sicurezza dell’Applicazione
Per garantire che il traffico verso il tuo server rimanga sicuro, otteniamo un certificato SSL per il tuo dominio. Ci sono diverse modalità per farlo, tra cui ottenere un certificato gratuito da Let’s Encrypt, generare un certificato autofirmato, o acquistarne uno da un altro fornitore e configurare Nginx per usarlo seguendo i passaggi da 2 a 6 di Come Creare un Certificato SSL Autofirmato per Nginx in Ubuntu 22.04. Utilizzeremo l’opzione uno (Let’s Encrypt) per ragioni di rapidità.
Installa il pacchetto Nginx di Certbot con apt
:
Certbot fornisce una varietà di modi per ottenere certificati SSL tramite plugin. Il plugin Nginx si occuperà di riconfigurare Nginx e ricaricare la configurazione quando necessario. Per utilizzare questo plugin, digita quanto segue:
Questo esegue certbot
con il plugin --nginx
, utilizzando -d
per specificare i nomi per cui vogliamo che il certificato sia valido.
Se questa è la prima volta che esegui certbot
, ti verrà chiesto di inserire un indirizzo email e accettare i termini del servizio. Dopo averlo fatto, certbot
comunicherà con il server Let’s Encrypt, quindi eseguirà una sfida per verificare che tu controlli il dominio per il quale stai richiedendo un certificato.
Se ciò avviene con successo, certbot
chiederà come desideri configurare le impostazioni HTTPS:
OutputPlease choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):
Seleziona la tua scelta e premi INVIO
. La configurazione verrà aggiornata e Nginx si ricaricherà per prendere le nuove impostazioni. certbot
concluderà con un messaggio che ti informerà che il processo è stato completato con successo e dove sono memorizzati i tuoi certificati:
OutputIMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/your_domain/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/your_domain/privkey.pem
Your cert will expire on 2020-08-18. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Se hai seguito le istruzioni di installazione di Nginx nei prerequisiti, non avrai più bisogno dell’autorizzazione del profilo HTTP ridondante:
Per verificare la configurazione, naviga nuovamente sul tuo dominio, utilizzando https://
:
https://your_domain
Dovresti vedere di nuovo l’output della tua applicazione, insieme all’indicatore di sicurezza del tuo browser, che dovrebbe indicare che il sito è protetto.
Conclusion
In questa guida, hai creato e protetto una semplice applicazione Flask all’interno di un ambiente virtuale Python. Hai creato un punto di ingresso WSGI in modo che qualsiasi server applicativo compatibile con WSGI possa interfacciarsi con esso, e quindi hai configurato il server dell’applicazione Gunicorn per fornire questa funzionalità. Successivamente, hai creato un file di servizio systemd per avviare automaticamente il server dell’applicazione all’avvio. Hai anche creato un blocco server Nginx che instrada il traffico dei client web al server dell’applicazione, inoltrando le richieste esterne e proteggendo il traffico verso il tuo server con Let’s Encrypt.
Flask è un framework molto semplice ma estremamente flessibile pensato per fornire alle tue applicazioni funzionalità senza essere troppo restrittivo per quanto riguarda struttura e design. Puoi utilizzare lo stack generale descritto in questa guida per servire le applicazioni Flask che progetti.