# Application web de la veille législative (SvelteKit, adapter-node). # # Démarrée par veille-web.socket à la première requête, elle s'arrête d'elle-même # après IDLE_TIMEOUT secondes sans trafic, et systemd la réveille à la suivante. # # Node ≥ 20.6 requis : les variables ne sont PAS chargées automatiquement en # production, d'où --env-file. [Unit] Description=Veille législative — application web Documentation=file:///opt/veille-legislative/README.md Requires=veille-web.socket After=network.target veille-web.socket [Service] Type=simple User=veille Group=veille WorkingDirectory=/opt/veille-legislative/web # `env` plutôt qu'un chemin figé : NodeSource installe dans /usr/bin, une # compilation manuelle dans /usr/local/bin, et les deux sont dans le PATH par # défaut de systemd. Un chemin en dur échouerait sur la moitié des machines. ExecStart=/usr/bin/env node --env-file=/opt/veille-legislative/.env build Environment=NODE_ENV=production Environment=VEILLE_DB=/opt/veille-legislative/data/veille.db # Mise en sommeil après cinq minutes sans requête. Environment=IDLE_TIMEOUT=300 # ── Origine des requêtes, derrière un reverse proxy ────────────────────────── # # Sans indication d'origine, adapter-node refuse les soumissions de formulaire # (« Cross-site POST form submissions are forbidden »). # # Deux façons de la lui donner. On retient ici celle qui ne dépend pas du # domaine : l'application déduit l'origine des en-têtes que pose le reverse # proxy. Cette unité fonctionne donc telle quelle, quel que soit le domaine — # aucun fichier versionné n'est à éditer au déploiement. # # Ces en-têtes ne sont dignes de confiance que parce que l'application n'écoute # que sur 127.0.0.1 (voir veille-web.socket) : seul le proxy local peut les # poser. Exposer directement le port rendrait l'origine falsifiable par le # client — ne le faites pas. # # Le reverse proxy DOIT poser ces trois en-têtes ; les exemples nginx et Caddy # du README le font. Environment=PROTOCOL_HEADER=x-forwarded-proto Environment=HOST_HEADER=x-forwarded-host Environment=ADDRESS_HEADER=x-forwarded-for Environment=XFF_DEPTH=1 # Alternative : figer l'origine au lieu de la déduire. Renseignez # ORIGIN=https://votre-domaine dans /opt/veille-legislative/.env ; adapter-node # la retient d'office, sa résolution s'écrivant `origin || get_origin(headers)`. # # Cela ne fonctionne QUE parce que ORIGIN n'est pas déclarée ci-dessus : le # `--env-file` de Node ne remplace pas une variable déjà présente dans # l'environnement, c'est l'environnement qui gagne (vérifié sur Node 24). Ne # déclarez donc jamais ORIGIN ici, sinon le fichier .env resterait sans effet. Restart=on-failure RestartSec=5 # Durcissement : l'application ne fait que lire la base. NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadOnlyPaths=/opt/veille-legislative/data ProtectKernelTunables=true ProtectKernelModules=true ProtectControlGroups=true RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX RestrictNamespaces=true LockPersonality=true StandardOutput=journal StandardError=journal SyslogIdentifier=veille-web [Install] WantedBy=multi-user.target