Modules de service
✨ darkone.service.adguardhome
Section intitulée « ✨ darkone.service.adguardhome »AdGuard Home entièrement configuré pour passerelle / routeur local.
- enable
boolActive le service adguardhome local
darkone.service.adguardhome.enable = false;✨ darkone.service.ai
Section intitulée « ✨ darkone.service.ai »Intelligence artificielle locale (open-webui + ollama + llms).
- enable
boolActiver le service d’IA local
darkone.service.ai.enable = false;✨ darkone.service.audio
Section intitulée « ✨ darkone.service.audio »Services audio : alsa, pulse (pas jack pour le moment).
Ajoute automatiquement les utilisateurs au groupe audio quand il est activé.
- enable
boolActiver le système sonore
darkone.service.audio.enable = false;✨ darkone.service.dnsmasq
Section intitulée « ✨ darkone.service.dnsmasq »dnsmasq pré-configuré pour la passerelle / routeur local.
- enable
boolActive le service dnsmasq local
darkone.service.dnsmasq.enable = false;✨ darkone.service.docs
Section intitulée « ✨ darkone.service.docs »Un module LaSuite Docs entièrement configuré.
- enable
boolActiver le service de documentation local - s3Host
strNom d’hôte du backend S3 - s3Port
portPort du backend S3 - s3Bucket
strNom du bucket S3 pour le stockage des documents
darkone.service.docs = { enable = false; s3Host = "127.0.0.1"; s3Port = dnfConfig.network.ports.garage; s3Bucket = "docs";};✨ darkone.service.element
Section intitulée « ✨ darkone.service.element »Client web Element pour le service matrix local.
- enable
boolActiver le service element local
darkone.service.element.enable = false;✨ darkone.service.fail2ban
Section intitulée « ✨ darkone.service.fail2ban »Module fail2ban spécifique à DNF.
- enable
boolActiver fail2ban avec les spécificités DNF
darkone.service.fail2ban.enable = false;✨ darkone.service.forgejo
Section intitulée « ✨ darkone.service.forgejo »Une forge git forgejo entièrement configurée.
- enable
boolActive le service forgejo local
darkone.service.forgejo.enable = false;✨ darkone.service.garage
Section intitulée « ✨ darkone.service.garage »Un service Garage S3 local entièrement configuré.
Fournit un stockage d’objets interne compatible S3 accessible uniquement sur 127.0.0.1:3900.
- enable
boolActiver le service Garage S3 local - srvPort
portPort de l’API S3 exposé sur l’IP interne - s3Region
strNom de la région S3 (doit correspondre à la config du consommateur) - capacity
strIndication de capacité de stockage du nœud transmise àgarage layout assign. Utilisée uniquement au premier démarrage pour l’initialisation du layout ; n’agit pas comme un quota strict sur le système de fichiers sous-jacent. Suffixes pris en charge : B, KB, MB, GB, TB, PB.
darkone.service.garage = { enable = false; srvPort = srvPort; s3Region = s3Region; capacity = "500GB";};✨ darkone.service.geneweb
Section intitulée « ✨ darkone.service.geneweb »GeneWeb — Service de généalogie puissant.
- enable
boolActiver le service de généalogie GeneWeb local - enablePasswords
boolActiver les mots de passe sops (non recommandé)
darkone.service.geneweb = { enable = false; enablePasswords = false;};✨ darkone.service.harmonia
Section intitulée « ✨ darkone.service.harmonia »Harmonia : serveur local de cache binaire Nix (sert le /nix/store de cet hôte).
Expose les chemins du store locaux construits / réalisés en HTTP simple (port
5000), signés avec la clé de cache binaire propre au déploiement. Active par
hôte depuis etc/config.yaml (services.harmonia), comme tout autre service DNF.
- enable
boolActiver un serveur de cache binaire Nix Harmonia local
darkone.service.harmonia.enable = false;✨ darkone.service.headscale.audit
Section intitulée « ✨ darkone.service.headscale.audit »DNF headscale : headscale-audit. Doc : en-tête de ../headscale.nix.
✨ darkone.service.headscale.dns
Section intitulée « ✨ darkone.service.headscale.dns »DNF headscale : DNS pivot du tailnet. Doc : en-tête de ../headscale.nix.
✨ darkone.service.headscale.enroll
Section intitulée « ✨ darkone.service.headscale.enroll »DNF headscale : dnf-tailnet-enroll. Doc : en-tête de ../headscale.nix.
✨ darkone.service.headscale
Section intitulée « ✨ darkone.service.headscale »Un service headscale entièrement configuré pour le HCS.
La politique ACL du tailnet est générée depuis la topologie (zones, hôtes,
utilisateurs) par dnfLib.mkHeadscalePolicy, validée par headscale policy check
à la construction, puis rechargée au changement (SIGHUP) sans redémarrer headscale.
- Les machines sont taguées :
tag:hcs,tag:gw-<zone>,tag:admin(hôte dontgroupscontientadmin). - Les machines et les LAN de zone joignent les autres. Appareils personnels : DNS
et HTTPS sur le HCS, HTTPS sur les passerelles de zone (toutes les zones pour
les admin, sinon leurs groupes
zone-*). SSH depuis les postes d’admin etpolicy.adminDevices. - Les appareils personnels se connectent via Kanidm (OIDC), pour les membres du
groupe Kanidm
tailnet; leurs clés expirent aprèsnodeExpiry.
darkone.service.headscale.policy.adminDevices.phone-alice = "100.64.0.9";Sous-modules (headscale/) :
dns.nix: unbound, le DNS pivot du tailnet et sa vuetailnet-machines;audit.nix:headscale-audit, nœuds actifs confrontés à la topologie déclarée ;enroll.nix:dnf-tailnet-enroll, derrièrejust tailnet-enroll.
DNS pivot (dns.nix)
Section intitulée « DNS pivot (dns.nix) »unbound sur le HCS. Les noms internes l’atteignent par le split DNS de headscale ; il relaie chaque domaine de zone vers la passerelle de zone, le reste vers Quad9 par TLS.
Vue tailnet-machines : les nœuds tagués (HCS mis à part) reçoivent l’adresse
LAN de zone des services globaux qu’une zone dessert (git.<domain> sur une
passerelle), tous les autres reçoivent l’adresse publique.
unbound-tailnet-view liste leurs IP de tailnet depuis headscale, déclarées
nulle part ailleurs.
Audit (audit.nix)
Section intitulée « Audit (audit.nix) »headscale-audit, toutes les 15 min : nœuds actifs confrontés à la topologie
déclarée. Métriques pour les alertes dnf-headscale-<zone>, détails dans son
journal. Ne tague ni ne supprime jamais.
Enrôlement (enroll.nix)
Section intitulée « Enrôlement (enroll.nix) »dnf-tailnet-enroll, côté root de just tailnet-enroll : clés à usage unique
taguées depuis la topologie déclarée ; le nœud enrôlé reçoit son nom et ses
tags déclarés.
- enable
boolActiver le service DNF headscale - enableGRPC
boolOuvrir le port TCP GRPC - nodeExpiry
strExpiration des clés des appareils personnels (0: jamais). Les machines taguées n’expirent jamais. - policy.enforce
boolACL du tailnet en refus par défaut.falseautorise tout trafic, pour une migration uniquement. - policy.adminDevices
attrsAppareils personnels autorisés en SSH sur chaque machine et zone : nom -> IPv4 de tailnet. - policy.exitNodeSources
listOf strSources de politique autorisées à utiliser le HCS comme nœud de sortie. - policy.extraHosts
attrsAlias d’hôte de politique supplémentaires (nom -> CIDR), à utiliser dansextraAcls. - policy.extraAcls
listOf (attrsOf anything)Règles ACL ajoutées après celles générées. - shared
rawValeurs headscale partagées avec les sous-modulesheadscale/.
darkone.service.headscale = { enable = false; enableGRPC = false; nodeExpiry = "180d"; policy.enforce = true; policy.adminDevices = { }; policy.exitNodeSources = [ ]; policy.extraHosts = { }; policy.extraAcls = [ ]; shared = { inherit policy auditSpec idmUrl hcsTailnetIpv4 ; };};✨ darkone.service.home-assistant
Section intitulée « ✨ darkone.service.home-assistant »Un Home Assistant avec certains plugins (en cours).
- enable
boolActiver home-assistant
darkone.service.home-assistant.enable = false;✨ darkone.service.homepage
Section intitulée « ✨ darkone.service.homepage »Tableau de bord de page d’accueil configuré dynamiquement pour votre réseau local.
- enable
boolActiver le tableau de bord de la page d’accueil + httpd + hôte - protect
boolRestreindre la page d’accueil aux utilisateurs Kanidm authentifiés (oauth2-proxy forward auth) - localServices
listOf attrsServices à ajouter dans la section Applications locales - globalServices
listOf attrsServices communs du réseau & accessibles publiquement - remoteServices
listOf attrsServices à ajouter dans la section Applications distantes - bookmarks
listOf attrsRemplacer les favoris par défaut (liens) - widgets
listOf attrsRemplacer les widgets par défaut
darkone.service.homepage = { enable = false; protect = true; localServices = [ ]; globalServices = [ ]; remoteServices = [ ]; bookmarks = [ ]; widgets = [ ];};✨ darkone.service.idm.provision
Section intitulée « ✨ darkone.service.idm.provision »DNF idm : provision Kanidm. Doc : en-tête de ../idm.nix.
- oauth2
attrsGabarits de client OAuth2/OIDC fournis par les modules de service. Kanidm provisionne un client par entrée correspondante dansnetwork.services, avecclientId = dnfLib.oauth2ClientName.- enable
boolProvisionner ou non des clients OAuth2 pour ce gabarit. - clientName
nullOr strRemplace le nom de client kanidm. Par défaut dnfLib.oauth2ClientName. - displayName
strNom lisible affiché sur l’écran de consentement kanidm. - imageFile
pathIcône de l’application. Renvoyée à chaque exécution de kanidm-provision. - redirectPaths
listOf strChemins de redirection OAuth2 (un par URL de rappel acceptée). - landingPath
strChemin du point d’entrée de connexion automatique sur le service. - enableLegacyCrypto
boolAutoriser les algorithmes de signature JWT hérités (ex. RS256). - allowInsecureClientDisablePkce
boolDésactiver PKCE sur le client (uniquement pour les clients qui ne l’implémentent pas). - preferShortUsername
nullOr boolUtiliser le nom d’utilisateur court (sans domaine) dans la revendicationpreferred_username. - extra
attrsAttributs supplémentaires fusionnés dans le client provisionné (claimMaps, etc).
- enable
darkone.service.idm.provision = { oauth2.enable = true; oauth2.clientName = null; oauth2.displayName = null; oauth2.imageFile = null; oauth2.redirectPaths = [ ]; oauth2.landingPath = "/"; oauth2.enableLegacyCrypto = false; oauth2.allowInsecureClientDisablePkce = false; oauth2.preferShortUsername = null; oauth2.extra = { };};✨ darkone.service.idm.replication
Section intitulée « ✨ darkone.service.idm.replication »DNF idm : réplication Kanidm. Doc : en-tête de ../idm.nix.
- replication
rawFaits de réplication de ce nœud.
darkone.service.idm.replication.replication = { inherit isMainReplica isReplConsumer; };✨ darkone.service.idm
Section intitulée « ✨ darkone.service.idm »Service DNF Kanidm (gestionnaire d’identités).
Sous-modules (idm/) :
replication.nix: réplication en lecture seule multi-zones, du HCS vers les passerelles de zone ;provision.nix: clients OAuth2 (registre de gabarits), groupes et personnes.
Réplication (replication.nix)
Section intitulée « Réplication (replication.nix) »Automatique, dérivée de l’endroit où idm est déclaré :
- idm sur le HCS seul, ou sur une passerelle sans HCS : une instance ;
- sur le HCS et >= 1 passerelle de zone : le HCS fournit (WriteReplica), chaque passerelle idm consomme.
Amorçage en deux temps : just apply génère tous les certificats de réplication
(les passerelles restent WriteReplicaNoUI), puis just idm-sync-certs +
just apply ajoute les partenaires et fait basculer les passerelles en
ReadOnlyReplica.
Provisionnement (provision.nix)
Section intitulée « Provisionnement (provision.nix) »Chaque module de service compatible OIDC contribue un modèle de client à
darkone.service.idm.oauth2 ; un client est provisionné par (modèle,
instance), fusionné par clientId à travers les zones. Jamais sur un
consommateur de réplication : il reflète le HCS.
- enable
boolActiver le SSO local avec Kanidm
darkone.service.idm.enable = false;✨ darkone.service.immich
Section intitulée « ✨ darkone.service.immich »Service Immich (gestion de photos) entièrement configuré.
- enable
boolActiver le service immich local - enableMachineLearning
boolActiver les fonctionnalités d’apprentissage automatique (reconnaissance faciale, détection d’objets) - enableRedis
boolActiver Redis pour la mise en cache (recommandé pour les performances)
darkone.service.immich = { enable = false; enableMachineLearning = false; enableRedis = false;};✨ darkone.service.jellyfin
Section intitulée « ✨ darkone.service.jellyfin »Un serveur jellyfin entièrement configuré.
- enable
boolActiver le service jellyfin
darkone.service.jellyfin.enable = false;✨ darkone.service.jitsi-meet
Section intitulée « ✨ darkone.service.jitsi-meet »Un service jitsi-meet entièrement configuré.
- enable
boolActiver le service jitsi-meet local
darkone.service.jitsi-meet.enable = false;✨ darkone.service.loki
Section intitulée « ✨ darkone.service.loki »Loki + Alloy, statistiques HTTP avec Grafana.
- enable
boolDéploie le serveur Loki + le datasource Grafana (co-localisé avec Grafana). - isClient
boolDéploie Alloy pour collecter les logs d’accès Caddy locaux. - retentionTime
strDurée de rétention des logs dans Loki (30 jours par défaut).
darkone.service.loki = { enable = config.darkone.service.monitoring.enable; isClient = config.services.caddy.enable && hasMonitoringHost; retentionTime = "720h";};✨ darkone.service.matrix.bridges
Section intitulée « ✨ darkone.service.matrix.bridges »DNF matrix : ponts mautrix. Doc : en-tête de ../matrix.nix.
✨ darkone.service.matrix.mas
Section intitulée « ✨ darkone.service.matrix.mas »DNF matrix : authentification déléguée à MAS. Doc : en-tête de ../matrix.nix.
✨ darkone.service.matrix.rtc
Section intitulée « ✨ darkone.service.matrix.rtc »DNF matrix : appels MatrixRTC (LiveKit). Doc : en-tête de ../matrix.nix.
✨ darkone.service.matrix
Section intitulée « ✨ darkone.service.matrix »Service matrix (synapse) DNF avec les ponts mautrix.
Les ponts (whatsapp, signal, telegram, messenger, discord) sont utilisables par tous les comptes locaux : chaque utilisateur lie son propre compte distant en dialoguant avec le bot du pont (@whatsappbot, @signalbot, … puis login) ; les sessions sont isolées par utilisateur. Les network.matrix.admins déclarés administrent les ponts et le serveur (cf. « Administrateurs » ci-dessous).
Le double puppeting utilise la méthode officielle appservice
(https://docs.mau.fi/bridges/general/double-puppeting.html 🡕) : un token appservice doublepuppet partagé permet aux ponts d’envoyer les messages d’origine distante sous le vrai compte matrix de l’utilisateur. Secrets sops requis :
mautrix-doublepuppet-as-token et mautrix-doublepuppet-hs-token
(openssl rand -hex 32 chacun).
Les tokens as/hs de chaque pont sont fournis par sops plutôt que générés automatiquement : le fichier de registration devient une pure fonction des secrets, donc réinitialiser le répertoire d’état d’un pont n’invalide jamais la registration chargée par synapse (sinon il faudrait purger la registration + redémarrer synapse, ce qui produirait des erreurs « as_token was not accepted »).
✨ darkone.service.matrix
Section intitulée « ✨ darkone.service.matrix »DNF matrix (synapse) homeserver.
Sous-modules (matrix/) :
mas.nix: authentification, déléguée au Matrix Authentication Service ;bridges.nix: ponts mautrix, utilisables par tout compte local ;rtc.nix: backend MatrixRTC (LiveKit) pour Element Call.
Fédération
Section intitulée « Fédération »La fédération est configurable via darkone.service.matrix.federation :
enable = false: bloque toute la fédération (liste blanche de domaines vide).enable = true; whitelist = [ ]: fédération ouverte avec tous les serveurs.enable = true; whitelist = [ "ami.org" ]: liste blanche (entrante + sortante).
La découverte reste verrouillée quoi qu’il arrive (salons absents des répertoires distants, profils privés sur la fédération), si bien que le réseau est joignable mais pas consultable.
L’auto-inscription des amis (friendRegistration.enable) ouvre des comptes
mot de passe locaux conditionnés par un jeton, en parallèle des utilisateurs
OIDC Kanidm. Fabriquer un jeton sur l’hôte avec
sudo dnf-mas manage issue-user-registration-token.
Administrateurs
Section intitulée « Administrateurs »network.matrix.admins (parties locales) est la source déclarative unique
des deux administrations, appliquée à la reconstruction sans écriture en
base :
- ponts : niveau
admindans chaque cartepermissionsmautrix ; - serveur :
policy.data.admin_users, que la politique MAS fournie transforme en scopesurn:mas:admineturn:synapse:admin:*(API admin MAS, API admin synapse, connexion à l’UImatrix-admin).
Authentification (mas.nix)
Section intitulée « Authentification (mas.nix) »Toute l’authentification passe toujours par le Matrix Authentication
Service : Element X, la connexion par QR code et le portail d’auto-service
/account n’existent que là, et l’auth propre à synapse est dépréciée en
amont (MSC3861). Kanidm reste la source d’identité : MAS est le client OIDC
à la place de synapse, et synapse ne fait qu’interroger MAS pour introspecter
les jetons.
Même vhost : MAS détient les points d’auth racine + compat, synapse garde
/_matrix/* et /_synapse/*. La découverte des clients est automatique
(synapse sert lui-même auth_metadata), aucun changement de well-known.
Secrets sops requis, tous créés par just configure-admin-host :
mas-encryption-secret, mas-synapse-secret et mas-rsa-private-key.
dnf-mas (root) enveloppe mas-cli pour l’administration côté hôte : jetons
d’inscription, promote-admin, register-user, syn2mas. MAS tourne avec
DynamicUser et lit ses secrets depuis les credentials systemd, absents hors
de l’unité en cours ; le wrapper reconstruit un répertoire de credentials
équivalent à partir des fichiers sops, donc fonctionne que le service soit en
service ou non (syn2mas l’exige à l’arrêt).
mas-cli n’agit que, jamais de listage : activer le service matrix-admin
pour le côté lecture (comptes, appareils, sessions), il parle les deux API
admin.
Ponts (bridges.nix)
Section intitulée « Ponts (bridges.nix) »Ponts mautrix : WhatsApp, Signal, Telegram, Messenger, Discord. Chaque
utilisateur lie son propre compte distant en parlant au bot du pont
(@whatsappbot, @signalbot, … puis login) ; les sessions sont isolées
par utilisateur. Administrateurs des ponts : cf. « Administrateurs » ci-dessus.
Double puppeting : méthode officielle appservice
(https://docs.mau.fi/bridges/general/double-puppeting.html 🡕). Un jeton
appservice doublepuppet partagé permet aux ponts d’envoyer des messages à
origine distante sous le vrai compte matrix de l’utilisateur. Secrets sops
requis : mautrix-doublepuppet-as-token et mautrix-doublepuppet-hs-token
(générés par just configure-admin-host).
Les jetons as/hs appservice de chaque pont proviennent de sops, jamais auto-générés : le fichier de registration est une fonction pure des secrets, si bien qu’effacer le répertoire d’état d’un pont n’invalide jamais la registration chargée par synapse (« as_token was not accepted », effacement de la registration + redémarrage de synapse).
Appels (rtc.nix)
Section intitulée « Appels (rtc.nix) »Deux stacks coexistent, car aucune seule ne couvre tous les clients :
- WebRTC 1:1 historique, négocié via synapse et relayé par coturn
(
darkone.service.turn). La seule chose que parle Element Classic. - MatrixRTC (
matrixRtc.enable) : un SFU LiveKit plus son service d’autorisation, pour les appels de groupe et Element Call. Element X ne parle que celui-là et affiche « call is not supported » (MISSING_MATRIX_RTC_TRANSPORT) sans lui ; Element Web/Desktop intègrent aussi Element Call et en gagnent les appels de groupe.
Les deux sont servis depuis le vhost matrix, à côté de synapse et MAS : le
websocket du SFU sur /livekit/sfu, le service JWT sur /livekit/jwt. Les
clients le découvrent via matrix_rtc.transports (synapse, MSC4143) et, en
repli pour les plus anciens, via rtc_foci dans le well-known.
Secret sops requis : livekit-secret (just configure-admin-host), partagé
par le SFU et le service JWT.
- enable
boolActiver le service matrix (synapse) - federation.enable
boolAutoriser la fédération serveur-à-serveur. False bloque toute la fédération. - federation.whitelist
listOf strVide = fédérer avec tous les serveurs ; non vide = seulement ces domaines (entrant + sortant). - matrixRtc.enable
boolActiver le backend MatrixRTC (SFU LiveKit) pour les appels de groupe Element Call. - friendRegistration.enable
boolAutoriser les amis à s’auto-inscrire avec un jeton d’invitation (conditionné par jeton). - bridges.whatsapp.enable
boolPont Mautrix WhatsApp (connexion par QR code). - bridges.signal.enable
boolPont Mautrix Signal (connexion par QR code). - bridges.telegram.enable
boolPont Mautrix Telegram (connexion par numéro de téléphone). - bridges.messenger.enable
boolPont Mautrix Facebook Messenger (connexion par cookies). - bridges.discord.enable
boolPont Mautrix Discord (connexion par QR code, expérimental). - shared
rawValeurs matrix partagées avec les sous-modulesmatrix/.
darkone.service.matrix = { enable = false; federation.enable = false; federation.whitelist = [ ]; matrixRtc.enable = false; friendRegistration.enable = false; bridges.whatsapp.enable = true; bridges.signal.enable = true; bridges.telegram.enable = true; bridges.messenger.enable = true; bridges.discord.enable = false; shared = { inherit params masKanidmUlid livekitJwtUrl matrixAdmins ; };};✨ darkone.service.mealie
Section intitulée « ✨ darkone.service.mealie »Gestion de recettes Mealie
- enable
boolActiver le service mealie
darkone.service.mealie.enable = false;✨ darkone.service.minio
Section intitulée « ✨ darkone.service.minio »Un service MinIO S3 local entièrement configuré. (wip)
Fournit un backend de stockage d’objets compatible S3 interne accessible uniquement sur 127.0.0.1:9000. L’interface Web de la console s’exécute sur 127.0.0.1:9001 pour l’administration et le débogage.
- enable
boolActiver le service MinIO S3 local
darkone.service.minio.enable = false;✨ darkone.service.monitoring.fs-readonly
Section intitulée « ✨ darkone.service.monitoring.fs-readonly »Supervision DNF : montages rw rendus en lecture seule par le noyau. Doc : en-tête de ../monitoring.nix.
✨ darkone.service.monitoring
Section intitulée « ✨ darkone.service.monitoring »Module de supervision : tableaux de bord Grafana + exporteur par nœud.
Surveillance en lecture seule (monitoring/fs-readonly.nix) : chaque nœud exporte
dnf_filesystem_forced_readonly, ses montages rw dont le noyau a rendu le
système de fichiers en lecture seule, derrière FilesystemReadOnly. Les
montages ro et liaisons prévus n’y apparaissent jamais ; le fichier vit sur
tmpfs, il survit donc au disque défaillant.
- enable
boolActiver la supervision avec prometheus, grafana et l’exporteur de nœud - isNode
boolS’agit-il d’un nœud de supervision - kioskTarget
strCible (relative, sans/) de la redirection automatique vers Grafana depuis la racine du domaine de supervision. Surchargée par le module Loki lorsqu’il est actif pour pointer vers un tableau de bord multi-sources.
darkone.service.monitoring = { enable = false; isNode = lib.hasAttrByPath [ "features" "monitoring-node" ] host; kioskTarget = "d/dnf-monitoring-home/home?kiosk";};✨ darkone.service.nextcloud
Section intitulée « ✨ darkone.service.nextcloud »Service Nextcloud entièrement configuré.
-
enable
boolActiver le service nextcloud local -
adminUser
strNom d’utilisateur administrateur pour Nextcloud -
enableSsoRedirect
boolEnvoyer les utilisateurs directement vers Kanidm au lieu d’afficher le formulaire de connexion Nextcloud (user_oidcallow_multiple_user_backends). Économise un clic à chaque connexion, y compris celle du client de bureau via Login Flow v2.Sans effet si Kanidm est absent du réseau.
-
plugins
listOf (enum (appstoreApps ++ shippedToggleableApps))Applications Nextcloud à activer. Seulscalendar,contactsettaskssont activés par défaut ; Talk (spreed), le tableau de bord, le flux d’activité, les photos et toutes les autres applications restent désactivées tant qu’elles ne sont pas listées ici.user_oidc(SSO Kanidm) etnotify_push(push client) sont toujours activés, quelle que soit cette liste.
darkone.service.nextcloud = { enable = false; adminUser = "admin"; enableSsoRedirect = true; plugins = [ ];};✨ darkone.service.nfs
Section intitulée « ✨ darkone.service.nfs »Serveur + client NFS pour les partages domestiques.
- enable
boolActive le serveur NFS DNF (éviter l’activation manuelle) - serverDomain
strFQDN du serveur NFS
darkone.service.nfs = { enable = hasServer && (isServer || isClient); serverDomain = "nfs";};✨ darkone.service.nix-cache
Section intitulée « ✨ darkone.service.nix-cache »Proxy de cache binaire Nix par zone (nginx proxy_cache).
Met en cache le cache Nix public (cache.nixos.org) sur la passerelle de
zone, afin qu’un déploiement à l’échelle de la flotte récupère chaque
fermeture depuis le WAN une seule fois, puis la serve sur le LAN à tous les
autres hôtes. Les chemins compilés localement sont servis directement
depuis harmonia (voir harmonia.nix) ; ce proxy ne sert jamais de
façade à harmonia.
- enable
boolLe proxy de cache binaire Nix par zone (nginx devant cache.nixos.org) - maxSize
strTaille maximale du cache sur disque ; nginx évince au-delà les entrées les moins récemment utilisées. - roaming
boolHôte nomade (ordinateur portable déplacé entre zones) : remplacer les substituteurs épinglés à la zone par les noms neutres de zone que le DNS de chaque zone résout vers ses propres services de cache. Hors de toute zone DNF, ces noms répondent NXDOMAIN immédiatement et Nix se rabat sur cache.nixos.org. Déclaré par la fonctionnalitéroamingdansconfig.yaml; à définir à la main pour un déplacement temporaire.
darkone.service.nix-cache = { enable = false; maxSize = "40g"; roaming = (host.features or { }) ? "roaming";};✨ darkone.service.openclaw
Section intitulée « ✨ darkone.service.openclaw »Assistant OpenClaw d’un espace IA (passerelle + interface de gestion, derrière le SSO de la zone).
Une instance par hôte ai-space, déclarée comme n’importe quel service :
- hostname: "ia-pro" profile: "ai-space" users: ["alice"] # membres : groupe Kanidm `space-ia-pro` features: ["monitoring-node"] # alertes : espace injoignable, unité de la passerelle en échec services: { openclaw: {} }- accès : forward auth Caddy, membres de
space-<host>uniquement (proxy.spaceMembersOnly) ; OpenClaw fait confiance à la passerelle de la zone en tant que proxy (trusted-proxy) et lit l’identité dansx-auth-request-email; - appareils : le navigateur d’un membre est appairé à la première visite, sans admin de l’opérateur (accordé uniquement depuis le CLI de l’hôte) ;
- port : joignable depuis la passerelle de la zone uniquement ;
- CLI hôte :
openclaw, relancé en tant qu’utilisateur du service, au-delà detrusted-proxyavec le mot de passe de la passerelle (openclaw-gateway-password,just space-init) ; - état :
/var/lib/openclaw(connexions aux fournisseurs, sessions, espace de travail, clés E2EE Matrix) ; - propriétaire (
owner, par défaut : l’unique membre) : son abonnement fait tourner l’agent, il reçoit les demandes d’approbation et les messages proactifs ; - Matrix : canal de DM avec le bot
@<host>:<domain>, membres uniquement, salons ignorés, une session par membre quand il y en a plusieurs, quand le réseau dispose de Matrix et quejust space-init <host>a créé le bot (marqueurvar/generated/spaces/<host>.nix, jeton dans le fichier sops de l’espace) ; approbations d’exec demandées au propriétaire en DM ; - outillage de l’agent : MCP, skills, Claude Code / Codex et
packagesde l’espace (darkone.host.ai-space), partagés avec les homes des membres ; - identité (
identity: nom, emoji, avatar) : déclarée, la configuration étant en lecture seule (openclaw agents set-identityéchoue) ; - espace de travail (
/var/lib/openclaw/workspace) : fichiersworkspace(AGENTS.md, SOUL.md…) remplacés à chaque démarrage, les autres laissés à l’agent ;projectsclonés une fois enprojects/<name>; - notes vocales : whisper.cpp local (
transcription, modèle ggmlsmall).
darkone.service.openclaw = { workspace."AGENTS.md" = ./agents/AGENTS.md; projects.notes = "git@forge.example.com:alice/notes.git";};-
enable
boolActiver l’assistant OpenClaw d’un espace IA -
owner
nullOr strMembre propriétaire de l’espace : son abonnement connecte l’agent (model), il reçoit les demandes d’approbation et les messages proactifs. Requis avec plusieurs membres (l’ordre deusersn’est pas conservé). -
model
strModèle principal. Runtime d’abonnement de son fournisseur :anthropic/*via le CLIclaude(avecdarkone.host.ai-space.enableClaude),openai/*via le plugincodex(OAuth ChatGPT). -
exec
enum [ "full" "auto" "ask" "allowlist" "deny" ]Politique de commandes de l’agent (OpenClawtools.exec.mode) :full: n’importe quelle commande, non approuvée (défaut d’OpenClaw) ;ask: commandes de la liste blanche exécutées, toute autre interroge le propriétaire ;auto: un modèle examine les manques, le propriétaire décide en cas de doute ;allowlist,deny: commandes de la liste blanche uniquement, aucune.
Liste blanche :
openclaw approvals allowlist add --agent main <path>. Avec le runtimeclaude-cli, les pipes, redirections et substitutions sont refusés avant toute invite horsfull. -
identity.name
nullOr strNom de l’assistant, affiché dans l’interface. -
identity.emoji
nullOr strEmoji de l’assistant, affiché dans l’interface. -
identity.avatar
nullOr strImage d’avatar (URL ou chemin relatif à l’espace de travail). -
workspace
attrsFichiers de l’espace de travail de l’agent, par chemin relatif : contenu ou fichier. Remplacés à chaque démarrage de la passerelle ; les fichiers non déclarés appartiennent à l’agent. -
projects
attrsDépôts git clonés une fois dansworkspace/projects/<name>, jamais tirés. Les remotes SSH utilisent la clé d’openclaw(/var/lib/openclaw/.ssh, créée à la main) ; la clé du serveur est acceptée au premier clonage. -
transcription.enable
boolTranscrire les notes vocales en local (whisper.cpp, CPU). -
transcription.model
pathModèle ggml de whisper.cpp. -
transcription.language
strLangue parlée (auto: détectée par note).
darkone.service.openclaw = { enable = false; owner = "alice"; model = "openai/gpt-6-astra"; exec = "ask"; identity.name = "Jarvis"; identity.emoji = "🦉"; identity.avatar = null; workspace = { }; projects = { }; transcription.enable = true; transcription.model = pkgs.fetchurl { url = "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin"; sha256 = "0ywqxbziyp2bv72riyjpw4brk9v46d4cfbjfwqvvjrrq0srakqqv"; }; transcription.language = "fr";};✨ darkone.service.outline
Section intitulée « ✨ darkone.service.outline »Un wiki outline complètement configuré.
- enable
boolActiver le service outline local
darkone.service.outline.enable = false;✨ darkone.service.oxicloud
Section intitulée « ✨ darkone.service.oxicloud »OxiCloud — Fast Sovereign Cloud (stockage de fichiers, WebDAV, CalDAV et CardDAV).
- enable
boolActiver le service OxiCloud local
darkone.service.oxicloud.enable = false;✨ darkone.service.postfix
Section intitulée « ✨ darkone.service.postfix »Relais SMTP Postfix.
- enable
boolActiver le relais SMTP Postfix
darkone.service.postfix.enable = false;✨ darkone.service.printing
Section intitulée « ✨ darkone.service.printing »Imprimantes et scanners.
- enable
boolPaquets utiles par défaut - loadAll
boolImprimantes et scanners complets - enableScanners
boolActiver les scanners - enableHpPrinters
boolImprimantes HP uniquement - enableManualInstall
boolInstallation manuelle des pilotes
darkone.service.printing = { enable = false; loadAll = false; enableScanners = false; enableHpPrinters = false; enableManualInstall = false;};✨ darkone.service.prometheus
Section intitulée « ✨ darkone.service.prometheus »Serveur de supervision Prometheus avec escalade déclarative via Alertmanager.
-
enable
boolActiver le serveur de métriques + d’alerting Prometheus -
retentionTime
strDurée de rétention des métriques Prometheus -
alerting.enable
boolActiver Alertmanager (activé par défaut une fois les salons Matrix d’alerte provisionnés) -
alerting.matrix.enable
boolDiffuser les alertes dans les salons Matrix via le bot matrix-alertmanager -
alerting.matrix.userId
strID utilisateur Matrix du bot d’alerte (par défaut depuis network.matrix.bot) -
alerting.matrix.warningsRoom
strID du salon Matrix pour les avertissements (par défaut depuis network.matrix.warningsRoom) -
alerting.matrix.incidentsRoom
strID du salon Matrix pour les incidents (par défaut depuis network.matrix.incidentsRoom) -
alerting.email.enable
boolEnvoyer aussi les alertes critiques par mail (via le relais Postfix local) -
alerting.email.to
strDestinataire des mails d’alerte critique -
alerting.network.enable
boolSonder l’atteignabilité réseau (passerelle/tailnet/DNS) avec blackbox_exporter -
alerting.network.internetProbeTargets
listOf strAdresses IP externes que la passerelle de zone ping pour détecter une coupure WAN. Si toutes échouent,ZoneInternetDownse déclenche et inhibe les alertes de down (erronées) des hôtes accessibles uniquement via le WAN (par ex. le HCS). Liste vide = désactivé. -
alerting.network.httpProbeUrls
listOf strURLs HTTP(S) sondées pour la vivacité (ServiceEndpointDown) et l’expiration du certificat TLS (CertificateExpiringSoon/Critical). Vide par défaut : lister les endpoints web publics à surveiller. Les redirections vers un login SSO (3xx) sont comptées comme up ; l’expiration du certificat est lue depuis la poignée de main TLS quelle que soit la réponse HTTP. -
alerting.silenceOnRebuild
boolÉmettre le flag dnf-maintenance (textfile collector) afin que les reconstructions inhibent les alertes d’un nœud -
alerting.thresholds
attrsRemplacer les seuils d’alerte de ressources (voir les valeurs par défaut dans dnf/lib/alerts.nix) -
alerting.silences
listOf submoduleAlertes connues et acceptées qui ne doivent jamais notifier. Chaque entrée devient une route Alertmanager vers le récepteurnull: l’alerte se déclenche toujours et reste visible dans les interfaces Prometheus/Alertmanager/Grafana, elle ne parvient simplement plus à Matrix ni par mail.Déclaré sur l’hôte qui fait tourner Prometheus, car c’est là que les règles et routes de la zone sont générées. Un module consommateur à l’échelle de la flotte (
usr/modules/alerts.nix) est l’endroit pratique : il est importé partout et ne prend effet que là où Prometheus tourne.- alert
strNom de l’alerte à mettre en sourdine (labelalertname). Toujours restreint, afin que les niveaux de gravité voisins restent armés. - host
nullOr strRestreindre le silence à un seul hôte. Null met en sourdine l’alerte pour toute la flotte. - matchers
attrsÉtiquettes de correspondance exacte supplémentaires, combinées en ET avec les autres (par ex. le point de montage ou le device visé par l’alerte). - reason
strPourquoi cette alerte est acceptée, et ce qui rendrait le silence supprimable.
- alert
darkone.service.prometheus = { enable = false; retentionTime = "30d"; alerting.enable = roomsReady; alerting.matrix.enable = true; alerting.matrix.userId = "@alertbot:domain.tld"; alerting.matrix.warningsRoom = "!warnings:domain.tld"; alerting.matrix.incidentsRoom = "!incidents:domain.tld"; alerting.email.enable = true; alerting.email.to = "admin@${network.domain}"; alerting.network.enable = true; alerting.network.internetProbeTargets = [ ]; alerting.network.httpProbeUrls = [ ]; alerting.silenceOnRebuild = true; alerting.thresholds = { }; alerting.silences = [ ]; alerting.silences.alert = "DiskSpaceLow"; alerting.silences.host = "srv-main"; alerting.silences.matchers = { }; alerting.silences.reason = null;};✨ darkone.service.restic.metrics
Section intitulée « ✨ darkone.service.restic.metrics »DNF restic : métriques de fraîcheur des sauvegardes. Doc : en-tête de ../restic.nix.
✨ darkone.service.restic.server
Section intitulée « ✨ darkone.service.restic.server »DNF restic : le serveur REST. Doc : en-tête de ../restic.nix.
✨ darkone.service.restic
Section intitulée « ✨ darkone.service.restic »Module de sauvegarde restic : serveur REST + cibles de sauvegarde par hôte.
Exemple (configuration machine) :
darkone.service.restic = { enable = true; targets = [ { name = "main"; root = "rest:http://restic.my-zone.my-domain.tld:8888"; zone = "ag"; categories = [ "system" "nfs" ]; } ];};Disposition des dépôts par cible : un dépôt par catégorie, nommé d’après elle.
<root>/<hostname>/system <- catégorie "system" (/ moins les exclusions)<root>/<hostname>/nfs <- catégorie "nfs" (/srv/nfs/<...>)<root>/<hostname>/medias <- catégorie "medias" (/srv/medias/<...>)Sous-modules (restic/) :
server.nix: le serveur REST, un compte par hôte de la flotte ;metrics.nix: métriques de fraîcheur des sauvegardes pour les alertes restic.
Serveur REST (server.nix)
Section intitulée « Serveur REST (server.nix) »Un compte par hôte de la flotte (restic/<hostname>/rest-password), vérifié
contre un htpasswd assemblé au démarrage ; privateRepos confine chaque hôte
à son propre préfixe <hostname>/.
Métriques (metrics.nix)
Section intitulée « Métriques (metrics.nix) »Nœuds monitorés uniquement (fonction monitoring-node) : chaque tâche
horodate sa dernière réussite dans le collecteur textfile, et restic-declared
liste les tâches déclarées pour qu’une tâche qui ne réussit jamais vieillisse
quand même en alerte dnf-restic-<zone>.
- enable
boolActiver le client de sauvegarde restic - enableDryRun
boolMode simulation (dry run) - enableWaitRemoteFs
boolExécuter les sauvegardes seulement après remote-fs.target - enableServer
boolActiver le serveur REST restic - listenAll
boolLier le serveur REST sur 0.0.0.0 (clients hors site) - serverDataDir
strRacine de stockage locale du serveur REST (dépôts de tous les hôtes) - targets
listOf submoduleDestinations de sauvegarde pour cet hôte (chemin local ou URL REST)- name
strIdentifiant de cible, utilisé dans les noms de sauvegarde/d’unité (<category>-<name>) - root
strRacine du dépôt : chemin local ou URL REST - zone
strZone sélectionnant la phrase secrète du dépôt (restic-password-<zone>) - categories
listOf ( enum [ "system" "nfs" "medias" ] )Ce qu’il faut sauvegarder vers cette cible
- name
- nfsPaths
listOf strRépertoires NFS (/srv/nfs/<xxx>) inclus dans la catégorie ‘nfs’ - mediasPaths
listOf strRépertoires médias (/srv/medias/<xxx>) inclus dans la catégorie ‘medias’ - shared
rawValeurs restic partagées avec les sous-modulesrestic/.
darkone.service.restic = { enable = false; enableDryRun = false; enableWaitRemoteFs = false; enableServer = false; listenAll = false; serverDataDir = "/mnt/backup/restic"; targets = [ ]; targets.name = "main"; targets.root = "rest:http://restic.${zone.domain}:${toString srvPort}"; targets.zone = zone.name; targets.categories = [ ]; nfsPaths = [ ]; mediasPaths = [ ]; shared = { inherit params; };};✨ darkone.service.searx
Section intitulée « ✨ darkone.service.searx »Un moteur de recherche durci et entièrement configuré.
- enable
boolActiver le proxy de recherche local
darkone.service.searx.enable = false;✨ darkone.service.stk
Section intitulée « ✨ darkone.service.stk »Pistes partagées SuperTuxKart, servies via NFS.
- enable
boolExporter les pistes partagées SuperTuxKart (éviter d’activer manuellement) - enableClient
boolMonter les pistes partagées SuperTuxKart de la zone - serverName
nullOr strHostname du serveur hébergeant les pistes, par défaut l’hôtestkde la zone
darkone.service.stk = { enable = stk.isServer; enableClient = false; serverName = stk.server;};✨ darkone.service.tailscale.autopause
Section intitulée « ✨ darkone.service.tailscale.autopause »DNF tailscale : mise en pause automatique lors des déplacements. Doc : en-tête de ../tailscale.nix.
✨ darkone.service.tailscale.cert-sync
Section intitulée « ✨ darkone.service.tailscale.cert-sync »DNF tailscale : synchronisation des certificats HCS. Doc : en-tête de ../tailscale.nix.
✨ darkone.service.tailscale.selfheal
Section intitulée « ✨ darkone.service.tailscale.selfheal »DNF tailscale : chien de garde d’auto-réparation. Doc : en-tête de ../tailscale.nix.
✨ darkone.service.tailscale
Section intitulée « ✨ darkone.service.tailscale »Client tailscale du tailnet DNF (headscale sur le HCS).
Rejoint le HCS, les passerelles de zone (isGateway : sous-réseau de zone
annoncé, routes acceptées, propre résolveur conservé) et les hôtes en
déplacement.
Sous-modules (tailscale/) :
cert-sync.nix: les passerelles de zone récupèrent les certificats Caddy du HCS ;selfheal.nix: chien de garde redémarrant un tailscaled déconnecté ;autopause.nix: les clients en déplacement mettent tailscale en pause sur une LAN de zone.
Synchronisation des certificats (cert-sync.nix)
Section intitulée « Synchronisation des certificats (cert-sync.nix) »Les certificats publics sont émis sur le HCS uniquement ; chaque passerelle de
zone récupère tout le stockage Caddy par le tailnet (rsync en tant que nix,
élevé à caddy côté HCS), puis le publie sur son propre Caddy.
Auto-réparation (selfheal.nix)
Section intitulée « Auto-réparation (selfheal.nix) »Chaque minute, vérifie que le backend tourne et que le plan de contrôle voit
le nœud en ligne ; redémarre tailscaled après une perte prolongée. Exporte les
métriques dnf_tailscale_* pour les alertes TailscaleFlapping/
TailscaleUnhealthy.
Mise en pause automatique (autopause.nix)
Section intitulée « Mise en pause automatique (autopause.nix) »Clients en déplacement uniquement. Sur une LAN de zone DNF, --accept-dns
hijackerait resolv.conf (dnsmasq/AdGuard local) et --accept-routes
entrerait en conflit avec le sous-réseau de zone connecté : un dispatcheur
NetworkManager met tailscale en pause sur place et le réactive ailleurs.
- enable
boolActiver le client tailscale pour se connecter au HCS - isGateway
boolCe nœud tailscale est une passerelle de sous-réseau - isExitNode
boolConfigurer ce client comme nœud de sortie - selfHeal.enable
boolChien de garde : détecter la déconnexion d’headscale et redémarrer tailscaled. - autoPauseOnLan.enable
boolClient en déplacement : mettre tailscale en pause (down) branché sur une LAN de zone DNF connue, le réactiver ailleurs. Clients NetworkManager non passerelle uniquement. - shared
rawValeurs tailscale partagées avec les sous-modulestailscale/.
darkone.service.tailscale = { enable = false; isGateway = false; isExitNode = false; selfHeal.enable = true; autoPauseOnLan.enable = false; shared = { inherit tsBin isHcsSubnetGateway selfHealEnable selfHealStateDir autoPauseEnable autoPauseStateFile ; };};✨ darkone.service.turn
Section intitulée « ✨ darkone.service.turn »Serveur Coturn (matrix).
Ajouter des entrées DNS pour optimiser :
Type,Name,Priority,Pds,Port,TargetSRV,_stun._udp,0,0,3478,turn.mydomain.tldSRV,_stun._tcp,0,0,3478,turn.mydomain.tldSRV,_turn._udp,0,0,3478,turn.mydomain.tldSRV,_turn._tcp,0,0,3478,turn.mydomain.tldSRV,_turns._tcp,0,0,5349,turn.mydomain.tld- enable
boolActiver le service turn local (visio)
darkone.service.turn.enable = false;✨ darkone.service.vaultwarden
Section intitulée « ✨ darkone.service.vaultwarden »Un serveur vaultwarden entièrement configuré.
- enable
boolActiver le service Vaultwarden local - enableSmtp
boolActiver SMTP pour l’envoi d’e-mails (recommandé, nécessitenetwork.smtp)
darkone.service.vaultwarden = { enable = false; enableSmtp = true;};