Déploiement VPS
Difficulté : Intermédiaire | Temps : 1–2 h | Coût : 5–20 €/mois
Prérequis
- VPS Debian 12+ ou Ubuntu 22.04+
- Accès root ou sudo
- Domaine pointant vers l'IP du VPS
- Ports 80 et 443 ouverts
1. Préparation du serveur
sudo apt update && sudo apt upgrade -y
sudo apt install -y \
python3.12 python3.12-venv python3.12-dev \
postgresql postgresql-contrib \
nginx \
git \
certbot python3-certbot-nginx \
build-essential libpq-dev
# Créer l'utilisateur applicatif
sudo useradd -m -s /bin/bash suddenly
sudo mkdir -p /opt/suddenly
sudo chown suddenly:suddenly /opt/suddenly
2. Base de données PostgreSQL
sudo -u postgres psql << 'EOF'
CREATE USER suddenly WITH PASSWORD 'motdepasse-securise';
CREATE DATABASE suddenly OWNER suddenly;
GRANT ALL PRIVILEGES ON DATABASE suddenly TO suddenly;
\q
EOF
3. Application
sudo -u suddenly bash << 'EOF'
cd /opt/suddenly
git clone https://github.com/RebelliousSmile/suddenly.git app
cd app
python3.12 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -e ".[federation]"
pip install gunicorn
EOF
Configuration .env
sudo -u suddenly nano /opt/suddenly/app/.env
DJANGO_SETTINGS_MODULE=config.settings.production
SECRET_KEY=votre-cle-secrete-longue
DOMAIN=votre-domaine.com
ALLOWED_HOSTS=votre-domaine.com
DATABASE_URL=postgres://suddenly:motdepasse-securise@localhost:5432/suddenly
DJANGO_SETTINGS_MODULEest indispensable :manage.pypointe par défaut sur les settings de développement. Sans cette ligne, vos migrations s'appliqueraient avecDEBUG=Trueet la mauvaise base. Les cookiesSecure, HSTS etDEBUG=Falseviennent du module de production — il n'y a pas de variable à poser pour ça.
Initialisation
sudo -u suddenly bash << 'EOF'
cd /opt/suddenly/app
source venv/bin/activate
set -a; source .env; set +a
python manage.py migrate
python manage.py createcachetable
python manage.py collectstatic --noinput
python manage.py createsuperuser
EOF
Les clés RSA de fédération ne se génèrent pas à la main : Suddenly crée les clés d'instance au premier besoin, et une paire par acteur à sa création.
4. Service systemd (Gunicorn)
sudo mkdir -p /var/log/suddenly
sudo chown suddenly:suddenly /var/log/suddenly
sudo tee /etc/systemd/system/suddenly.service << 'EOF'
[Unit]
Description=Suddenly Gunicorn Daemon
After=network.target postgresql.service
[Service]
User=suddenly
Group=suddenly
WorkingDirectory=/opt/suddenly/app
Environment="PATH=/opt/suddenly/app/venv/bin"
EnvironmentFile=/opt/suddenly/app/.env
ExecStart=/opt/suddenly/app/venv/bin/gunicorn \
--workers 3 \
--bind unix:/opt/suddenly/suddenly.sock \
--access-logfile /var/log/suddenly/access.log \
--error-logfile /var/log/suddenly/error.log \
suddenly.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable suddenly
sudo systemctl start suddenly
5. Nginx
sudo tee /etc/nginx/sites-available/suddenly << 'EOF'
upstream suddenly {
server unix:/opt/suddenly/suddenly.sock fail_timeout=0;
}
server {
listen 80;
server_name votre-domaine.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name votre-domaine.com;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=31536000" always;
access_log /var/log/nginx/suddenly_access.log;
error_log /var/log/nginx/suddenly_error.log;
client_max_body_size 10M;
location /static/ {
alias /opt/suddenly/app/staticfiles/;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /media/ {
alias /opt/suddenly/app/media/;
expires 7d;
}
location / {
proxy_pass http://suddenly;
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;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/suddenly /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
6. SSL (Let's Encrypt)
sudo certbot --nginx -d votre-domaine.com
Certbot configure Nginx et met en place le renouvellement automatique.
7. Redis (optionnel)
Recommandé pour les instances de 50+ utilisateurs.
sudo apt install -y redis-server
sudo systemctl enable redis-server
sudo systemctl start redis-server
Ajouter dans .env :
REDIS_URL=redis://localhost:6379/0
8. Celery (optionnel)
Nécessaire pour la livraison fédérée asynchrone sur les instances de 500+ utilisateurs, ou si Redis est activé.
Deux services : le worker (qui exécute les tâches) et beat (qui les planifie — purge des citations éphémères toutes les heures, rafraîchissement des acteurs distants une fois par jour).
sudo tee /etc/systemd/system/suddenly-celery.service << 'EOF'
[Unit]
Description=Suddenly Celery Worker
After=network.target redis.service
[Service]
User=suddenly
WorkingDirectory=/opt/suddenly/app
Environment="PATH=/opt/suddenly/app/venv/bin"
EnvironmentFile=/opt/suddenly/app/.env
ExecStart=/opt/suddenly/app/venv/bin/celery \
-A suddenly worker --loglevel=info \
--logfile=/var/log/suddenly/celery.log
Restart=on-failure
EOF
sudo tee /etc/systemd/system/suddenly-celery-beat.service << 'EOF'
[Unit]
Description=Suddenly Celery Beat
After=network.target redis.service
[Service]
User=suddenly
WorkingDirectory=/opt/suddenly/app
Environment="PATH=/opt/suddenly/app/venv/bin"
EnvironmentFile=/opt/suddenly/app/.env
ExecStart=/opt/suddenly/app/venv/bin/celery \
-A suddenly beat --loglevel=info \
--scheduler django_celery_beat.schedulers:DatabaseScheduler \
--logfile=/var/log/suddenly/celery-beat.log
Restart=on-failure
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now suddenly-celery suddenly-celery-beat
Sans Celery, ces deux tâches périodiques ne tournent pas : les citations éphémères ne seront jamais purgées. Sur une petite instance, planifiez-les en cron (voir Maintenance).
Mise à jour
sudo -u suddenly bash << 'EOF'
cd /opt/suddenly/app
git pull origin main
source venv/bin/activate
pip install --upgrade pip && pip install -e ".[federation]"
python manage.py migrate
python manage.py collectstatic --noinput
EOF
sudo systemctl restart suddenly
sudo systemctl restart suddenly-celery # si Celery activé
Dépannage
# Statut et logs de l'application
sudo systemctl status suddenly
sudo journalctl -u suddenly -n 50
# Logs Nginx
sudo tail -f /var/log/nginx/error.log
# Test de connexion à la base
sudo -u suddenly psql -d suddenly -c "SELECT 1;"
# Erreur 502 — vérifier le socket
ls -la /opt/suddenly/suddenly.sock