Sous le capot, la qualité technique du serveur

Tout ce qui tourne en coulisses sur votre serveur IA, reproductibilité NixOS, durcissement ANSSI, chiffrement age, backups chiffrés, passerelle LLM, monitoring et automatisations. La page pour les techniciens.

Sous le capot

Cette page est un inventaire technique, sans filtre marketing. Chaque point ci-dessous correspond à du code réel, déclaratif et reproductible, déployé sur votre serveur. C'est ce qui distingue une infrastructure d'ingénieur d'un simple VPS configuré à la main.

Le système entier est décrit en NixOS. Tout ce qui suit est déclaratif, versionné et reproductible à l'identique sur n'importe quelle machine.


Reproductibilité & architecture NixOS

  • Flake consommable, Sur chaque serveur, /etc/nixos/ ne contient que 3 fichiers : flake.nix, flake.lock, server.nix. Toute la logique (modules, apps, scripts) vient du flake en dépendance. Modifier le serveur = éditer un seul fichier server.nix puis nixos-rebuild switch.
  • Mises à jour atomiques + rollback, Chaque génération du système est une entrée de boot indépendante. Une mise à jour ratée se rollback instantanément en redémarrant sur la génération précédente. Aucun état intermédiaire cassé possible.
  • Empreinte Git dans chaque génération, system.configurationRevision injecte le hash Git du flake dans chaque build. On sait exactement quel code a produit l'état courant du serveur.
  • Double nixpkgs, épinglable par app, Chaque application peut être figée sur un canal (stable / unstable) ou sur une révision exacte (pin.commit / pin.hash), sans toucher au flake.nix. On isole une app sur une version stable pendant que le reste tourne en unstable.
  • Partitionnement déclaratif (disko), Le découpage disque (GPT + ESP + ext4) est décrit en Nix et appliqué automatiquement à l'installation par nixos-anywhere. Zéro fdisk manuel.
  • Auto-découverte des modules, Le système scanne apps/ et importe automatiquement toute app contenant un default.nix. Ajouter une app ne demande aucun import manuel.
  • Installation à distance, Déploiement complet d'un serveur nu (partitionnement + OS + apps) en une commande via nixos-anywhere, depuis un simple accès SSH root en rescue.

Sécurité & durcissement

  • Durcissement en 3 niveaux (minimal / standard / reinforced) inspiré des recommandations ANSSI (R8–R14) et de l'audit Lynis, cumulatif.
  • Mitigations CPU au boot, pti=on, spectre_v2=on, l1tf=full,force, mds=full,nosmt (Spectre / Meltdown / MDS / L1TF). En mode renforcé : slab_nomerge, page_alloc.shuffle=1, init_on_alloc=1.
  • Durcissement systemd des services, En mode renforcé, ~16 directives appliquées (ex. sur Caddy) : PrivateTmp, PrivateDevices, ProtectSystem=strict, NoNewPrivileges, MemoryDenyWriteExecute, etc.
  • Profil Lynis sur mesure pour NixOS, Un profil custom.prf avec 18 règles documentées adaptées aux spécificités NixOS (store immutable, nftables, comptes système verrouillés). Audit + score /100 à la demande.
  • auditd avec règles progressives, Surveillance de passwd/group/shadow/sudoers, et en mode renforcé : accès aux secrets, chargement de modules kernel, mounts, changements d'horloge, exécutions en euid=0.
  • SSH durci, Port non-standard (10234 par défaut), PermitRootLogin no, PasswordAuthentication false, pas de TCP/agent forwarding, MaxAuthTries 3, log du MAC de clé. Option « clé matérielle uniquement » (FIDO2 / ed25519-sk).
  • fail2ban à bantime exponentiel, Multiples de ban 1× → 64× jusqu'à 168 h (1 semaine), compteur global partagé entre toutes les jails.
  • sudo granulaire, Tout est NOPASSWD sauf les opérations destructives (rm, dd, mkfs, fdisk, useradd…) et l'arrêt des services critiques (postgresql, caddy, fail2ban), qui exigent le mot de passe.
  • Blacklist kernel étendue, Désactivation de filesystems rares et de ~14 protocoles réseau legacy (dccp, sctp, rds, tipc, ax25, x25, decnet, ipx, appletalk…).
  • Scan CVE du store Nix (vulnix), Croisement des paquets installés avec la base NVD, à la demande, exportable en JSON pour la CI.
  • Politique mots de passe, SHA_CRYPT_MIN_ROUNDS=5000, expiration à 365 j, acct (process accounting) et sysstat activés.
  • Firewall minimal, Seuls SSH (port custom), 80 et 443 sont ouverts. Le port 22 standard est fermé.

Chiffrement & gestion des secrets

  • Chiffrement age via la clé SSH de l'hôte, Les secrets sont chiffrés avec age en utilisant la clé ed25519 du serveur comme clé publique. Pas de vault externe, pas de clé séparée à gérer : la clé d'identité du serveur est la clé de déchiffrement.
  • /run/secrets en tmpfs strict, Les secrets déchiffrés au boot vivent en RAM uniquement (mode=0751, nodev, nosuid, noexec, 16 Mo). Ils ne touchent jamais le disque et disparaissent au reboot.
  • Helper encrypt-secret, Une commande sur le serveur prend un fichier, le chiffre vers /etc/secrets/<nom>.age et le rend disponible immédiatement en clair dans /run/secrets/.
  • Secrets jamais dans le store, Le token d'accès au flake privé est chargé dans nix.conf via !include /run/secrets/... : il ne passe jamais par le Nix store (qui est immutable et lisible par tous).
  • Secrets auto-générés, Les clés sensibles (secret key Grafana, clé RSA 4096 du cache Nix Attic…) sont générées au premier boot puis chiffrées en age. Rien à préconfigurer.

Sauvegardes

  • Restic vers S3, chiffré, Deux dépôts distincts : dumps PostgreSQL (2 h) et état système complet /var/lib + /home + /etc/secrets (3 h). Tout est chiffré côté client avant l'envoi.
  • Rétention documentée, 7 quotidiennes, 4 hebdomadaires, 6 mensuelles, puis prune automatique.
  • Dump PostgreSQL natif avant restic, pg_dump programmé en amont du backup restic pour des snapshots cohérents de la base.
  • Vérification d'intégrité hebdomadaire, Timer restic-check chaque dimanche, vérifiant 10 % des données par défaut (couverture complète du dépôt sur 10 semaines), pourcentage paramétrable.
  • Alerting healthchecks.io, Ping de succès et de /fail sur chaque unité de backup en erreur. Si une sauvegarde ne tourne pas, vous le savez.
  • UI web optionnelle (Backrest), Gestion graphique des snapshots restic.

IA & LLM

  • Bifrost, passerelle LLM unifiée, Une seule API compatible OpenAI pour 15+ fournisseurs (OpenAI, Anthropic, Bedrock, Vertex, OpenRouter, Ollama, Groq, Gemini, Mistral, Cerebras, Cohere…). Écrit en Go : ~10–20 µs de latence ajoutée, 50–150 Mo de RAM. Virtual keys avec budgets, routing rules, dashboard.
  • Agrégateur de LLM gratuits, Un script idempotent détecte vos clés free-tier (Groq, Gemini, Mistral, Cerebras, Cohere, OpenRouter) et configure automatiquement 4 routes : free-llm (généraliste), free-fast (ultra-rapide), free-best (fallback vers le meilleur), free-code (modèles de code). Llama 3.3 70B, Gemini 2.5 Flash, Codestral, Qwen3, DeepSeek… gratuitement, derrière une API unique.
  • Agrégation MCP, Tous les serveurs MCP des apps activées sont exposés derrière une seule URL https://bifrost.<domaine>/mcp. Claude Code et tout client MCP voient l'ensemble des outils du serveur en une seule connexion.
  • LLM 100 % local (Ollama), Llama, Mistral, Gemma exécutés sur le serveur, sans API cloud ni coût par token. Vos données ne sortent jamais.
  • Agent IA messagerie (Hermes), Agent connecté à Telegram / WhatsApp, modèle configuré déclarativement, secret chiffré en age.
  • Observabilité LLM dans Grafana, Si Grafana et Bifrost coexistent, un dashboard est provisionné automatiquement : latences, tokens in/out, coût cumulé, fallbacks, cache hits, usage par clé.

Réseau & reverse proxy

  • Caddy avec HTTPS automatique, Certificats Let's Encrypt par défaut, et certificats wildcard via Cloudflare DNS-01 quand un token est fourni. Aucune configuration TLS manuelle.
  • En-têtes de sécurité sur tous les vhosts, HSTS (max-age=31536000; includeSubDomains; preload), X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, Referrer-Policy, Permissions-Policy, suppression du header Server.
  • Persistance des certificats, /var/lib/caddy survit aux rebuilds via bind mount, pour ne pas re-solliciter Let's Encrypt (et éviter les rate limits).
  • DNS local automatique, Les domaines des apps activées sont résolus en 127.0.0.1 au build. Une app peut appeler le webhook d'un autre service local par son domaine, sans aller-retour DNS externe.
  • Compression et restauration d'IP, zstd+gzip automatique sur chaque vhost ; en mode Cloudflare, restauration des IP réelles via trusted_proxies (plages CIDR officielles).
  • Helpers Caddy réutilisables, Les apps appellent mkVhost { domain, port } au lieu d'écrire du Caddyfile brut. La couche d'auth SSO (forward_auth Authelia) s'injecte de façon transparente quand elle est activée.

Base de données

  • Version PostgreSQL épinglée, Le package est forcé (mkOverride 900) : un nixos-rebuild ne peut pas faire un upgrade majeur silencieux. Changer de version demande un pg_upgrade explicite.
  • Extensions mutualisées et dédupliquées, Les apps déclarent leurs extensions requises ; elles sont fusionnées avec les vôtres et le paquet PostgreSQL final est construit une seule fois (pgvector, PostGIS, TimescaleDB, pg_cron…).
  • Auth peer par socket Unix, Les apps se connectent sans mot de passe réseau (nom d'utilisateur système = rôle PostgreSQL). Rien à stocker dans les secrets.
  • Observabilité SQL, Avec le monitoring : pg_stat_statements (toutes les requêtes) et logging des requêtes lentes (> 100 ms).

Monitoring & observabilité

  • Stack complète en un commutateur, grafana.enable = true déploie Grafana + Prometheus (node / process / postgres exporters) + Loki + Alloy (shipping de logs).
  • Alertes pré-configurées, CPU > 80 % (2 min), RAM > 90 % (5 min), disque > 85 % (5 min), service systemd down (1 min).
  • Pipeline de logs, Alloy expédie le journal systemd (labellisé par unit) et les logs JSON de Caddy (avec parsing status / uri / remote_ip / duration) vers Loki.
  • Dashboards bundlés, Vue d'ensemble serveur, PostgreSQL et Bifrost provisionnés automatiquement (conditionnels selon les apps actives). Zéro clic dans l'UI.
  • MOTD à sondes HTTP, À chaque connexion SSH, le message d'accueil affiche l'état réel de chaque app (point vert/rouge selon une vraie requête HTTP locale).
  • Monitoring léger (Beszel), Alternative ou complément à la stack Grafana, avec agent intégré.

Isolation & attribution des ports

  • Une app = un utilisateur système, Chaque service tourne sous son propre utilisateur isolé, avec sandboxing systemd. Une app compromise n'atteint ni les autres apps ni les données du serveur.
  • Registre de ports append-only, Attribution déterministe et figée : apps en 10000–10999, sites web en 11000–11999, WordPress en 12000–12999. Une assertion Nix échoue au build si un port sort de sa plage.
  • Détection de conflits au build, Les ports auto-assignés sont validés contre les ports configurables (SSH, etc.). Un conflit casse le build, jamais la production.
  • Ports en lecture seule, L'utilisateur ne configure pas les ports internes : ils sont gérés par le système, sans collision possible.

SSO & identité

  • OIDC centralisé (Authelia), Chaque app contribue déclarativement son client OIDC et ses règles d'accès par groupe. Hash de mots de passe en argon2.
  • Deux modes SSO par app, authelia (exclusif) ou authelia-staff (additif, en conservant les comptes locaux).
  • Attribution de rôle automatique, Ex. les membres du groupe admin sont promus GrafanaAdmin automatiquement via une expression JMESPath.

Expérience développeur & automatisation

  • Maskfiles, Les tâches sont définies dans des fichiers maskfile.md lisibles (un maskfile dev, un maskfile serveur). mask rebuild, mask logs -S caddy, mask backup, mask audit security, mask ports… Chaque tâche délègue à un script, pas de logique inline.
  • mask preview avant rebuild, Build sans activer + nvd diff (diff lisible des paquets) + dry-activate (liste des services qui seront redémarrés). On voit l'impact exact avant d'appliquer.
  • Skills IA par app (symlinks), Le home déployé contient 45+ fichiers SKILL.md (un par app), versionnés dans un dépôt séparé et synchronisés via git subtree + bare repo. L'IA du serveur sait piloter chaque app via son API. Mise à jour sans toucher à la config NixOS.
  • Token killer (RTK), Un hook PreToolUse filtre la sortie des commandes shell de l'IA pour économiser 60–90 % de tokens sur les opérations de dev.
  • Suite de tests NixOS (~75 tests), Chaque app a son test en VM légère (démarrage, endpoints, API), plus des tests d'intégration (ex. n8n + Bifrost + MCP). Les ports sont injectés depuis le registre, jamais hardcodés.
  • Tests locaux conteneur + VM, Conteneur NixOS (démarrage en 5–10 s) pour itérer vite, VM QEMU (isolation complète) pour valider. mask vm rebuild enchaîne stop / clean / build / run.
  • Cache Nix self-hosted (Attic), Cache de binaires pour accélérer les builds CI, injecté dans nix.conf via !include.
  • CI intégrée (Woodpecker + Forgejo), OAuth configuré automatiquement, agent embarquant nix/git/lfs, pipelines Nix natifs. Git hooks installables via mask dev setup.
  • Gestion mémoire en 4 couches, zram (25 % de RAM compressée, ~×3) → swap disque (4 Go) → earlyoom (kill à 8 % RAM / 5 % swap libres) pour éviter tout gel kernel.
  • ACL POSIX sur /etc/nixos, Héritage g:wheel:rwx sur les fichiers utilisateur, scripts système en root:root. Les admins éditent leur config sans sudo.
  • Cohérence du code, treefmt + .editorconfig ; formatage Nix d'une commande.

En une phrase

Un serveur déclaratif de bout en bout : sécurité de niveau ANSSI, secrets chiffrés par l'identité de la machine, sauvegardes chiffrées vérifiées, passerelle vers des LLM (y compris gratuits), monitoring complet et une IA qui connaît chaque application, le tout reproductible à l'identique, versionné, et restaurable d'un redémarrage.

Copyright © 2026