Files
team-tryouts/docs/deployment.md
T
GGThedandClaude Opus 5 2f40290f00 fix(deps): nommer le pilote PostgreSQL, sinon rien ne demarre
QUA-001, volet dialecte.

`postgresql://` ne veut pas dire "le pilote installe" : SQLAlchemy y lit
psycopg2 et importe ce module a la creation du moteur. requirements.txt
epingle psycopg 3 (`psycopg[binary]`) et pas psycopg2. Une installation
propre demarree sur cette URL leve donc

  ModuleNotFoundError: No module named 'psycopg2'

avant la premiere requete. Verifie dans le .venv du depot, et c est
exactement la forme que Render distribue -- celle que docs/deployment.md et
docs/database-restore.md donnaient en exemple.

normalise_database_url() nomme le pilote quand l URL n en nomme pas.
`postgres://` (alias hérite, abandonne par SQLAlchemy en 1.4) est traite de
meme. Une URL qui nomme deja son pilote est laissee telle quelle, y compris
`postgresql+psycopg2://` : un environnement qui a psycopg2 garde le choix.

La normalisation a lieu apres l application de la configuration passee en
argument, pour couvrir aussi les appels de test. backup.py n avait pas
besoin d etre touche : il retirait deja le suffixe +pilote.

Documentation alignee sur les trois fichiers qui donnaient l exemple, dont
docs/deployment.md qui proposait sqlite:/// pour DATABASE_URL alors que
create_app refuse de demarrer sans PostgreSQL.

Reste de QUA-001, dit franchement
  - les trois paquets parasites (dotenv, login, discord) ne sont plus dans
    requirements.txt : deja retires. psycopg est deja epingle.
  - la consolidation vers des groupes de dependances n est PAS faite. Le
    deploiement est un miroir de fichiers lftp sans etape de construction ;
    les groupes PEP 735 demandent pip >= 25.1 sur une machine dont on ne
    peut pas verifier la version d ici. A revoir avec OPS-011.

14 tests, dont trois qui prouvent que l echec est reel et non theorique.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-08 15:50:35 -04:00

4.7 KiB

Team Tryouts - Production Deployment Guide (Windows)

This document outlines the secure production deployment for the Team Tryouts Flask application on Windows with Nginx reverse proxy.

Architecture Overview

Internet → Nginx (HTTPS:443) → Waitress (127.0.0.1:5000) → Flask App
  • Nginx: TLS termination, static file serving, rate limiting, security headers
  • Waitress: Production WSGI server with multiple worker threads
  • Flask: Application logic (never exposed directly to the internet)

Prerequisites

  1. Python 3.12+ installed
  2. Nginx for Windows downloaded from nginx.org
  3. SSL Certificate (Let's Encrypt via certbot or commercial provider)
  4. Windows Firewall configured properly

Step 1: Install Dependencies

# Install Python packages
pip install -r requirements.txt

# Create required directories
mkdir logs
mkdir backups

Step 2: Configure Environment Variables

Create a .env file in the project root:

# Security (REQUIRED - generate with: python -c "import secrets; print(secrets.token_hex(32))")
SECRET_KEY=<your-generated-64-char-hex-key>

# Database — PostgreSQL. create_app() refuses to start without this.
# Either form works; the driver is named for you if you leave it out.
DATABASE_URL=postgresql://user:password@host:5432/dbname

# Security settings
SESSION_COOKIE_SECURE=true
FORCE_HTTPS=true
FLASK_DEBUG=false

# CORS (set to your actual domain in production)
CORS_ALLOWED_ORIGINS=https://yourdomain.com

# Discord bot (optional)
DISCORD_BOT_TOKEN=
DISCORD_WEBHOOK_URL=

# Backup settings
BACKUP_DIR=./backups
BACKUP_RETENTION_DAYS=30

Important: Never commit .env to version control.

Step 3: Configure Nginx

  1. Copy nginx.conf to your Nginx installation directory (e.g., C:\nginx\conf\)
  2. Place SSL certificate files:
    • C:\nginx\certs\fullchain.pem
    • C:\nginx\certs\privkey.pem
  3. Start Nginx: C:\nginx\nginx.exe

Obtaining SSL Certificates

Using Let's Encrypt with certbot (recommended):

# Using certbot on Windows
certbot certonly --standalone -d yourdomain.com

Or use your hosting provider's SSL certificate.

Step 4: Start the Application

# Production start
python wsgi.py

# Or with custom port/threads
$env:PORT=5000
$env:WAITRESS_THREADS=5
python wsgi.py

Step 5: Configure Windows Firewall

# Allow only necessary ports
New-NetFirewallRule -DisplayName "Nginx HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
New-NetFirewallRule -DisplayName "Nginx HTTP Redirect" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow

# Block direct access to Waitress port (5000) from outside
New-NetFirewallRule -DisplayName "Block Waitress External" -Direction Inbound -Protocol TCP -LocalPort 5000 -Action Block

Step 6: Set Up Automated Backups

Create a scheduled task for daily backups:

# Run backup script daily at 2:00 AM
$Action = New-ScheduledTaskAction -Execute "python" -Argument "backup.py" -WorkingDirectory "C:\path\to\team-tryouts"
$Trigger = New-ScheduledTaskTrigger -Daily -At 2:00AM
Register-ScheduledTask -TaskName "TeamTryoutsBackup" -Action $Action -Trigger $Trigger

Step 7: Run Security Validation

Before going live:

# Run the security scanner
python security_scan.py --url https://yourdomain.com

All checks must pass before deployment.

Security Checklist

  • .env is not committed to repository
  • SECRET_KEY is strong (64+ hex characters, randomly generated)
  • FLASK_DEBUG is set to false
  • Nginx is running with HTTPS (port 443)
  • HTTP (port 80) redirects to HTTPS
  • TLS 1.2+ configured (TLS 1.0/1.1 disabled)
  • HSTS header is present (max-age=31536000; includeSubDomains; preload)
  • CSP header is configured with no unsafe-eval
  • server_tokens is off in Nginx
  • File uploads restricted to PDF only
  • File uploads limited to 16MB
  • Database backups scheduled daily
  • Firewall rules applied (only 80/443 open)
  • Application is not running as administrator
  • Logs directory exists and is writable
  • Health check endpoint returns 200

Monitoring

  • Application logs: ./logs/app.log
  • Error logs: ./logs/errors.log
  • Auth logs: ./logs/auth.log
  • Nginx access logs: C:\nginx\logs\access.log
  • Nginx error logs: C:\nginx\logs\error.log

Monitor these logs regularly for suspicious activity.

Maintenance

  • Run pip-audit weekly to check for vulnerabilities
  • Run python security_scan.py after any configuration changes
  • Test backup restoration quarterly
  • Review and rotate SECRET_KEY if compromised
  • Keep Python and system packages updated