Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
165 lines (152 loc) · 10.2 KB
/
Copy path.env.example
File metadata and controls
165 lines (152 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# Piloti — Variables d'environnement
# Copier ce fichier : cp .env.example .env
# puis remplir les valeurs ci-dessous.
# ── Versions des images Docker ─────────────────────────────────────────────────
# Lues par docker compose (prod, staging, dev) : obligatoires, le build échoue
# sans elles. Épinglées à la version exacte pour qu'un rebuild redonne la même
# image ; on les monte ici, en une ligne, puis on redéploie.
# Node : doit rester sur une ligne LTS (22 → fin de support avril 2027).
NODE_IMAGE_TAG="22.23.3-alpine3.24"
# Traefik : v3.6 minimum (Docker Engine 29+).
TRAEFIK_IMAGE_TAG="v3.7.13"
CLOUDFLARED_IMAGE_TAG="2026.9.3"
# ── Base de données ────────────────────────────────────────────────────────────
# SQLite : chemin relatif au dossier racine du projet.
DATABASE_URL="file:./dev.db"
# ── better-auth ────────────────────────────────────────────────────────────────
# Secret de signature des sessions JWT. DOIT être unique par environnement.
# Générer avec : openssl rand -hex 32
BETTER_AUTH_SECRET="changez-moi-openssl-rand-hex-32"
# URL publique complète de l'application (utilisée pour les liens dans les emails).
BETTER_AUTH_URL="http://localhost:3000"
# ── Resend (emails de réinitialisation de mot de passe) ───────────────────────
# Optionnel en développement local : si vide, le flux "mot de passe oublié"
# retournera une erreur, mais le reste de l'application fonctionnera normalement.
#
# Pour activer :
# 1. Créer un compte sur https://resend.com (gratuit jusqu'à 3 000 emails/mois)
# 2. Ajouter et vérifier votre domaine (DNS TXT)
# 3. Créer une clé API dans le dashboard Resend
RESEND_API_KEY=""
RESEND_FROM_EMAIL="noreply@votre-domaine.fr"
# ── Web Push (VAPID) — notifications push navigateur ──────────────────────────
# Optionnel : si vide, l'app fonctionne mais le push est désactivé (l'in-app et
# l'email restent disponibles). Pour activer :
# npx web-push generate-vapid-keys
# La clé publique est transmise au client au runtime (pas de NEXT_PUBLIC_).
VAPID_PUBLIC_KEY=""
VAPID_PRIVATE_KEY=""
VAPID_SUBJECT="mailto:contact@votre-domaine.fr"
# ── Seed (données factices : dev et staging uniquement) ───────────────────────
# `pnpm db:seed` EFFACE la base visée. Il refuse de tourner si DATABASE_URL
# n'est pas la base de dev locale, sauf SEED_CONFIRM="1" (posé par le compose
# staging). Ne jamais poser cette variable dans un environnement de production.
SEED_CONFIRM=""
# Mot de passe des comptes factices. Si vide, un mot de passe aléatoire est
# généré et affiché en fin de seed. Jamais de valeur en dur dans le code.
SEED_PASSWORD=""
# ── Conservation du journal d'audit (#163) ────────────────────────────────────
# Durée, en années entières, au-delà de laquelle les lignes du journal d'audit
# sont supprimées par le planificateur. Vide = 10 ans (historique comptable).
# Entier de 1 à 100 : toute autre valeur empêche l'application de démarrer.
# Affichée telle quelle dans /confidentialite (« Durées de conservation »).
# Indépendamment de ce réglage, le texte des messages de salon modifiés ou
# supprimés est retiré du journal au bout d'1 an (durée fixe).
AUDIT_RETENTION_YEARS=""
# ══════════════════════════════════════════════════════════════════════════════
# DÉPLOIEMENT — variables lues par les fichiers docker-compose.
# Le développement local n'en a pas besoin : tout ce qui précède suffit.
# ══════════════════════════════════════════════════════════════════════════════
# ── Identité légale du groupe (pages /mentions-legales, /cgu, /confidentialite) ─
# OBLIGATOIRES en production : `docker compose up` échoue si l'une manque. Les
# mentions légales sont une obligation légale (LCEN art. 6-III) — une instance
# ne doit pas pouvoir être publiée avec des pages légales incomplètes.
# En développement local, les laisser vides affiche un « [À COMPLÉTER : … ] »
# visible sur la page ; rien d'autre n'en dépend.
# Éditeur du site au sens LCEN : QUI publie cette instance. Les Scouts et Guides
# de France ont une personnalité morale UNIQUE (SIREN 775 682 024) : un groupe
# local n'est pas une association et ne peut donc pas être éditeur. Selon le
# déploiement, mettre ici l'association nationale ou la personne qui héberge
# l'instance pour son groupe.
ORG_NAME="Prénom Nom"
# Groupe local desservi — l'usage, pas l'éditeur. Peut valoir la même chose que
# ORG_NAME si les deux coïncident.
ORG_GROUP="Groupe SGDF de Votre-Ville"
ORG_ADDRESS="12 rue de l'Exemple, 00000 Votre-Ville"
ORG_EMAIL="contact@votre-domaine.fr"
# Adresse par laquelle s'exercent les droits RGPD (accès, rectification,
# effacement). Peut être relevée par une autre personne que le contact général.
ORG_PRIVACY_EMAIL="rgpd@votre-domaine.fr"
# Directeur de la publication — en pratique le responsable de groupe.
ORG_PUBLICATION_DIRECTOR="Prénom Nom"
# Hébergeur, nom ET localisation. En auto-hébergement, indiquer l'hébergeur de
# la connexion et le lieu de la machine — la LCEN impose de le désigner.
ORG_HOSTING_PROVIDER="Auto-hébergé — Votre-Ville, France (accès via Cloudflare)"
# ── Production (docker-compose.yml, fichier .env) ─────────────────────────────
# Reprend BETTER_AUTH_*, RESEND_* et VAPID_* ci-dessus, plus ces deux-ci.
# Aucun port n'est publié : tout entre par cloudflared → Traefik.
TRAEFIK_DOMAIN="piloti.votre-domaine.fr"
CLOUDFLARE_TUNNEL_TOKEN=""
# ── Sauvegardes (scripts/backup.ps1, côté hôte) ───────────────────────────────
# Lues par le script de sauvegarde, PAS par l'application : ces variables vivent
# dans l'environnement de l'hôte, pas dans le conteneur.
#
# Chiffrement des archives : `age`, à clé publique (cf. D-030). Générer la paire
# une seule fois :
# docker run --rm alpine:3.21 sh -c "apk add --no-cache age >/dev/null && age-keygen"
#
# Clé PUBLIQUE (age1…) : posée ici, sur l'hôte de sauvegarde. Non sensible — elle
# ne permet que de chiffrer. L'hôte produit donc des sauvegardes qu'il ne peut
# pas relire : une machine compromise n'ouvre pas l'historique.
BACKUP_AGE_RECIPIENT=""
# Clé PRIVÉE (fichier contenant AGE-SECRET-KEY-…) : nécessaire UNIQUEMENT pour
# restaurer ou pour `-Verify`. À conserver AILLEURS que sur cette machine et
# ailleurs que dans les archives qu'elle protège — la perdre rend toutes les
# sauvegardes définitivement illisibles. Laisser vide pour la sauvegarde
# quotidienne planifiée ; ne la monter que le temps d'une vérification.
BACKUP_AGE_IDENTITY=""
# Répertoire local des archives. Défaut : "$HOME/piloti-backups".
PILOTI_BACKUP_DIR=""
# Destination HORS-SITE (chemin réseau, disque externe, montage NAS…). Vide =
# sauvegarde locale uniquement : protège d'une migration ratée, pas d'un vol,
# d'un incendie ni d'un rançongiciel. L'archive étant chiffrée ET authentifiée,
# la destination n'a besoin d'être ni de confiance ni protégée en écriture : une
# archive altérée sera rejetée à la restauration.
PILOTI_BACKUP_REMOTE=""
# ── Staging (docker-compose.staging.yml, fichier .env.staging) ────────────────
# Stack parallèle et TOTALEMENT isolée de la prod (cf. D-017) : secrets, tunnel
# et domaine distincts. Ne jamais y recopier les valeurs de production —
# la base staging est jetable et ne doit contenir aucune donnée réelle.
# Toutes ces variables sont OBLIGATOIRES : le compose refuse de démarrer sans.
STAGING_DOMAIN="staging.votre-domaine.fr"
STAGING_BETTER_AUTH_SECRET="changez-moi-openssl-rand-hex-32"
STAGING_BETTER_AUTH_URL="https://staging.votre-domaine.fr"
STAGING_CLOUDFLARE_TUNNEL_TOKEN=""
# Mot de passe des comptes factices seedés à chaque déploiement staging.
STAGING_SEED_PASSWORD=""
# Optionnels (vides = canal désactivé). Ne jamais pointer vers les identifiants
# de prod : on enverrait de vrais emails/push depuis un environnement de test.
# Clé DÉDIÉE à staging, jamais celle de la prod : révocable seule. Attention —
# activer l'envoi sur staging expose la réputation du domaine, partagée avec la
# production : le jeu de démonstration est plein d'adresses en TLD réservé, qui
# rebondiraient toutes. `src/lib/email.ts` les filtre pour cette raison.
STAGING_RESEND_API_KEY=""
# Expéditeur. Le BAC À SABLE de Resend est recommandé pour staging : il
# n'autorise qu'un seul destinataire, l'adresse du titulaire du compte Resend.
# Staging devient alors physiquement incapable d'écrire à une famille, et sa
# réputation d'envoi n'a rien de commun avec celle de la production. Ce n'est
# pas un repli : c'est le réglage le plus sûr pour un environnement peuplé de
# données factices.
STAGING_RESEND_FROM_EMAIL="onboarding@resend.dev"
#
# PIÈGE, rencontré le 2026-08-25 : une clé Resend est cadrée sur UN domaine,
# et l'écran « API keys » affiche la permission mais PAS cette portée. Une clé
# créée sur la mauvaise portée renvoie un 403 « not authorized to send emails
# from <domaine> » — quelle que soit l'adresse d'expédition, y compris celle
# que la production utilise avec succès. Le domaine ne se modifie pas après
# coup : il faut recréer la clé. Diagnostic en deux requêtes :
# from=<votre domaine> → 403 = la clé n'a pas droit à ce domaine
# from=onboarding@resend.dev → 200 = la clé et le compte sont bons
STAGING_VAPID_PUBLIC_KEY=""
STAGING_VAPID_PRIVATE_KEY=""
STAGING_VAPID_SUBJECT=""