SLBCloud
Intermédiaire9 min de lecture

Héberger une application Python

Django ou FastAPI derrière nginx : environnement virtuel, gunicorn ou uvicorn, service systemd et fichiers statiques.

Le schéma est le même que pour Node : l'application écoute en local, nginx se place devant. La différence tient au serveur d'application — gunicorn pour Django et Flask, uvicorn pour FastAPI.

L'environnement virtuel

bash
sudo apt install python3-venv python3-dev
cd /var/www/mon-appli
python3 -m venv venv
./venv/bin/pip install -r requirements.txt gunicorn

Jamais de pip install en root

Installer des paquets Python à l'échelle du système entre en conflit avec ceux de la distribution, et les versions récentes de Debian refusent carrément. L'environnement virtuel n'est pas une précaution de puriste : c'est la seule façon propre.

Django

bash
./venv/bin/python manage.py migrate
./venv/bin/python manage.py collectstatic --noinput
./venv/bin/gunicorn monprojet.wsgi:application --bind 127.0.0.1:8000 --workers 3

Le nombre de workers se cale sur le nombre de cœurs : deux fois le nombre de cœurs plus un est la règle de départ. Au-delà, vous consommez de la mémoire sans servir plus vite.

FastAPI

bash
./venv/bin/pip install 'uvicorn[standard]'
./venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 3

Le service

/etc/systemd/system/mon-appli.service

ini
[Unit]
Description=Mon application Python
After=network.target

[Service]
Type=simple
User=appli
WorkingDirectory=/var/www/mon-appli
EnvironmentFile=/var/www/mon-appli/.env
ExecStart=/var/www/mon-appli/venv/bin/gunicorn monprojet.wsgi:application \
  --bind 127.0.0.1:8000 --workers 3 --timeout 60
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

nginx, et les fichiers statiques

nginx
server {
    listen 80;
    server_name mon-appli.fr;

    # Servis directement : inutile de réveiller Python pour une image
    location /static/ { alias /var/www/mon-appli/staticfiles/; expires 30d; }
    location /media/  { alias /var/www/mon-appli/media/; }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Les réglages Django à ne pas oublier

DEBUG = False en production — sinon une erreur affiche votre configuration complète, base de données comprise. ALLOWED_HOSTS doit contenir votre domaine, faute de quoi Django refuse toutes les requêtes. Et SECURE_PROXY_SSL_HEADER doit être défini pour que Django sache qu'il est derrière un proxy HTTPS.

Bloqué malgré tout ? Ouvrez un ticket : on répond en français, et on regarde votre machine si besoin.

Ouvrir un ticket