Files
team-tryouts/docs/deployment.md
T
GGThed d0a9e75fe6 perf: servir les statiques par nginx, et dire ce que le bot n a pas livre
PERF-006. Le bloc location /static/ etait commente : 59 Ko de CSS et de JS
passaient par Waitress a chaque page. L activer tel quel aurait ete une
regression : ces URL ne changent jamais, donc un cache de 30 jours sert une
feuille de style vieille d un mois apres chaque deploiement, sans moyen de
l invalider. url_for('static') estampille maintenant chaque URL du mtime du
fichier ; c est ce qui rend le immutable vrai et pas seulement rapide.

Deux pieges nginx consignes dans le fichier : un add_header dans un location
annule tous les add_header herites du server (nosniff disparaissait du
JavaScript), et un statique manquant doit renvoyer 404 plutot que retomber
sur Flask, sinon un deploiement casse se cache derriere une page qui marche.

PERF-005. Les objets utilisateur Discord sont mis en cache. A etre precis
sur le gain : un envoi coute deux appels reseau, resoudre puis envoyer, et
seul le premier est economise — un premier match a vingt joueurs fait
toujours vingt resolutions. Ce qui est gagne l est entre notifications, la
ou le bot ecrit aux memes personnes soir apres soir.

Chaque message dit desormais ce qu il est devenu, avec le destinataire et
la raison. Les trois echecs ne se ressemblent pas et ne se lisent plus
pareil : une boite fermee est definitive et ne se retente pas, une erreur
HTTP est passagere, un identifiant sans proprietaire est un compte a
corriger. Le lot quotidien annonce son propre deficit.

Piege trouve en ecrivant les tests : configure_logging met propagate=False
sur le logger 'app', et le handler de caplog est sur la racine. Les
assertions sur les journaux passaient seules et echouaient dans la suite
complete, ou une application avait deja ete construite — elles lisaient un
journal vide, pas un bot silencieux.

417 tests.
2026-08-11 11:56:48 -04:00

183 lines
5.7 KiB
Markdown

# 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](https://nginx.org/en/download.html)
3. **SSL Certificate** (Let's Encrypt via certbot or commercial provider)
4. **Windows Firewall** configured properly
## Step 1: Install Dependencies
```powershell
# 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:
```env
# 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 `app/nginx.conf` to your Nginx installation directory (e.g., `C:\nginx\conf\`)
2. **Edit the `alias` in the `location /static/` block** to point at this
checkout's `app/static/` directory — absolute path, forward slashes, keep
the trailing slash. It ships as `C:/team-tryouts/app/static/`, which is a
guess about your machine. Nginx resolves a relative path against its own
install prefix, not against `nginx.conf`.
3. Place SSL certificate files:
- `C:\nginx\certs\fullchain.pem`
- `C:\nginx\certs\privkey.pem`
4. Check the configuration parses before restarting: `C:\nginx\nginx.exe -t`
5. Start Nginx: `C:\nginx\nginx.exe`
Nginx serves `/static/` from disk with a 30-day `immutable` cache. That is
only safe because `url_for('static', …)` appends `?v=<mtime>` to every static
URL (`version_static_urls` in `app/app.py`), so a redeployed file is requested
under a new URL. If that stamp is ever removed, remove the cache headers with
it or visitors keep a month-old stylesheet.
After a deploy, confirm the stamp changed rather than trusting it:
```powershell
# The v= value must differ from the one served before the deploy.
(Invoke-WebRequest https://your-domain/auth/login).Content -match 'style\.css\?v=(\d+)'
```
### Obtaining SSL Certificates
Using Let's Encrypt with certbot (recommended):
```powershell
# Using certbot on Windows
certbot certonly --standalone -d yourdomain.com
```
Or use your hosting provider's SSL certificate.
## Step 4: Start the Application
```powershell
# 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
```powershell
# 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:
```powershell
# 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:
```powershell
# 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