First commit
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
Configuration Gunicorn pour LOGIS en production.
|
||||
"""
|
||||
# Adresse d'écoute (nginx fait le proxy depuis le port 80/443)
|
||||
bind = '127.0.0.1:8091'
|
||||
|
||||
# Nombre de workers : (2 × CPU) + 1 est une heuristique classique
|
||||
workers = 3
|
||||
worker_class = 'sync'
|
||||
timeout = 120
|
||||
keepalive = 5
|
||||
max_requests = 1000
|
||||
max_requests_jitter = 50
|
||||
|
||||
# Journaux
|
||||
accesslog = '/var/log/logis/gunicorn_access.log'
|
||||
errorlog = '/var/log/logis/gunicorn_error.log'
|
||||
loglevel = 'info'
|
||||
capture_output = True
|
||||
|
||||
# Répertoire de travail
|
||||
chdir = '/path/to/LOGIS'
|
||||
@@ -0,0 +1,90 @@
|
||||
# Configuration nginx pour LOGIS
|
||||
# Copier dans : /etc/nginx/sites-available/logis
|
||||
# Puis : ln -s /etc/nginx/sites-available/logis /etc/nginx/sites-enabled/
|
||||
# SSL fourni par : certbot --nginx -d your-domain.com
|
||||
|
||||
# Rate-limit sur le formulaire de contact : 10 requêtes/min par IP
|
||||
limit_req_zone $binary_remote_addr zone=contact:10m rate=10r/m;
|
||||
|
||||
# Redirection HTTP → HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name your-domain.com;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/html;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# Serveur HTTPS principal
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name your-domain.com;
|
||||
|
||||
# Certificats SSL (générés par certbot)
|
||||
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
|
||||
# Sécurité des en-têtes
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header X-Frame-Options DENY always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
# Taille max des uploads (photos haute résolution)
|
||||
client_max_body_size 25M;
|
||||
|
||||
# Fichiers statiques servis directement par nginx
|
||||
location /static/ {
|
||||
alias /path/to/LOGIS/staticfiles/;
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Fichiers médias (photos uploadées)
|
||||
location /media/ {
|
||||
alias /path/to/LOGIS/media/;
|
||||
expires 7d;
|
||||
add_header Cache-Control "public";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Scans automatiques — drop silencieux (pas de réponse)
|
||||
location ~* \.(php|asp|aspx|jsp|cgi|pl|sh|bash|env|git|svn|htaccess)$ {
|
||||
return 444;
|
||||
}
|
||||
location ~* ^/(cgi-bin|vendor|phpunit|Autodiscover|autodiscover|wp-admin|wp-login|phpmyadmin|admin\.php|xmlrpc\.php|shell|config|\.well-known/(?!acme)) {
|
||||
return 444;
|
||||
}
|
||||
|
||||
# Rate-limit sur l'endpoint de contact (fr + en)
|
||||
location ~* ^/(en/)?contact/ {
|
||||
limit_req zone=contact burst=5 nodelay;
|
||||
proxy_pass http://127.0.0.1:8091;
|
||||
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;
|
||||
}
|
||||
|
||||
# Proxy vers Gunicorn (port 8091)
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8091;
|
||||
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;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_buffering on;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
# Script d'installation et de configuration de LOGIS en production
|
||||
# Exécuter une seule fois sur le VPS en tant que l'utilisateur applicatif
|
||||
# Usage : bash conf/setup_production.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
VENV="$BASE_DIR/venv"
|
||||
LOG_DIR="/var/log/logis"
|
||||
|
||||
echo "==> Répertoire de l'application : $BASE_DIR"
|
||||
|
||||
# ── 1. Répertoires de logs ────────────────────────────────────────────────────
|
||||
echo "==> Création du répertoire de logs…"
|
||||
sudo mkdir -p "$LOG_DIR"
|
||||
sudo chown "$USER:$USER" "$LOG_DIR"
|
||||
sudo chmod 755 "$LOG_DIR"
|
||||
|
||||
# ── 2. Environnement virtuel Python ──────────────────────────────────────────
|
||||
if [ ! -d "$VENV" ]; then
|
||||
echo "==> Création du virtualenv…"
|
||||
python3 -m venv "$VENV"
|
||||
fi
|
||||
echo "==> Installation des dépendances…"
|
||||
"$VENV/bin/pip" install --upgrade pip
|
||||
"$VENV/bin/pip" install -r "$BASE_DIR/requirements.txt"
|
||||
|
||||
# ── 3. Fichier .env de production ────────────────────────────────────────────
|
||||
if [ ! -f "$BASE_DIR/.env" ]; then
|
||||
echo "==> Copie de .env.example → .env (à personnaliser !)"
|
||||
cp "$BASE_DIR/.env.example" "$BASE_DIR/.env"
|
||||
echo ""
|
||||
echo " ⚠ Éditez maintenant $BASE_DIR/.env avec vos vraies valeurs"
|
||||
echo " (SECRET_KEY, EMAIL_*, ALLOWED_HOSTS, SITE_DOMAIN…)"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# ── 4. Migrations et fichiers statiques ──────────────────────────────────────
|
||||
echo "==> Migrations…"
|
||||
DJANGO_SETTINGS_MODULE=logis_project.settings.production \
|
||||
"$VENV/bin/python" "$BASE_DIR/manage.py" migrate --noinput
|
||||
|
||||
echo "==> Fichiers statiques…"
|
||||
DJANGO_SETTINGS_MODULE=logis_project.settings.production \
|
||||
"$VENV/bin/python" "$BASE_DIR/manage.py" collectstatic --noinput
|
||||
|
||||
echo "==> Compilation des traductions…"
|
||||
DJANGO_SETTINGS_MODULE=logis_project.settings.production \
|
||||
"$VENV/bin/python" "$BASE_DIR/manage.py" compilemessages
|
||||
|
||||
# ── 5. Supervisor ────────────────────────────────────────────────────────────
|
||||
echo "==> Installation du service Supervisor…"
|
||||
sudo cp "$BASE_DIR/conf/supervisor.conf" /etc/supervisor/conf.d/logis.conf
|
||||
sudo supervisorctl reread
|
||||
sudo supervisorctl update
|
||||
|
||||
# ── 6. Nginx ─────────────────────────────────────────────────────────────────
|
||||
echo "==> Installation de la configuration nginx…"
|
||||
sudo cp "$BASE_DIR/conf/nginx.conf" /etc/nginx/sites-available/logis
|
||||
if [ ! -f /etc/nginx/sites-enabled/logis ]; then
|
||||
sudo ln -s /etc/nginx/sites-available/logis /etc/nginx/sites-enabled/logis
|
||||
fi
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
|
||||
# ── 7. Certbot SSL ────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "==> Pour générer le certificat SSL, exécutez :"
|
||||
echo " sudo certbot --nginx -d \$(grep SITE_DOMAIN $BASE_DIR/.env | cut -d= -f2)"
|
||||
echo ""
|
||||
|
||||
echo "✓ Installation terminée."
|
||||
echo " Créez un superutilisateur : $VENV/bin/python $BASE_DIR/manage.py createsuperuser"
|
||||
@@ -0,0 +1,21 @@
|
||||
; Configuration Supervisor pour le processus Gunicorn de LOGIS
|
||||
; Copier dans : /etc/supervisor/conf.d/logis.conf
|
||||
; Puis : supervisorctl reread && supervisorctl update
|
||||
|
||||
[program:logis]
|
||||
command=/path/to/LOGIS/venv/bin/gunicorn
|
||||
--config /path/to/LOGIS/conf/gunicorn.conf.py
|
||||
logis_project.wsgi:application
|
||||
directory=/path/to/LOGIS
|
||||
environment=DJANGO_SETTINGS_MODULE="logis_project.settings.production"
|
||||
user=your-user
|
||||
group=your-user
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startretries=3
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/var/log/logis/supervisor.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=5
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
Reference in New Issue
Block a user