Variables d'environnement
Reference complete des variables d'environnement pour configurer MyTelevision API dans tous les environnements.
Vue d'ensemble
MyTelevision API utilise des variables d'environnement pour toute sa configuration. Les variables sont validees au demarrage via un schema Joi pour garantir une configuration correcte.
Hierarchie de configuration
1. Variables d'environnement (priorite la plus elevee)
2. Fichier .env (developpement uniquement)
3. Valeurs par defaut (si applicable)
Fichiers de configuration
| Fichier | Role | Suivi Git |
|---|---|---|
.env | Developpement local | Non |
.env.example | Template avec toutes les variables | Oui |
docker-compose.yml | Valeurs par defaut Docker | Oui |
src/infrastructure/config/env.validation.ts | Schema de validation | Oui |
Application
| Variable | Default | Description | Requis |
|---|---|---|---|
NODE_ENV | development | Mode d'environnement (development, staging, production) | Oui |
PORT | 3000 | Port du serveur API | Non |
API_PREFIX | api/v2 | Prefixe des routes API | Non |
API_DOCS_PATH | /api/docs | Chemin de la documentation Swagger | Non |
LOG_LEVEL | debug | Niveau de log (debug, info, warn, error) | Non |
LOG_FORMAT | pretty | Format de log (pretty, json pour production) | Non |
CORS
| Variable | Default | Description | Requis |
|---|---|---|---|
CORS_ORIGINS | * | Origins autorisees (comma-separated) | Non |
CORS_CREDENTIALS | true | Autoriser les credentials | Non |
Base de donnees (PostgreSQL)
| Variable | Default | Description | Requis |
|---|---|---|---|
DATABASE_URL | - | URL complete de connexion PostgreSQL (postgresql://user:pass@host:5432/db?schema=public) | Oui |
DB_HOST | localhost | Hote de la base de donnees | Non |
DB_PORT | 5432 | Port de la base de donnees | Non |
DB_USER | mytv | Nom d'utilisateur | Non |
DB_PASSWORD | - | Mot de passe | Non |
DB_NAME | mytv | Nom de la base de donnees | Non |
Cache & Sessions (Redis)
| Variable | Default | Description | Requis |
|---|---|---|---|
REDIS_HOST | localhost | Hote Redis | Oui |
REDIS_PORT | 6379 | Port Redis | Non |
REDIS_PASSWORD | - | Mot de passe Redis | Prod uniquement |
REDIS_DB | 0 | Index de la base Redis | Non |
REDIS_TLS | false | Activer TLS (true en production) | Prod uniquement |
Cache applicatif
| Variable | Default | Description | Requis |
|---|---|---|---|
CACHE_TTL | 300 | Duree du cache en secondes (5 minutes) | Non |
CACHE_MAX_ITEMS | 1000 | Nombre maximum d'items en cache | Non |
JWT & Authentification
| Variable | Default | Description | Requis |
|---|---|---|---|
JWT_SECRET | - | Secret pour signer les access tokens (min 32 caracteres) | Oui |
JWT_EXPIRATION | 15m | Duree de validite de l'access token | Non |
JWT_REFRESH_SECRET | - | Secret pour signer les refresh tokens (min 32 caracteres) | Oui |
JWT_REFRESH_EXPIRATION | 7d | Duree de validite du refresh token | Non |
Generation de secrets securises
# Generer un secret JWT (64 caracteres)
openssl rand -base64 48
# Ou avec Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Encryption (TOTP 2FA)
| Variable | Default | Description | Requis |
|---|---|---|---|
TOTP_ENCRYPTION_KEY | - | Cle de 32 bytes en hexadecimal (64 caracteres hex) | Prod uniquement |
Firebase (Authentification sociale)
| Variable | Default | Description | Requis |
|---|---|---|---|
FIREBASE_PROJECT_ID | - | ID du projet Firebase | Oui |
FIREBASE_PRIVATE_KEY | - | Cle privee du service account (format PEM, JSON-escaped) | Oui |
FIREBASE_CLIENT_EMAIL | - | Email du service account | Oui |
FCM_SERVER_KEY | - | Cle serveur FCM pour les notifications push | Non |
Format de la cle privee Firebase
Dans le fichier .env, les retours a la ligne doivent etre echappes :
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBg...\n-----END PRIVATE KEY-----\n"
Stockage (Cloudflare R2)
| Variable | Default | Description | Requis |
|---|---|---|---|
R2_ACCOUNT_ID | - | Account ID Cloudflare | Prod uniquement |
R2_ACCESS_KEY_ID | - | Cle d'acces R2 | Prod uniquement |
R2_SECRET_ACCESS_KEY | - | Cle secrete R2 | Prod uniquement |
R2_BUCKET_NAME | - | Nom du bucket R2 | Prod uniquement |
R2_ENDPOINT | - | URL endpoint R2 | Prod uniquement |
R2_PUBLIC_URL | - | URL publique CDN du bucket | Prod uniquement |
PRESIGNED_URL_EXPIRY | 3600 | Duree des URLs presignees en secondes (1 heure) | Non |
MAX_FILE_SIZE | 104857600 | Taille max de fichier en bytes (100 MB) | Non |
TMDb API
| Variable | Default | Description | Requis |
|---|---|---|---|
TMDB_API_KEY | - | Cle API TMDb | Oui |
TMDB_API_URL | https://api.themoviedb.org/3 | URL de base de l'API TMDb | Non |
TMDB_IMAGE_BASE_URL | https://image.tmdb.org/t/p | URL de base des images TMDb | Non |
TMDB_DEFAULT_LANGUAGE | fr-FR | Langue par defaut pour les requetes TMDb | Non |
Streaming & Securite
| Variable | Default | Description | Requis |
|---|---|---|---|
STREAMING_SIGNING_SECRET | - | Cle HMAC pour signer les tokens de streaming (min 32 caracteres) | Oui |
STREAMING_AES128_KEY | - | Cle AES-128 pour chiffrement DRM/URLs (64 caracteres hex, 256 bits) | Oui |
STREAM_TOKEN_EXPIRY_HOURS | 24 | Duree de validite du token en heures | Non |
STREAM_TOKEN_MAX_USES | 5 | Nombre max d'utilisations par token | Non |
STREAM_TOKEN_IP_BINDING | true | Lier le token a l'IP client | Non |
Generation des cles de streaming
# STREAMING_SIGNING_SECRET (base64, min 32 chars)
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
# STREAMING_AES128_KEY (hex, 64 chars = 256 bits)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Flux d'authentification streaming (X-Stream-Token)
Le streaming securise utilise un systeme de double-token :
- Authorization : Bearer token JWT (authentification utilisateur)
- X-Stream-Token : Token de streaming (genere dynamiquement pour chaque contenu)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Login │ ──> │ Generate │ ──> │ Stream │
│ /auth/login │ │ Stream Token│ │ Content │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
v v v
accessToken POST /streaming/token GET /movies/{id}/stream
+ accessToken + accessToken
+ mediaType/mediaId + X-Stream-Token
Rate Limiting
| Variable | Default | Description | Requis |
|---|---|---|---|
THROTTLE_SHORT_TTL | 1000 | Fenetre courte en ms | Non |
THROTTLE_SHORT_LIMIT | 3 | Requetes max par fenetre courte | Non |
THROTTLE_MEDIUM_TTL | 10000 | Fenetre moyenne en ms | Non |
THROTTLE_MEDIUM_LIMIT | 20 | Requetes max par fenetre moyenne | Non |
THROTTLE_LONG_TTL | 60000 | Fenetre longue en ms | Non |
THROTTLE_LONG_LIMIT | 100 | Requetes max par fenetre longue | Non |
Internationalisation (i18n)
| Variable | Default | Description | Requis |
|---|---|---|---|
DEFAULT_LOCALE | fr_FR | Locale par defaut | Non |
SUPPORTED_LOCALES | fr_FR,en_US | Locales supportees (comma-separated) | Non |
Pagination
| Variable | Default | Description | Requis |
|---|---|---|---|
DEFAULT_PAGE_SIZE | 20 | Taille de page par defaut | Non |
MAX_PAGE_SIZE | 100 | Taille de page maximale | Non |
Email
| Variable | Default | Description | Requis |
|---|---|---|---|
EMAIL_ENABLED | false | Activer l'envoi reel d'emails | Non |
EMAIL_PROVIDER | console | Fournisseur d'email (console, sendgrid, ses) | Non |
EMAIL_FROM_ADDRESS | [email protected] | Adresse d'expedition | Non |
EMAIL_FROM_NAME | MyTelevision | Nom d'expedition | Non |
EMAIL_VERIFICATION_EXPIRY_HOURS | 24 | Duree de validite du code de verification en heures | Non |
MAX_VERIFICATION_ATTEMPTS | 5 | Max tentatives de verification | Non |
RESEND_VERIFICATION_COOLDOWN_MINUTES | 2 | Delai entre renvois de code en minutes | Non |
Monitoring (Prometheus)
| Variable | Default | Description | Requis |
|---|---|---|---|
METRICS_ENABLED | true | Activer les metriques Prometheus | Non |
METRICS_PATH | /metrics | Chemin de l'endpoint metriques | Non |
Multi-tenant (Systeme Account/Profile)
| Variable | Default | Description | Requis |
|---|---|---|---|
DEFAULT_MAX_PROFILES_PER_ACCOUNT | 4 | Max profils par compte | Non |
DEFAULT_MAX_DEVICES_PER_ACCOUNT | 5 | Max appareils par compte | Non |
DEFAULT_MAX_CONCURRENT_SESSIONS | 4 | Max sessions simultanees | Non |
KIDS_DEFAULT_MAX_AGE_RATING | 7 | Rating max par defaut pour profils enfants | Non |
KIDS_DEFAULT_DAILY_LIMIT_MINUTES | 120 | Limite quotidienne en minutes | Non |
PIN_MAX_ATTEMPTS | 5 | Max tentatives avant blocage | Non |
PIN_LOCKOUT_MINUTES | 15 | Duree du blocage en minutes | Non |
Suppression de compte (RGPD)
| Variable | Default | Description | Requis |
|---|---|---|---|
DELETION_RETRACTION_DAYS | 30 | Jours avant suppression definitive | Non |
Synchronisation (Sources externes)
| Variable | Default | Description | Requis |
|---|---|---|---|
MYTV_V1_API_URL | https://mytelevision.stream/api | URL de l'API MyTV v1 legacy | Non |
D5NEWS_API_URL | https://apiv3.d5newstv.com | URL de l'API D5News | Non |
Configuration par environnement
Developpement
# .env (developpement local)
NODE_ENV=development
PORT=3000
# Database (Docker)
DATABASE_URL=postgresql://mytv:mytv_password@localhost:5432/mytv?schema=public
# Redis (Docker)
REDIS_HOST=localhost
REDIS_PORT=6379
# JWT (secrets dev - PAS pour la production)
JWT_SECRET=dev-jwt-secret-minimum-32-characters-long
JWT_REFRESH_SECRET=dev-jwt-refresh-secret-minimum-32-chars
# Firebase (projet de test)
FIREBASE_PROJECT_ID=mytelevision-dev
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
FIREBASE_CLIENT_EMAIL=[email protected]
# TMDb
TMDB_API_KEY=your_tmdb_api_key
# Streaming
STREAMING_SIGNING_SECRET=dev-streaming-secret-min-32-chars-long
STREAMING_AES128_KEY=0000000000000000000000000000000000000000000000000000000000000000
Staging
NODE_ENV=staging
PORT=3000
DATABASE_URL=postgresql://app:${DB_PASSWORD}@staging-db.internal:5432/mytelevision?schema=public
REDIS_HOST=staging-redis.internal
REDIS_PORT=6379
REDIS_PASSWORD=${REDIS_PASSWORD}
JWT_SECRET=${JWT_SECRET}
JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
FIREBASE_PROJECT_ID=mytelevision-staging
FIREBASE_PRIVATE_KEY=${FIREBASE_PRIVATE_KEY}
FIREBASE_CLIENT_EMAIL=${FIREBASE_CLIENT_EMAIL}
R2_ACCOUNT_ID=${R2_ACCOUNT_ID}
R2_ACCESS_KEY_ID=${R2_ACCESS_KEY_ID}
R2_SECRET_ACCESS_KEY=${R2_SECRET_ACCESS_KEY}
R2_BUCKET_NAME=mytelevision-staging
R2_PUBLIC_URL=https://staging-cdn.mytelevision.com
TMDB_API_KEY=${TMDB_API_KEY}
STREAMING_SIGNING_SECRET=${STREAMING_SIGNING_SECRET}
Production
NODE_ENV=production
PORT=3000
# Connection pooling en production
DATABASE_URL=postgresql://app:${DB_PASSWORD}@prod-db-pool.internal:6432/mytelevision?schema=public&connection_limit=20
# Redis cluster avec TLS
REDIS_HOST=prod-redis.internal
REDIS_PORT=6379
REDIS_PASSWORD=${REDIS_PASSWORD}
REDIS_TLS=true
# Secrets JWT forts (generes, rotation trimestrielle)
JWT_SECRET=${JWT_SECRET}
JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET}
# Firebase (production)
FIREBASE_PROJECT_ID=mytelevision-prod
FIREBASE_PRIVATE_KEY=${FIREBASE_PRIVATE_KEY}
FIREBASE_CLIENT_EMAIL=${FIREBASE_CLIENT_EMAIL}
# R2 (production)
R2_ACCOUNT_ID=${R2_ACCOUNT_ID}
R2_ACCESS_KEY_ID=${R2_ACCESS_KEY_ID}
R2_SECRET_ACCESS_KEY=${R2_SECRET_ACCESS_KEY}
R2_BUCKET_NAME=mytelevision-prod
R2_PUBLIC_URL=https://cdn.mytelevision.com
TMDB_API_KEY=${TMDB_API_KEY}
STREAMING_SIGNING_SECRET=${STREAMING_SIGNING_SECRET}
Variables requises par profil Docker
| Variable | dev | staging | prod |
|---|---|---|---|
JWT_SECRET | default | requis | requis |
JWT_REFRESH_SECRET | default | requis | requis |
STREAMING_SIGNING_SECRET | default | requis | requis |
CORS_ORIGINS | default | requis | requis |
Gestion des secrets
Developpement
cp .env.example .env
# Editer .env avec vos valeurs locales
Docker Compose (Staging/Production)
# Creer les secrets
echo "your_jwt_secret" | docker secret create jwt_secret -
echo "your_db_password" | docker secret create db_password -
# Reference dans docker-compose.production.yml
secrets:
jwt_secret:
external: true
db_password:
external: true
services:
api:
secrets:
- jwt_secret
- db_password
environment:
- JWT_SECRET_FILE=/run/secrets/jwt_secret
- DB_PASSWORD_FILE=/run/secrets/db_password
Kubernetes
apiVersion: v1
kind: Secret
metadata:
name: mytelevision-secrets
type: Opaque
stringData:
JWT_SECRET: 'your-jwt-secret'
JWT_REFRESH_SECRET: 'your-refresh-secret'
DATABASE_URL: 'postgresql://...'
---
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: api
envFrom:
- secretRef:
name: mytelevision-secrets
Rotation des secrets
| Secret | Frequence | Processus |
|---|---|---|
JWT_SECRET | Trimestrielle | Rolling update, conserver l'ancienne cle 24h |
JWT_REFRESH_SECRET | Trimestrielle | Idem JWT_SECRET |
DB_PASSWORD | Annuelle | Coordonner avec le DBA |
| Cles R2 | Annuelle | Creer nouvelle, deprecier ancienne |
FIREBASE_PRIVATE_KEY | Si necessaire | Via Firebase Console |
Validation au demarrage
Schema Joi
L'API valide toutes les variables d'environnement au demarrage :
// src/infrastructure/config/env.validation.ts
export const validationSchema = Joi.object({
NODE_ENV: Joi.string()
.valid('development', 'staging', 'production')
.default('development'),
PORT: Joi.number().default(3000),
DATABASE_URL: Joi.string().required(),
JWT_SECRET: Joi.string().min(32).required(),
JWT_REFRESH_SECRET: Joi.string().min(32).required(),
// ... autres validations
});
Regles de validation
| Regle | Description |
|---|---|
required() | Obligatoire, bloque le demarrage si absente |
min(32) | Minimum 32 caracteres (pour les secrets) |
valid(...) | Doit etre une des valeurs specifiees |
default(...) | Valeur utilisee si non fournie |
when('NODE_ENV', ...) | Conditionnelle selon l'environnement |
Erreurs au demarrage
Si la validation echoue, l'API affiche une erreur claire et s'arrete :
[Nest] ERROR - Config validation error: "JWT_SECRET" length must be at least 32 characters long
Troubleshooting
1. Connexion base de donnees echouee
Error: connect ECONNREFUSED 127.0.0.1:5432
Solution :
docker-compose ps
docker-compose up -d postgres
2. Connexion Redis echouee
Error: connect ECONNREFUSED 127.0.0.1:6379
Solution :
docker-compose ps
docker-compose up -d redis
3. Secret JWT trop court
Error: "JWT_SECRET" length must be at least 32 characters long
Solution :
openssl rand -base64 32
4. Format cle privee Firebase
Error: Firebase private key must be a valid PEM string
Solution :
# Dans .env, echapper les retours a la ligne :
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBg...\n-----END PRIVATE KEY-----\n"
5. R2 non configure (production)
Warning: R2 storage not configured. File uploads will fail.
Solution :
R2_ACCOUNT_ID=your_account_id
R2_ACCESS_KEY_ID=your_access_key
R2_SECRET_ACCESS_KEY=your_secret_key
R2_BUCKET_NAME=your_bucket
R2_PUBLIC_URL=https://your-cdn-url