HashiCorp Vault sur Synology :
Fini les
certificats pourris ! 🔐
Ou comment j'ai arrêté de pleurer devant mes certificats auto-signés
TL;DR pour les pressés
On va installer Vault sur un Synology pour générer et renouveler automatiquement nos certificats SSL. Plus jamais d'erreurs "certificat non valide" dans le navigateur ou pour connecter un service, plus jamais de weekend gâché à renouveler manuellement des certificats expirés. Promise de dev ! 🤞
🤦♂️ Générer des certificats, quelle galère !
C'est toujours chiant de générer des certificats. Tu te dis “je le ferai plus tard” pour aller vite… et puis, au moment où tu veux brancher un service, il en a absolument besoin. Là, c'est la galère : ça ne fait pas très pro, et tu perds un temps fou à te remettre dedans.
Ou alors cette magnifique erreur qui fait toujours plaisir en gros dans ton navigateur :
Votre connexion n'est pas privée. Des individus malveillants tentent peut-être de dérober vos informations...
Yeah, génial ! Sans compter que parfois, c'est un service tout frais qui te sort cette erreur et lui, il n'arrive carrément pas à s'en servir ! 😅
Et ne parlons pas de ces moments où tu configures ton homelab avec des certificats auto-signés “juste pour tester”, et que finalement une bonne moitié de tes services traînent encore en HTTP ou avec des certificats foireux.
BREEEEEFFFFFF....
"Il n'y a que deux types de développeurs : ceux qui ont déjà eu des problèmes de certificats, et ceux qui mentent."
💡 La solution : Vault + Synology = ❤️
Alors voilà l'idée géniale (bon, pas de moi, merci HashiCorp) : utiliser HashiCorp Vault comme une PKI (Public Key Infrastructure) pour générer automatiquement nos certificats SSL.
Mais attention, on ne va pas juste installer Vault et l'oublier dans un coin. Non non non. On va faire ça proprement avec :
Consul
Notre backend de stockage. Parce que Vault tout seul, c'est comme un frigo vide : ça sert à rien.
Stockage distribué, haute disponibilité, tout ça...Vault
Le chef d'orchestre. Il génère les certificats, gère les secrets, et fait tout ça de manière sécurisée.
PKI, secrets management, API REST...Vault-Agent
Le petit robot qui fait le sale boulot : récupère les certificats et les déploie automatiquement.
Templating, déploiement, redémarrage des services...Parce que ton NAS Synology tourne H24, qu'il a Docker, et qu'il est parfait pour héberger ce genre de services d'infrastructure ! Et puis soyons honnêtes, on a tous un Synology qui tourne dans un coin, autant qu'il serve à quelque chose d'utile. 😏 Oui, oui Netflix tu m'as vu 🙃
🏗️ Architecture de notre petit chef-d'œuvre
Bon, avant de se lancer tête baissée dans les commandes, comprenons un peu ce qu'on va construire :
Au début, notre Vault backé par Consul sera accessible en HTTP (oui, je sais, c'est ironique pour un truc qui gère la sécurité). Mais c'est temporaire, le temps qu'on configure tout.
Phase 2 : "The magic happens"Une fois configuré, Vault-Agent va :
- Se connecter à Vault avec ses identifiants en HTTP.
Mais lui il sera sur le réseau Docker donc il a le droit ! - Générer un nouveau certificat SSL
- Le déployer dans le bon répertoire de Synology
- Redémarrer Nginx pour prendre en compte le nouveau certificat
- Répéter tout ça automatiquement avant expiration
Résultat : on accède à Vault en HTTPS depuis l'exterieur avec un certificat valide, et tous nos autres services peuvent bénéficier du même système !
Une fois que c'est en place, tu peux générer des certificats pour tous tes services internes : le NAS, Portainer, ton API maison, etc. Un seul endroit pour gérer tous tes certificats !
Autre point positif : Vault est
générique, tu n'es même pas obligé de lui faire générer des
certificats : tu peux aussi lui en fournir comme...
ceux d'un Let's Encrypt avec un Cerbot pour exposer ton service
sur Internet par example 😉
Mais cela sera l'object d'un
autre article notament sur Kubernetes avec Cert-manager pour
celles et ceux qui conaissent déjà.
📁 Structure du projet (ou "comment s'organiser comme un chef")
Treve de bavardage, passons à la pratique
On commence par créer notre petite architecture. Parce que oui, l'organisation c'est important (même si on fait tous semblant de s'en foutre) :
Le point de départ sur mon Synology où je vais travailler :
- sur la partition RAID1 que j'ai crée : volume1
- dans un dossier partagé : docker qui me sert bah à tous mes Dockers hein logique ! En plus il backupé sur AWS toutes les nuits donc les configs ne vont pas s'envoler 😉.
- dans un dossier spécifique : secret afin de ne pas mélanger les choux et les carottes.
Arborescence du projet
📁 /volume1/docker/secret/
├── 🐳 swarm_consul_vault.yml # Orchestration pour Consul & Vault
├── 🐳 swarm_vault_agent.yml # Orchestration pour Vault-Agent
├── 📁 consul/
│ ├── 📁 config/
│ │ ├── 📄 server.hcl # Config Consul
│ │ └── 📄 start-consul.sh # Script de démarrage
│ └── 📁 data/ # Données Consul (généré auto)
├── 📁 vault/
│ ├── 📁 config/
│ │ └── 📄 vault.hcl # Config Vault
└── 📁 vault-agent/
├── 📁 config/
│ └── 📄 agent.hcl # Config de l'agent
│ └── 📄 restart_service.sh # Script de redémarrage
└── 📁 templates/
└── 📄 cert.tpl # Template de certificat
Chaque dossier a son rôle, chaque fichier a sa mission. C'est beau, c'est organisé, ça donne envie de pleurer de bonheur ! 🥲
🚀 Phase 1 : On met le bazaar en place
Bon, maintenant qu'on a compris le principe, on va passer aux choses sérieuses. Prépare-toi un bon café, on va faire du Docker Swarm !
Oui je sais tu ne l'avais pas vu venir celle-là hein ☺️!
La vérité c'est que l'interface Docker de Synology est bien trop limité. Deplus sur le long terme si tu as envie d'avoir plusieurs Synology, tu pouras étandre le Swarm dessus (et donc notament le vault-agent automatiquement) pas mal hein !
Avant de commencer, assure-toi d'avoir accès SSH à ton Synology et que Docker est installé ET configuré. Si tu ne sais pas comment faire, Google est ton ami (ou ChatGPT, on ne juge pas).
Étape 1 : Initialisation du swarm
Première étape : on active notre Docker en mode Swarm. Pourquoi ? Parce que ça nous permet d'utiliser les secrets Docker (bien plus sécurisé que des variables d'environnement).
Je ferai probablement un article sur Docker Swarm. Je trouve cette techno vraiment sous-estimée alors qu'elle peut rendre de sacrés services (comme ici), surtout face au monstre Kubernetes qui demande énormement de configuration. Mais bon, restons concentrés, on n'est pas là pour parler des Godzilla du cloud !
# On active le mode swarm sur l'interface réseau principale (chez moi c'est la premiere eth0)
docker swarm init --advertise-addr eth0
Bon, là il n'y a pas grand-chose à dire : Docker est déjà installé via le gestionnaire de paquets de Synology, et Swarm est nativement intégré à Docker Engine depuis près de dix ans.
Pensez simplement à enregistrer le token, au cas où tu souhaiterais ajouter d'autres Synology au cluster Swarm à l'avenir.
Dans l'absolu, nous allons utiliser très peu de fonctionnalités de Swarm : déploiement, réplication, exposition de services et gestion des secrets.
Étape 2 : Déploiement de la stack
Bon, maintenant qu'on a fait le tour de l'architecture, il est temps de rentrer dans le vif du sujet ! On va éplucher ensemble chaque fichier de cette arborescence que je t'ai montrée plus haut.
Alors prépare-toi un bon café ☕ (ou un thé si tu es de ce bord-là), lance ton éditeur de code favori - et s'il te plaît, pas Notepad, on a notre dignité ! - et c'est parti pour une plongée dans ces fichiers YAML, HCL et Bash qui vont métamorphoser ton petit NAS en véritable bunker numérique.
Cette stack déploie les services consul et vault avec
leurs volumes, réseaux et configurations spécifiques. Elle utilise une syntaxe
compatible Docker Compose, que Docker Swarm comprend et interprète sans souci.
Cette première stack prépare le backend de stockage de Vault avec Consul, et déploie Vault en mode serveur.
cap_add: IPC_LOCK: Permet à Vault de verrouiller sa mémoire et éviter que des secrets ne soient échangés sur le disque.volumes: Persistence des informations, chargement des configurations et synchronisation de l'heure avec l'hôte via/etc/localtimepour éviter les problèmes de logs et certificats.secrets:Les clés de chiffrement sont injectées de façon sécurisée via les secrets Swarm.networks: secret: Un réseau overlay Swarm dédié pour isoler la communication entre services.healthcheck: Teste périodiquement la disponibilité des services (ex: API Consul, endpoint santé Vault).deploy.restart_policy: Paramètres pour gérer automatiquement la résilience en cas d'erreurs.
Voici le fichier swarm_consul_vault.yml complet avec tous les
commentaires qui expliquent chaque section en détail :
version: "3.8"
services:
consul:
image: hashicorp/consul:1.17
ports:
# Port web UI et API Consul
- "8500:8500"
volumes:
# Configuration de Consul en lecture seule
- /volume1/docker/secret/consul/config:/consul/config
# Données persistantes pour Consul
- /volume1/docker/secret/consul/data:/consul/data
# Synchronisation de l'heure avec l'hôte pour cohérence temporelle
- /etc/localtime:/etc/localtime:ro
environment:
# Informations sur le cluster Consul
CONSUL_DATACENTER: Low-layer
CONSUL_DOMAIN: consul
CONSUL_NODE_NAME: synology-01-consul
# Clé de chiffrement réseau, injectée via secret
CONSUL_ENCRYPT_KEY_FILE: /run/secrets/consul-encrypt-key
# Identifiants utilisateur/groupe pour permissions d'accès
PUID: 1027
PGID: 100
command: sh /consul/config/start_consul.sh
networks:
- secret
secrets:
# Secret Consul encrypt key externe
- consul-encrypt-key
healthcheck:
# Test pour vérifier que Consul est joignable
test: ["CMD", "consul", "members", "-http-addr=http://localhost:8500"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
deploy:
replicas: 1
restart_policy:
condition: any
delay: 30s
max_attempts: 20
window: 600s
vault:
image: hashicorp/vault:1.15
cap_add:
# Verrouillage mémoire pour éviter le swap des secrets sur disque
- IPC_LOCK
ports:
# Port de l'API Vault et UI accessible via 8200
- "8200:8200"
volumes:
# Configuration Vault
- /volume1/docker/secret/vault/config:/vault/config
# Synchronisation de l'heure avec l'hôte pour éviter dérives
- /etc/localtime:/etc/localtime:ro
environment:
PUID: 1027
PGID: 100
command: vault server -config=/vault/config/vault.hcl
networks:
- secret
deploy:
replicas: 1
restart_policy:
condition: any
delay: 30s
max_attempts: 20
window: 600s
healthcheck:
# Vérifie la santé de Vault, accepte aussi état non initialisé ou scellé
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8200/v1/sys/health?uninitcode=200&sealedcode=200"]
interval: 30s
timeout: 10s
retries: 10
start_period: 120s
# Secrets à créer à la main avant déploiement
secrets:
consul-encrypt-key:
external: true
# Réseau chiffré Swarm externe déjà créé (overlay)
networks:
secret:
name: secret
external: true
Cette stack déploie le vault_agent, un client Vault qui s'exécute
sur tous les nœuds (mode global). Il s'authentifie via un AppRole
sécurisé (avec role_id et secret_id) et récupère les
secrets, en particulier les certificats, qu'il écrit directement dans les
emplacements système des NAS Synology.
- Première stack : déploie le backend
consul+vault, nécessaire pour initialiser et faire tourner Vault. - Deuxième stack : déploie l'agent Vault qui consomme les secrets, il ne peut être lancé qu'après que Vault est initialisé et déverrouillé.
root), des capacités spécifiques (SYS_CHROOT,
IPC_LOCK) et accès en lecture sur le système hôte. Cela permet
notamment d'appliquer les certificats et de redémarrer les services (nginx
notamment) sur le NAS.
user: rootpour avoir tous les droits nécessaires.cap_add: IPC_LOCKpour verrouiller la mémoire et protéger les secrets.cap_add: SYS_CHROOTpour utiliser chroot et accéder au système hôte, notamment pour redémarrer des services.volumesimportants :- Les configs agent et templates de certificats.
- L'emplacement des certificats Synology (avec RW).
- L'accès au système hôte en lecture pour contrôle et actions.
secrets: injection desrole_idetsecret_idvia secrets Docker Swarm.deploy.mode: globalpour garantir la présence d'un agent par nœud.
Voici le fichier swarm_vault_agent.yml complet avec commentaires
pour bien comprendre chaque partie :
version: "3.8"
services:
vault_agent:
image: hashicorp/vault:1.15
user: root
cap_add:
# Protection mémoire pour éviter le swap des secrets
- IPC_LOCK
# Permet d'utiliser chroot pour accéder au système hôte (ex: pour redémarrer nginx)
- SYS_CHROOT
volumes:
# Configuration de l'agent Vault
- /volume1/docker/secret/vault_agent/config:/vault/config
# Templates des certificats TLS à générer
- /volume1/docker/secret/vault_agent/templates:/vault/templates
# Emplacement des certificats Synology, accès lecture/écriture
- /usr/syno/etc/certificate/_archive:/certs:rw
# Synchronisation horaire avec l'hôte
- /etc/localtime:/etc/localtime:ro
# Accès en lecture au système hôte pour contrôle et redémarrage
- /:/host:ro
secrets:
# Credentials AppRole Vault injectés via secrets Swarm
- vault-role-id
- vault-secret-id
command: sh -c "vault agent -config=/vault/config/agent.hcl"
networks:
- secret
deploy:
# Lancement d'un agent sur chaque nœud du Swarm
mode: global
restart_policy:
condition: any
delay: 30s
max_attempts: 20
window: 600s
# Secrets AppRole à créer manuellement avant déploiement
secrets:
vault-role-id:
external: true
vault-secret-id:
external: true
# Réseau chiffré overlay Swarm partagé entre services
networks:
secret:
name: secret
external: true
Ce fichier server.hcl est probablement le plus court de notre stack,
mais ne t'y trompes pas ce petit fichier optimise silencieusement les
performances
de Consul.
Consul utilise l'algorithme Raft pour maintenir la cohérence des données dans le cluster. Ce multiplicateur est un facteur d'échelle qui affecte directement les timeouts de HeartbeatTimeout, ElectionTimeout et LeaderLeaseTimeout.
raft_multiplier = 1
Configuration haute performance recommandée pour la
production. HashiCorp recommande de configurer ce paramètre à 1 en
production
pour permettre aux serveurs Consul de détecter rapidement une défaillance du
leader et de terminer les élections de leader beaucoup plus
rapidement.
- Performance optimale : Détection rapide des défaillances et élections de leader plus rapides
- Réseau local : Convient parfaitement aux environnements avec faible latence réseau
- Production ready : Configuration recommandée par HashiCorp
- Timeouts optimisés : HeartbeatTimeout=1000ms, ElectionTimeout=1000ms, LeaderLeaseTimeout=500ms
La valeur par défaut de Consul est 5 (pour des instances t2.micro AWS), mais
cela rend la détection de défaillance et les élections beaucoup plus lentes.
Dans notre environnement NAS local, 1 est le choix optimal !
Pour plus de détails sur les paramètres de performance Consul, consultez la documentation HashiCorp sur les exigences serveur.
En résumé, ce fichier fait exactement ce qu'il faut : il configure Consul pour
qu'il
fonctionne avec les performances optimales recommandées par HashiCorp.
Contrairement
aux idées reçues, la valeur 1 n'est pas la "configuration par
défaut"
mais bien la configuration haute performance pour la production
!
# Configuration de performance pour Consul
performance {
# Multiplicateur Raft pour ajuster les timeouts
# Valeur 1 = configuration pour la production
raft_multiplier = 1
}
Le script shell start_consul.sh fait le travail ingrat que personne
ne
veut faire : récupérer
automatiquement l'IP du conteneur et démarrer Consul avec les bons paramètres.
Parce
que personne n'a envie de faire du docker inspect à chaque
redémarrage
!
IP=$(getent hosts $HOSTNAME | awk '{ print $1 }') - Cette ligne
magique récupère l'IP du conteneur dans le réseau Docker. Plus besoin de deviner
ou de hardcoder une IP !
-serverMode serveur (pas agent)-uiActive l'interface web-client="0.0.0.0"Écoute sur toutes les interfaces-bind="$IP"IP d'écoute pour le cluster-advertise="$IP"IP annoncée aux autres nœuds
-bootstrap-expect=1 indique à Consul qu'il n'y aura qu'un seul
serveur dans le cluster. Parfait pour notre NAS, mais attention à ne pas
utiliser cette configuration pour un vrai cluster distribué !
-data-dir="/consul/data"- Stockage persistant des données-config-dir="/consul/config"- Répertoire de configuration-log-level="INFO"- Niveau de logs équilibré-disable-host-node-id=true- Désactive l'ID basé sur l'hôte (recommandé pour Docker)
Le exec final remplace le processus shell par Consul, permettant une
gestion propre des signaux Docker (PID 1). C'est la différence
entre un
script amateur et un
script professionnel !
Docker attribue des IPs dynamiques aux conteneurs. Ce script évite les configurations statiques fragiles et s'adapte automatiquement à l'environnement Docker Swarm, même si l'IP change.
#!/bin/sh
# Retrieves the IP on the 'secret' network (adapt the interface name if needed)
IP=$(getent hosts $HOSTNAME | awk '{ print $1 }')
echo "Starting Consul with IP: $IP"
# Read encryption key in secret Docker Swarm
if [ -f /run/secrets/consul-encrypt-key ]; then
ENCRYPT_KEY=$(cat $CONSUL_ENCRYPT_KEY_FILE)
echo "Encrypt key load from secret"
else
echo "ERROR: Secret consul-encrypt-key not found!"
exit 1
fi
exec consul agent \
-server \
-ui \
-client="0.0.0.0" \
-bind="$IP" \
-advertise="$IP" \
-bootstrap-expect=1 \
-data-dir="/consul/data" \
-config-dir="/consul/config" \
-log-level="INFO" \
-encrypt="$ENCRYPT_KEY" \
-datacenter="$CONSUL_DATACENTER" \
-domain="$CONSUL_DOMAIN" \
-node="$CONSUL_NODE_NAME" \
-disable-host-node-id=true
Ce fichier vault.hcl est le cerveau de notre Vault. Contrairement au
server.hcl minimaliste, celui-ci contient tous les paramètres essentiels pour
faire
tourner notre coffre-fort en mode production.
ui = true
Active l'interface web de Vault, parce que personne n'a envie de tout faire en
ligne de commande (même si c'est possible).
storage "consul"
Vault utilise Consul comme backend de stockage. C'est du
mariage arrangé qui fonctionne parfaitement : Consul gère la persistance,
Vault
gère la sécurité. Pour une solution encore plus simple, il est tout à fait
possible de se passer complètement de Consul et de configurer Vault pour
qu'il
stocke ses données directement sur l'hôte, via un backend comme
file.
address = "consul:8500"Adresse du serveur Consul (nom Docker)path = "vault/"Chemin de stockage dans le KV store Consulscheme = "http"Protocole HTTP (réseau interne sécurisé)session_ttl = "15s"Durée de vie des sessions Consullock_wait_time = "15s"Temps d'attente pour les verrous
listener "tcp"
Configuration du listener HTTP sur le port 8200 avec TLS
désactivé car géré par le reverse proxy Synology. Le chiffrement ne sera pas
strictement de bout en bout, puisque c'est le reverse proxy qui termine la
connexion TLS. Cependant, comme ce proxy est hébergé sur le même hôte que
Vault,
le trafic non chiffré entre le proxy et Vault ne transite que sur
l'interface
localhost.
Ce compromis est généralement acceptable dans un environnement contrôlé, tant que l'hôte est correctement sécurisé. Toutefois, pour une configuration de production à haute sensibilité, il est recommandé d'activer TLS directement dans Vault afin d'assurer un chiffrement complet, même en local.
Pour plus de détails sur le fonctionnement du mTLS consultez l'article ici.
Les paramètres x_forwarded_for_* permettent à Vault de récupérer
les vraies adresses IP des clients qui passent par le reverse proxy. Essentiel
pour l'audit et la sécurité !
default_lease_ttl = "168h"7 jours par défaut pour les secretsmax_lease_ttl = "720h"30 jours maximum, parce qu'il faut bien une limiteapi_addr = "https://vault.internal"URL publique via le reverse proxy
log_level = "INFO" et
log_format = "standard"
Configuration optimisée pour Synology avec logs lisibles et niveau d'information
approprié.
disable_mlock = false
Active le verrouillage mémoire (mlock) pour éviter que des
secrets
ne se retrouvent
dans le swap. C'est la bonne pratique recommandée par HashiCorp pour une
instance sérieuse de Vault.
Par défaut, les containers Docker ne peuvent pas utiliser
mlock(),
mais ici on a ajouté
la capacité IPC_LOCK (merci cap_add), ce qui
permet à
Vault de protéger ses
secrets correctement, même en container.
Bref, si tu veux dormir tranquille, tu laisses ça à false (oui,
c'est contre-intuitif,
mais c'est bien false qui signifie : "je n'empêche
pas
Vault d'utiliser
mlock()"). 🛡️
disable_clustering = true
Désactive le clustering Vault car nous n'avons qu'un seul
nœud. Simplifie la configuration.
# Active l'interface web de Vault
ui = true
# Configuration du backend de stockage Consul
storage "consul" {
# Adresse du serveur Consul
address = "consul:8500"
# Chemin de stockage dans Consul
path = "vault/"
# Protocole (HTTP car réseau interne)
scheme = "http"
# Configuration de session Consul
# Durée de vie des sessions
session_ttl = "15s"
# Temps d'attente pour les verrous
lock_wait_time = "15s"
}
# Listener HTTP - TLS géré par le reverse proxy Synology
listener "tcp" {
address = "0.0.0.0:8200"
# TLS désactivé (géré par le reverse proxy)
tls_disable = 1
# Configuration pour les en-têtes X-Forwarded-For
x_forwarded_for_authorized_addrs = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
x_forwarded_for_hop_skips = 0
x_forwarded_for_reject_not_authorized = false
x_forwarded_for_reject_not_present = false
}
# Configuration pour le reverse proxy HTTPS
# URL publique via reverse proxy
api_addr = "https://vault.internal"
disable_clustering = true
# Activer mlock pour éviter le swap sur l'hôte
disable_mlock = false
# Configuration des logs
log_level = "INFO"
# Format lisible pour Synology
log_format = "standard"
# Configuration des baux (leases)
# 7 jours par défaut
default_lease_ttl = "168h"
# 30 jours maximum
max_lease_ttl = "720h"
Le agent.hcl configure Vault-Agent, le composant qui transforme
notre infrastructure en véritable usine à certificats automatisée. C'est lui qui
se
connecte à Vault,
s'authentifie tout seul comme un grand, et génère nos certificats SSL sans
intervention humaine.
La section vault définit comment l'agent se connecte au serveur
Vault avec une stratégie de retry robuste (5 tentatives) pour gérer les
redémarrages et les problèmes réseau temporaires. Chaque tentative est plus
longue que la précédente afin de laisser le temps au Vault de démarrer.
L'agent utilise la méthode AppRole pour s'authentifier automatiquement auprès de Vault.
- Sécurité : Les paires sont révocables et assignables à des politiques de gestion plus fines.
- Automatisation : Pas besoin d'intervention ou d'interaction humaine. C'est fait pour les scripts, les jobs ou les agents !
- Rotation : Les secret_id peuvent être renouvelés automatiquement.
remove_secret_id_file_after_reading = false
La section template est le cœur de l'automatisation. Elle surveille
le template /vault/templates/cert.tpl et génère automatiquement les
certificats.
writeToFileécrit systématiquement les fichiers à chaque rendu du template, même si le contenu n'a pas changé.- Le fichier
destinationest quant à lui comparé avant écriture : Vault Agent ne le réécrit que si son contenu diffère du précédent. - Le script
command(ex : redémarrage d'un service) est déclenché uniquement si le fichierdestinationest mis à jour. - C'est pourquoi il est recommandé de regrouper dans un seul fichier
destinationtous les éléments critiques (certificat, clé, CA concaténés), pour éviter des redémarrages inutiles.
- Surveillance L'agent surveille en permanence la validité du certificat (en interne).
- Génération Quand le certificat approche de l'expiration, le template est exécuté (à 90% du TTL ou lors d'un redémarrage de l'agent).
-
Déploiement
Le script
restart_service.shest automatiquement exécuté uniquement si le fichierdestinationa changé.
Cela évite de redémarrer le service inutilement si seuls les fichiers générés parwriteToFileont été écrits mais sans modification réelle du certificat.
Il est tout à fait possible de définir plusieurs sections template dans le
fichier de configuration de Vault-Agent. Chacune peut cibler un certificat
différent, un chemin spécifique dans Vault, et avoir son propre script de
démarrage (command) associé.
Cela te permet de générer autant de certificats que nécessaire, chacun avec des paramètres distincts (chemins, rôles, SAN, TTL, etc.). C'est particulièrement utile si tu dois équiper plusieurs services, applications ou interfaces réseau avec des certificats différents, tout en gardant une configuration centralisée et cohérente.
Astuce supplémentaire
Si tu utilises plusieurs templates avec chacun leur propre
destination et command, veille à bien gérer
l'ordre
des redémarrages pour éviter des interruptions partielles ou en double.
disable_mlock = false
Active le verrouillage mémoire (mlock) pour éviter que des
secrets
ne se retrouvent
dans le swap. C'est la bonne pratique recommandée par HashiCorp pour une
instance sérieuse de Vault.
Par défaut, les containers Docker ne peuvent pas utiliser
mlock(),
mais ici on a ajouté
la capacité IPC_LOCK (merci cap_add), ce qui
permet à
Vault de protéger ses
secrets correctement, même en container.
Bref, si tu veux dormir tranquille, tu laisses ça à false (oui,
c'est contre-intuitif,
mais c'est bien false qui signifie : "je n'empêche
pas
Vault d'utiliser
mlock()"). 🛡️
En résumé, ce fichier transforme Vault-Agent en véritable assistant personnel qui gère tout le cycle de vie des certificats SSL : authentification, génération, déploiement et redémarrage des services. Plus besoin de se lever à 3h du matin parce qu'un certificat a expiré !
# Configuration de connexion à Vault
vault {
address = "http://vault:8200"
retry {
# Nombre de tentatives de reconnexion
num_retries = 5
}
}
# Authentification automatique via AppRole
auto_auth {
method "approle" {
mount_path = "auth/approle"
config = {
# Fichiers contenant les identifiants AppRole
role_id_file_path = "/run/secrets/vault_role_id"
secret_id_file_path = "/run/secrets/vault_secret_id"
# Garde le secret_id pour éviter les re-authentifications
remove_secret_id_file_after_reading = false
}
}
}
# Activer mlock pour éviter le swap sur l'hôte
disable_mlock = true
# Template pour générer les certificats SSL
template {
# Template source
source = "/vault/templates/cert.tpl"
# Fichier de sortie
destination = "/certs/myCert/all-certs"
# Script post-génération
command = "/bin/sh /vault/config/restart_service.sh"
}
restart_service.sh : Quand Docker rencontre
Synology
Le script restart_service.sh fait le lien entre notre conteneur
Vault
Agent
et le système hôte Synology. Il permet de redémarrer nginx (ou d'autres
services)
automatiquement après la mise à jour des certificats, évitant ainsi toute
intervention manuelle.
Comment redémarrer un service système depuis un conteneur Docker ? La solution repose sur :
chrootpour basculer la racine du système de fichiers vers le système hôte- Un volume Docker
/:/host:romonté en lecture seule, exposant le système Synology à l'intérieur du conteneur
chroot /host « maquille » le conteneur en système hôte, lui
permettant d'exécuter les commandes système du Synology.
La commande synosystemctl restart nginx est
spécifique au DSM de
Synology : c'est l'équivalent de systemctl sur Linux classique.
- Sécurité : Le volume est monté en lecture seule
(
:ro) pour limiter les risques - Isolation : Le conteneur n'a accès qu'à ce dont il a besoin
- Automatisation : Le redémarrage se fait sans intervention humaine
- Simplicité : Pas besoin de services additionnels ou de mécanismes complexes de communication inter-processus
Pour que chroot fonctionne correctement, le conteneur Vault
Agent
doit être lancé avec l'utilisateur root et la capability
SYS_CHROOT activée.
Vérifie aussi que le montage du volume vers /host est
correctement
configuré.
🔧 Alternatives possibles :
Redémarrage manuel- Nécessite une intervention humaine
- Peu adapté à l'automatisation
- Un fichier flag écrit par le conteneur, surveillé par un cron ou un service hôte
- Complexité et risques d'incohérence liés à la synchronisation
- Implique un processus écouteur sur l'hôte
- Complexité accrue de mise en place
En résumé, ce script court et simple est une solution pragmatique et efficace pour relier Vault Agent et la gestion des services système sous Synology.
#!/bin/bash
# Script de redémarrage automatique des services après mise à jour des certificats
# Utilisé par Vault Agent via la directive `command` dans le template
set -euo pipefail
NGINX_RESTART_CMD="chroot /host /usr/syno/bin/synosystemctl restart nginx"
echo "Certificates deployed"
echo "Restarting nginx..."
if $NGINX_RESTART_CMD; then
echo "Nginx restarted successfully"
else
echo "Error while restarting nginx"
exit 1
fi
echo "Deployment completed successfully"
Ce template est le cœur de notre système de génération automatique de certificats. Il utilise la syntaxe des templates Vault-Agent pour générer des certificats SSL/TLS et les déployer automatiquement dans l'architecture Synology.
Anatomie du template :
Le template utilise la fonction pkiCert de Vault-Agent pour
générer
un certificat via l'API PKI de Vault (que l'on va créer en Phase 3), puis
déploie les différents composants
dans les fichiers requis par Synology. Tu peux écrire tous les certificats
que
tu souhaites et même faire plusieurs templates du moment qu'ils sont
déclarés
dans
le agent.hcl.
Paramètres de génération du certificat :
pki/issue/internal-server: Chemin vers le rôle PKI configuré dans Vault.common_name=nas.internal: Nom principal du certificat (CN).alt_names=consul.internal,vault.internal: Noms alternatifs (SAN).ttl=2160h: Durée de vie du certificat (90 jours).
{{ .Cert }}{{ .CA }}{{ .Key }}
Cette ligne concatène la clé privée, le certificat et la chaîne
d'autorité
dans un seul fichier nommé all-certs, utilisé par Vault
Agent pour suivre l'état du certificat.
Supprimer ce fichier sur l'hôte ne force pas automatiquement un renouvellement immédiat. Toutefois, cette suppression peut être détectée par Vault Agent si celui-ci est redémarré ou si son cache local est effacé, ce qui déclenche alors la régénération des certificats. Cette manipulation est utile si tu souhaites appliquer des modifications comme ajouter des SAN, changer la durée de vie (TTL) ou modifier d'autres paramètres du certificat.
Le template utilise la fonction writeToFile pour créer
automatiquement les fichiers nécessaires avec les bonnes permissions dans
l'archive des certificats Synology.
privkey.pem: Clé privée (permissions 0600, propriétaire root : format attendu par Synology)cert.pem: Certificat seul (permissions 0644, propriétaire root : format attendu par Synology)fullchain.pem: Certificat + CA (permissions 0644, propriétaire root : format attendu par Synology)all-certs: Fichier principal contenant tout (format attendu par Vault)
À chaque exécution du template (renouvellement du certificat),
Vault-Agent
génère
un nouveau certificat, l'écrit dans les fichiers appropriés, puis
déclenche
le
script restart_service.sh pour redémarrer nginx et
appliquer
les
nouveaux certificats.
Ce template illustre parfaitement la puissance de Vault-Agent : une seule configuration qui gère génération, déploiement et rechargement automatique des certificats. Plus besoin de se soucier des renouvellements manuels !
{{- with pkiCert "pki/issue/internal-server" "common_name=nas.internal" "alt_names=consul.internal,vault.internal" "ttl=2160h" -}}
{{ .Cert }}{{ .CA }}{{ .Key }}
{{- .Key | writeToFile "/certs/myCert/privkey.pem" "root" "root" "0600" -}}
{{- .Cert | writeToFile "/certs/myCert/cert.pem" "root" "root" "0644" -}}
{{- .Cert | writeToFile "/certs/myCert/fullchain.pem" "root" "root" "0644" -}}
{{- .CA | writeToFile "/certs/myCert/fullchain.pem" "root" "root" "0644" "append" -}}
{{- end -}}
Maintenant, on va déployer notre première stack, celle qui contient Consul et Vault. En effet, on travaille avec deux fichiers docker-compose.yml distincts, donc deux stacks séparées :
swarm_consul_vault.ymlpour Consul et Vaultswarm_vault_agent.ymlpour le Vault-agent
# Avant de déployer, il va nous falloir un reseau
docker network create --driver overlay --attachable --scope swarm secret
# On va également avoir besoin du hash d'une clef de chiffrement symétrique de 32 bytes pour Consul
KEY=$(openssl rand -base64 32); echo "Generated key: $KEY"; echo "$KEY" | docker secret create consul_encrypt_key -
# Vérification des secrets
docker secret ls
# Déploiement de la première stack (Consul + Vault)
docker stack deploy -c /volume1/docker/secret/swarm_consul_vault.yml secret
# Vérification que tout est bien déployé
docker stack services secret
Les secrets Docker sont chiffrés au repos et ne sont accessibles qu'aux services autorisés. C'est bien mieux que des fichiers .env qui traînent partout !
Je n'ai malheureusement pas encore trouvé comment chiffrer le flux réseau entre les composants dans le docker de Synology. Ajouter cette option dans la création du réseau semble bloquer le déploiement des conteneurs — probablement à cause d'un droit manquant au niveau du noyau, ou un autre mécanisme de sécurité interne.
Bref, ça ne fonctionne pas pour le moment.
Donc, si tu as besoin d'augmenter la sécurité, je te conseille de configurer un mTLS (mutual TLS) pour chiffrer la communication entre tes conteneurs, soit via un proxy type Traefik, soit directement en configurant des certificats dans tes services. Mais ça dépasse le cadre de cet article.
La clé de Consul (aka la clé gossip) n'est pas critique à mort, puisqu'elle ne sert qu'à chiffrer les communications entre les nœuds Consul. Pas touche aux données elles-mêmes, donc pas de panique côté secrets ou KV.
Théoriquement, tu peux la remplacer si tu l'as perdu — mais bon, c'est la galère : chaque nœud doit connaître la nouvelle clé, il faut gérer une période où nœuds supportent l'ancienne et la nouvelle (mode double clé, ambiance “team building”), et une mauvaise manip peut carrément éclater ton cluster en plusieurs morceaux. Bref, tu m'as compris...
Moralité : garde-la bien précieusement dans un coin. Je me suis même cassé le dos à t'écrire une commande qui te l'affiche, alors profites-en bien !
Si tout va bien, tu devrais voir 2 services dans cette première stack : consul et vault. Souvient toi, le Vault-agent, lui n'est pas lancé pour le moment car il a besoin de Vault configuré pour s'authentifier.
Cette gestion en deux stacks séparées n'est pas très pratique, mais Swarm ne permet pas de sélectionner les services à déployer dans une stack unique. C'est la solution la plus propre pour avancer sereinement : d'abord déployer ce qui fonctionne, puis, une fois les identifiants prêts, déployer la deuxième stack pour le Vault-agent.
Étape 3 : Initialisation de Vault
Là, c'est le moment crucial. Vault est démarré mais pas encore initialisé. On va créer les clés de chiffrement et le token root :
# Initialisation de Vault (à faire une seule fois !)
docker exec -it $(docker ps -qf "name=secret_vault.1") vault operator init
ULTRA IMPORTANT !
Cette commande va afficher 5 clés de déchiffrement et 1 token root. SAUVEGARDE TOUT ÇA DANS UN ENDROIT SÛR ! Si tu perds ces clés, tu peux dire adieu à toutes tes données Vault. Sérieusement, pas de blague. Ce n'est pas la même chose que la clef de Consul là.
Moi je les mets dans mon gestionnaire de mots de passe, certains les impriment et les mettent dans un coffre. À toi de voir, mais NE LES PERDS PAS !
Étape 4 : Vérification Consul et Vault
Avant d'aller plus loin, il est temps de vérifier que Consul et Vault ont démarré correctement et communiquent l'un avec l'autre, sinon la suite ne sert à rien vu qu'on va s'appuyer dessus. Comme dit le proverbe du dev : "mieux vaut vérifier deux fois que débugger toute la nuit" 😅
On va donc faire un petit check-up de nos services, histoire de s'assurer que tout ce beau monde se parle correctement avant de passer aux choses sérieuses.
Pour commencer, vérifions que Consul dans son coin est OK. Il suffit d'aller sur http://__NAS_IP__:8500 (oui, encore une interface web, je sais, on dirait que tout passe par le browser maintenant...)
Si ça mouline trop longtemps, c'est soit
que le service n'est pas encore complètement démarré (patience,
jeune padawan), soit qu'il y a un souci d'initialisation. Dans ce
cas, un petit docker logs consul peut t'éclairer sur ce
qui foire.
Ton interface devrait t'afficher ton (tes ?) nœud(s) de Consul avec un petit Active voter. Si tu vois ça, c'est que Consul a bien pris ses responsabilités de leader du cluster (même si on n'a qu'un seul nœud, il faut bien quelqu'un pour commander !)
Si c'est le cas, félicitations, c'est que ça tourne !
Ensuite on va vérifier l'état de la communication entre le Vault et le Consul, pour ce faire clique sur ton serveur "synology-01-consul". C'est là que ça devient intéressant, on va voir si nos deux services se parlent comme de vieux copains ou s'ils se boudent encore...
Et là, surprise ! Tu noteras le Vault Sealed Status au-dessus du HealthCheck du Consul. Un beau rouge bien visible, impossible de le louper !
C'est tout à fait normal et attendu, on vient à peine de créer le Vault qui est scellé pour le moment. D'où le pavé rouge du dessus où j'ai bien bien BIEN insisté pour que tu conserves les 5 clés que l'initialisation t'a générées. J'espère que tu ne les as pas perdues dans un coin de ton bureau ou pire, dans un fichier texte nommé "passwords.txt" sur le bureau... 😱
À chaque fois que le service détectera le moindre truc, le Vault se mettra en "sécurité". C'est comme un chien de garde numérique qui se réveille dès qu'il entend du bruit !
C'est son mécanisme pour protéger tes secrets, c'est très bien comme ça mais cela nécessitera que tu viennes toi-même le déverrouiller. Oui, c'est chiant, mais c'est le prix de la sécurité !
Sache enfin que le verrouillage n'est pas qu'esthétique, il bloque complètement les accès. Tant que tu ne le débloques pas, c'est comme coffre-fort fermé : impossible de récupérer ou déposer quoi que ce soit dedans ! Même les applications qui essaient d'accéder aux secrets vont se prendre un beau "403 Forbidden".
Je sais qu'il y a des petits malins qui s'amusent à coder des scripts pour unseal automatiquement le Vault. NE LE FAIS PAS : ce sont des idiots. C'est comme construire un coffre-fort ultra-sécurisé… puis percer un trou dedans parce que t'as la flemme de tourner la clé. Sérieusement, qui ferait ça dans une banque ? Bah là, c'est pareil !
En gros :Redémarrage = Vault scellé = Toi qui dois te lever pour le déverrouiller. C'est le côté moins fun de la sécurité...
Avant de quitter l'interface Consul, si tu vas dans la section Key/Value tu devrais voir une entrée "vault" apparaître. C'est le moment "aha !" où tu réalises que tout commence à bien communiquer !
Oui c'est en effet là que Vault va venir écrire tout son fourbi ! C'est un peu pour ça qu'on a installé Consul d'ailleurs, histoire que les données ne se baladent pas sur un disque en vrac. Consul fait office de backend de stockage distribué, bien plus classe qu'un simple fichier JSON qui traîne...
Si tu regardes bien, tu verras que Vault stocke ses données sous forme de clés-valeurs dans Consul. C'est du JSON encodé, mais heureusement on n'aura jamais à triturer ça à la main (ouf !). De toute façon si tu t'amuses à aller voir dedans, tout est chiffré et donc illisible ! Eh oui, c'est à ça que vont servir les clés, à déchiffrer le tout !
Maintenant, il est temps de déverrouiller (enfin !) le Vault, sans quoi comme on ne peut pas y accéder on ne pourra ni lire ni écrire dedans. Direction http://__NAS_IP__:8200. Tu devrais voir une interface dans le genre :
Si l'interface met du temps à charger, c'est normal, Vault prend son temps pour s'assurer que tout est sécurisé. La paranoia, c'est son truc !
Là il va te falloir rentrer 3 des 5 clés qu'il nous a générées à l'étape précédente. Peu importe lesquelles du moment que les 3 sont différentes ! C'est le moment de sortir ton petit carnet secret (ou ton gestionnaire de mots de passe, soyons modernes).
En fait Vault utilise le 🔐 Shamir's Secret Sharing qui permet de "diviser un secret (comme une clé maîtresse de chiffrement) en plusieurs parts, appelées shares, et définir un seuil minimal de parts à réunir pour reconstituer le secret." Bref comme on dit dans le milieu : cherche pas, c'est magique mais c'est bien pratique pour par exemple séparer ta clé sur plusieurs personnes de confiance et qu'une seule ne soit pas capable de déverrouiller seule les infos en cas de pépins :D
On a 5 clés, il en faut 3 pour déverrouiller. Donc même si tu perds 2 clés, tu peux encore accéder à tes secrets. Mais si tu en perds 3... ben c'est mort, il faudra tout réinitialiser (et dire au revoir à tes données). D'où l'importance de bien les sauvegarder !
Pas besoin que tout le monde fasse la queue derrière le même ordinateur avec son petit papier si les clés sont réparties entre plusieurs personnes. Chacun(e) peut les saisir depuis son propre poste !
Une fois déverrouillé, le Vault te demandera ta clé root. Forcément on n'a que ce seul token de connexion possible pour l'instant mais on va y remédier ! Cette clé root, c'est un peu comme le compte administrateur ultime : elle peut tout faire, alors on va vite créer des comptes plus limités par la suite.
Cette clé root, c'est celle qui était affichée lors de l'initialisation, pas les 5 clés de déverrouillage. Si tu l'as perdue... ben tu recommences tout depuis le début mais bon je l'avais écrit en rouge, c'etait pas pour rien !
Normalement à ce stade tu devrais voir l'interface du Vault (presque) vide. C'est normal, on vient de naître dans l'écosystème Vault, il n'y a encore rien dedans ! C'est comme un frigo neuf : il faut le remplir maintenant.
L'interface est plutôt clean, HashiCorp a fait du bon boulot sur l'UX. Tu vas voir, c'est bien plus user-friendly qu'on pourrait s'y attendre pour un outil de sécurité enterprise.
Si tu retournes sur celle du Consul là où on avait le status du Vault Seal, tu ne devrais plus le voir en rouge mais comme ça :
Si tout est vert, c'est que ton installation de Consul et de Vault est opérationnelle ! 🎉
Tu as maintenant une base solide pour gérer tes secrets de manière professionnelle. Consul stocke tout ça proprement, Vault chiffre et sécurise, et toi tu peux dormir tranquille en sachant que tes mots de passe ne traînent plus dans des fichiers texte un peu partout.
- ✅ Consul est up and running, prêt à stocker nos données
- ✅ Vault communique avec Consul (ils sont copains maintenant)
- ✅ Le processus de déverrouillage fonctionne (tes clés sont bonnes !)
- ✅ L'interface web répond correctement
🔧 Phase 2 : Configuration de Vault (le fun commence)
Maintenant qu'on a un Vault initialisé, on va le configurer pour qu'il devienne notre petite PKI personnelle. C'est là que ça devient intéressant !
Étape 1 : Configuration DNS
Avant tout, il faut créer des entrées DNS pour nos services. Va dans ton routeur (ou ton serveur DNS) et ajoute :
vault.internal→ IP de ton Synologyconsul.internal→ IP de ton Synology
Ensuite, on n'oublie pas d'aller configurer le reverse-proxy (celui du Synology dans mon cas) pour
faire pointer nos FQDN tout frais en HTTPS dans :
Panneau de configuration > Portail de connexion > Avancé > Proxy inversé.
Chez moi, ça donne ça.
Puis, il va te falloir installer le CLI Vault sur ta machine (pas sur le NAS, le système n'est pas standard tu ne pourras pas le faire).
Documentation officielle pour installer le CLIL'interface Web ne permet pas de générer le type d'identifiant dont on va avoir besoin, c'est pour ça que l'on installe le CLI.
Sache que tu peux très bien générer tout ce qu'il faudra par la suite également avec Terraform plutôt qu'en CLI, le provider intégré sait déjà configurer Vault.
Une fois que c'est fait, tu peux te connecter à Vault via le CLI depuis ta machine:
# Configuration de l'adresse Vault
export VAULT_ADDR="https://vault.internal"
# On ignore le self-signed certificat pour la configuration
export VAULT_SKIP_VERIFY=true
# Connexion avec le token root
vault login
# Colle ton token root ici
Pour plus de détails sur le fonctionnement des reverses proxy consultez l'article ici.
Étape 2 : Configuration AppRole
AppRole, c'est le système d'authentification qu'on va utiliser pour que Vault-Agent puisse se connecter à Vault automatiquement. C'est comme un couple login/password, mais en plus sécurisé.
# Activation de l'authentification AppRole
vault auth enable approle
# Création du rôle pour vault-agent
vault write auth/approle/role/vault-agent \
token_ttl=24h \
token_max_ttl=72h \
secret_id_ttl=0 \
secret_id_num_uses=0 \
bind_secret_id=true \
policies=vault-agent-policy
🐙 Version Terraform
Pour automatiser cette configuration, consultez ce fichier Terraform sur GitHub ici.
Ensuite, on récupère les identifiants (c'est ça qu'on va mettre dans nos secrets Docker pour le Vault-Agent avec de vrai valeurs d'authentification cette fois) :
# Création des secrets pour l'authentification (sur ton PC qui à Vault CLI)
# Récupération du role_id (c'est comme un username)
vault read -field=role_id auth/approle/role/vault-agent/role-id
# Génération d'un secret_id (c'est comme un password)
vault write -f -field=secret_id auth/approle/role/vault-agent/secret-id
# Enregistrement des secrets pour l'authentification (sur ton NAS qui à Docker)
echo "_ROLE_ID_" | docker secret create vault_role_id -
echo "_SECRET_ID_" | docker secret create vault_secret_id -
Le role_id est fixe et peut être réutilisé. Le secret_id est unique et peut être régénéré. C'est ce couple qui permet à Vault-Agent de s'authentifier.
Dans notre configuration, on a choisi que le secret_id
n'a pas de TTL (secret_id_ttl=0). En
clair, le Vault-agent utilise le couple
role_id + secret_id pour générer un token
d'authentification, qu'il va ensuite rafraîchir toutes les 24
heures, avec une tolérance maximale de 72 heures
(token_ttl=24h et token_max_ttl=72h).
Si on avait donné un TTL au secret_id, ça voudrait dire qu'il expire au bout d'un certain temps. Du coup, il faudrait arrêter l'agent, générer un nouveau secret_id manuellement, le déployer sur toutes les machines, puis redémarrer l'agent partout… Autant dire une galère sans fin, pas très pratique ni scalable !
Avec secret_id_ttl=0 et
secret_id_num_uses=0 (utilisations illimitées), le
secret_id ne périme jamais, ce qui simplifie grandement la
gestion côté Vault-agent, qui peut tourner en continu sans
interruption.
Étape 3 : Création des politiques
Les politiques Vault, c'est comme les permissions sur un système de fichiers : elles définissent qui peut faire quoi. Notre Vault-Agent aura besoin de permissions spécifiques :
# Création de la politique pour vault-agent
vault policy write vault-agent-policy - <<EOF
# Permission de créer des certificats
path "pki/issue/internal-server" {
capabilities = ["create", "update"]
}
# Permission de lire les infos de l'autorité de certification
path "pki/ca" {
capabilities = ["read"]
}
path "pki/ca/pem" {
capabilities = ["read"]
}
EOF
# Association de la politique au rôle AppRole
vault write auth/approle/role/vault-agent policies="vault-agent-policy"
Notre agent ne peut que créer des certificats et lire les infos de la CA. Il ne peut pas lire d'autres secrets ou modifier la configuration. C'est ça, la sécurité !
🐙 Version Terraform
Pour automatiser cette configuration, consultez ce fichier Terraform sur GitHub ici.
🏛️ Phase 3 : Création de notre PKI (on devient une autorité de certification)
Maintenant, on va transformer Vault en autorité de certification. En gros,
on
va créer notre propre "Let's Encrypt", mais en version maison, qui va gérer
tout seul les certificats pour notre réseau interne — sans avoir à sortir
ces horribles commandes openssl qui donnent des sueurs froides
!
Le sujet peut sembler un peu complexe au premier abord, mais ne t'inquiétes pas, je suis là pour te guider. Pour rendre tout ça plus clair et surtout plus sympa, on va utiliser une analogie simple et familière : celle d'une mairie. Tu vas voir, ça va nous aider à mieux comprendre cet univers un peu technique !
Étape 1 : Certificat racine
On va commencer par activer le moteur de gestion des certificats : notre PKI (le bureau des papiers d'identité d'une mairie) ainsi que créer le certificat racine. Ce certificat racine, c'est un peu comme le maire principal de notre ville - il va pouvoir tamponner et valider tous les autres certificats de nos services. Une fois qu'on aura notre maire en chef installé à la mairie, on pourra créer autant de certificats "citoyens" qu'on veut pour nos différents services, tous avec le tampon officiel qui va bien.
# Activation du moteur PKI
vault secrets enable pki
# Configuration de la durée de vie maximale (43800h = 5 an)
vault secrets tune -max-lease-ttl=43800h pki
# Génération du certificat racine
vault write -field=certificate pki/root/generate/internal \
common_name="Internal CA" \
issuer_name="internal-issuer" \
ttl=43800h
# Configuration des URLs de distribution
vault write pki/config/urls \
issuing_certificates="http://vault.internal/v1/pki/ca" \
crl_distribution_points="http://vault.internal/v1/pki/crl"
Le détail serait bien trop long à expliquer ici, la certification c'est un immense concept de sécurité informatique qu'il faut prendre le temps de présenter pas à pas (et crois-moi, ça mérite son propre article !). Pour le moment, contentons-nous du jargon essentiel pour comprendre ce qui se passe :
- common_name: c'est le nom de ton maire. Oui, "Hidalgo" marcherait aussi, mais là c'est pas son mandat !
- issuer_name : c'est l'étiquette qu'on colle sur son tampon officiel.
- ttl : Time To Live, c'est le mandat de ton maire : pendant 5 ans comme les présidentielles, il pourra délivrer des certificats durant cette période avant de devoir prendre sa retraite !
- issuing_certificates : où venir chercher les certificats
- crl_distribution_points : où consulter la liste des certificats révoqués (les citoyens déchus… eh oui, on est un peu certificatophobe 😬)
Ne t'inquiète pas si ça paraît compliqué, l'important c'est que Vault va s'occuper de tout ça pour nous !
Pour plus de détails sur le fonctionnement des certificats de sécurité consultez l'article ici.
🐙 Version Terraform
Pour automatiser cette configuration, consultez ce fichier Terraform sur GitHub ici.
Étape 2 : Rôle de certificat
Maintenant, on va créer un "rôle" qui définit quel type de certificats on peut générer - c'est comme créer un tampon spécialisé à la mairie. Au lieu d'avoir un seul tampon universel pour tout (ce qui serait un peu le bordel), on crée des tampons spécifiques : un pour les certificats de serveurs web, un autre pour les bases de données, etc. Notre rôle va dire "OK, avec ce tampon-là, tu peux créer des certificats pour tel ou tel usage, mais pas n'importe quoi !" :
# Création du rôle pour les certificats serveur
vault write pki/roles/internal-server \
allowed_domains="internal" \
allow_subdomains=true \
max_ttl="2160h" \
allow_any_name=false \
enforce_hostnames=true \
key_usage="DigitalSignature,NonRepudiation,KeyEncipherment,DataEncipherment" \
ext_key_usage="server_auth" \
basic_constraints="CA:FALSE"
- allowed_domains : On signe uniquement pour le domaine .internal (notre territoire national, quel beau pays, hein ? 😄)
- allow_subdomains : ... et ses sous-domaines (toutes nos régions : vault.internal, api.internal, etc.)
- max_ttl : Durée de vie maximale des certificats (2160h = 90 jours)
- allow_any_name : Pas question de signer n'importe quel nom au hasard
- enforce_hostnames : Le nom sur le certificat doit correspondre à une vraie machine
- key_usage : Fonctions de la clé, ce qu'elle peut faire (signature, chiffrement…)
- ext_key_usage : Usage spécifique, ce pour quoi le certificat va être utilisé : (authentification serveur, client, etc.)
- basic_constraints : Contraintes du certificat qui ici ne peut pas devenir lui-même une autorité pour signer d'autres certificats.
Rien de bien compliqué, ce sont juste nos règles locales : comme dans SimCity, mais avec plus de Matrix dedans.
Et tout ce qui ne respectera pas ces critères (libre à toi de les modifier hein évidemment) eh bien le maire va te rembarrer sec ! Comme à la préfecture quand il te manque une photocopie : pas de négociation, c'est non et au revoir.
🐙 Version Terraform
Pour automatiser cette configuration, consultez ce fichier Terraform sur GitHub ici.
Étape 3 : Test de génération
Allez, on fait un petit test pour voir si notre PKI fonctionne :
# Test de génération d'un certificat
vault write pki/issue/internal-server \
common_name="test.internal" \
ttl="720h"
Si ça marche, tu vas voir plein d'informations s'afficher, notamment le certificat généré - un peu comme quand tu demandes une carte d'identité et qu'ils te sortent une liasse de papiers avec plein de tampons officiels ! Si tu vois défiler des lignes de texte cryptique avec des "BEGIN CERTIFICATE" et des caractères bizarres, c'est bon signe ! 🎉 Ça veut dire que notre maire numérique a bien fait son boulot et a pondu un beau certificat tout frais !
D'ailleurs, essaie de certifier test.external par
exemple et tu vas voir que ça ne marche pas car on a dit à notre
maire de certifier "internal" et RIEN d'autre ! D'ailleurs comment
le pourrait-il vu qu'il n'a pas le tampon pour le faire ??? Si tu
demandais au maire de Paris de te délivrer un passeport américain -
il te regarderait bizarrement en mode "Désolé, moi je ne m'occupe
que des affaires parisiennes !" Notre PKI est pareil : elle est très
à cheval sur son territoire et refuse catégoriquement de signer quoi
que ce soit qui ne soit pas dans son domaine de compétence.
Il faudra déployer le CA sur tes machines ! Enfin sa clé publique pour être précis. Parce que là, on a créé notre propre maire avec son propre tampon, mais les navigateurs et applications ne le connaissent pas encore. C'est comme si tu débarquais à l'aéroport avec un passeport délivré par la République de ton salon ou si tu brandissais une carte d'identité dessiné sous Paint - techniquement valide selon tes règles, mais personne ne va le reconnaître ! Pour que tes services fassent confiance à nos certificats "maison", il faudra installer notre certificat racine sur chaque machine. Attention, on installe juste le "registre d'authenticité des signatures" du maire, pas ses pouvoirs ! Le maire reste dans notre mairie, sa clef privé ne sortira JAMAIS du Vault. Tes machines sauront reconnaître "Ah oui, ce certificat vient bien de notre maire légitime", mais elles ne pourront pas créer des certificats pour autant - c'est juste pour dire "Tu peux lui faire confiance !""
Pour le récupérer rien de plus simple :
Va sur ton Vault :
https://vault.internal > pki > issuer > internal-issuer
En haut à droite tu as un onglet Downloads
- PEM format : le CA générique pour les systèmes Linux
Il te suffira de le déposer au chemin approprié en fonction de ta distribution et de lancer la commande d'intégration - DER format : le CA reformaté pour système Windows
C'est encore plus facile, il te suffit de double-cliquer dessus et de suivre les interfaces pour l'installer dans les 'certifications racine' de ton ordinateur
Je précise que le CA n'est nécessaire que sur les machines qui ne seront pas gérées par le Vault-agent : ton PC, ton téléphone etc. Sinon c'est lui qui peut s'en charger et qui s'en chargera. C'est son taff après tout !
🔧 Phase 4 : Configuration de Synology (la partie fun)
Maintenant, on va préparer Synology pour recevoir nos beaux certificats automatiquement générés. C'est là que ça devient vraiment intéressant ! Notre objectif va être de retirer l'alerte de securité de l'interface web de Vault et Consul sur notre navigateur web donc n'oublie pas de récuperer et installer le CA !
Étape 1 : Préparation des dossiers
Synology stocke ses certificats dans un endroit bien précis. On va créer notre propre dossier de certificats :
# Connexion SSH à ton Synology
# Création du dossier pour nos certificats
sudo mkdir -p /usr/syno/etc/certificate/_archive/myCert
# Changement des permissions
sudo chown root:root /usr/syno/etc/certificate/_archive/myCert
sudo chmod 755 /usr/syno/etc/certificate/_archive/myCert
Étape 2 : Le fichier INFO
Synology utilise un fichier JSON pour lister tous les certificats disponibles. On va ajouter le nôtre :
# Backup du fichier original (on ne sait jamais)
sudo cp /usr/syno/etc/certificate/_archive/INFO /usr/syno/etc/certificate/_archive/INFO.backup
# Édition du fichier
sudo nano /usr/syno/etc/certificate/_archive/INFO
Ajoute cette section à la place la dernière accolade fermante du fichier :
,"myCert": {
"desc": "Certificat auto-généré par Vault",
"services": [
{
}
],
"user_deletable": false
}
}
Respecte bien la syntaxe JSON ! Une virgule en trop ou en moins et tout plante. Si tu as peur, fais un backup du fichier avant de le modifier.
Pendant la procédure, ne va JAMAIS sur l'interface web des certificats de Synology
Pourquoi ? Eh bien tout simplement car ils ont eu la brillante idée d'intégrer un checker auto-générant si tu cliques sur l'onglet. Ce n'est pas dramatique mais il faudra nettoyer le contenu du dossier que tu viens de créer des certificats auto-générés par Synology.
De la même manière, n'utilise pas le certificat que l'on génère pour la configuration par défaut de ton NAS, du moins tant que tu n'as pas généré des certificats valides. En effet, l'accès à l'interface web va provoquer une vérification du certificat et donc une génération auto-signée par le CA de Synology s'il n'arrive pas à l'utiliser (mal formé, expiré, etc.).
En gros, n'utilise ce certificat que pour tes services à toi, pas pour ceux de Synology et il ne viendra pas t'embeter même si tu passes par son reverse proxy.
Si tu veux automatiser les services qui devront utiliser nos certificats, tu peux les indiquer sous forme de liste dans le tableau "services". Mais attention à ne pas dupliquer des services déjà associés à d'autres certificats, sinon ton Synology risque de ne pas apprécier ! Dans cet article, on va rester simple et les appliquer via l'interface Web, une fois les certificats déployés.
🤖 Phase 5 : Lancement Vault-Agent
Bon, on y est. Le moment où tout ce qu'on a préparé en amont va (normalement) fonctionner. On va
relancer notre stack docker-compose pour cette fois activer Vault-agent (que l'on avait
retiré jusqu'ici) et déclencher le déploiement automatique de nos certificats.
Étape 1 : Déploiement de la stack Vault-Agent
Une fois que tu as les identifiants corrects et que Vault est configuré, tu peux redéployer la stack complète avec le Vault-Agent pour activer la mise à jour automatique des certificats :
# On déploie maintenant la stack complète avec Vault-Agent
docker stack deploy -c /volume1/docker/secret/swarm_vault_agent.yml secret
Ensuite, assure-toi que Vault est bien unsealed (c'est-à-dire déverrouillé). Sinon,
rien ne bougera côté génération de certificats. Si Vault est encore scellé, connecte-toi à
l'interface web (https://vault.internal) ou lance plusieurs fois la commande :
vault operator unseal
Cela déverrouille Vault avec les clés d'unseal, nécessaires pour que Vault puisse accéder à ses secrets et délivrer tes certificats.
À partir de là, Vault-Agent va :
- S'authentifier auprès de Vault grâce au mécanisme AppRole (plus sécurisé qu'un simple token)
- Se connecter au serveur Vault pour demander un certificat TLS via l'API PKI
- Générer le certificat en fonction du template que tu as défini (avec les SAN, TTL, etc.)
- Déployer les certificats au bon endroit sur ton NAS Synology (pour que DSM puisse les utiliser)
- Redémarrer automatiquement
nginx(le serveur web du NAS) pour appliquer les nouveaux certificats en direct
En clair, tu passes d'une config manuelle et casse-tête à une machine bien huilée qui bosse toute seule. Tu peux aller te faire un café pendant que ça tourne.
Étape 2 : Vérification des certificats
Maintenant que Vault-Agent a bossé, il est temps de vérifier que tout est bien généré et à sa place :
ls -l /usr/syno/etc/certificate/_archive/myCert/
Tu devrais voir apparaître :
privkey.pem→ ta clé privée (ultra sensible, permissions serrées à 0600)cert.pem→ le certificat publicfullchain.pem→ certificat + chaîne complète (certificat + CA)all-certs→ fichier utilisé par Vault pour gérer le suivi des certificats
Attention : Le redémarrage de NGINX est nécessaire pour que DSM prenne en compte les nouveaux certificats, mais cela redémarre aussi Docker. Cela veut dire que tous tes services dans ta stack Consul-Vault (et les autres) vont redémarrer aussi. Patience, attends que tout soit bien reparti avant d'aller plus loin et n'oublie pas qu'il faudra à nouveau unseal ton Vault.
Ton Vault-Agent a fait son taf, les certificats sont signés, frais et stockés pile là où Synology les attend. Plus de risques d'erreur humaine ou de certificat périmé qui fait planter ton NAS.
Le fichier all-certs joue le rôle de déclencheur principal pour le renouvellement
automatique. Si tu le supprimes, Vault-Agent va détecter son absence et générer un nouveau
certificat lors de la prochaine vérification programmée. C'est super pratique si tu veux ajouter
un SAN, ajuster la durée de vie, ou corriger une erreur dans le template de départ.
Mais attention : Vault-Agent ne compare pas le contenu sur l'hôte du fichier, il se base uniquement sur ce qu'il "sait" — c'est-à-dire la configuration initiale définie dans le template (durée, SAN, CN, etc) et le Vault. Si tu modifies un paramètre mais que tu ne redémarres pas l'agent, il ne fera pas forcément de mise à jour immédiate.
Étape 3 : Activation dans DSM
Direction DSM maintenant, dans Panneau de configuration > Sécurité > Certificat.
Tu verras apparaître les certificats générés par Vault. Il ne reste plus qu'à les assigner aux services que tu souhaites sécuriser (Vault, Consul, ton API etc, etc.) via l'onglet "Paramètres".
Ce qui est génial, c'est que le lien entre les services (ceux que tu as déclarés dans le reverse proxy) et les certificats est fait à un niveau supérieur, via le système de key-value JSON qu'on a modifié manuellement. En clair : ce n'est pas le contenu du certificat qui détermine quel service l'utilise, mais bien une référence déclarative dans un fichier de config système.
Résultat : tu peux régénérer tes certificats, les renouveler, les faire bénir par trois PKI
différentes… tant que tu ne touches pas à la déclaration JSON dans le fameux fichier
INFO, les assignations resteront intactes !
Attention quand même : si tu modifies manuellement le fichier INFO (ou
que tu fais une erreur de syntaxe, là
oui, il faudra repasser par la case “Assignation manuelle” dans DSM.
Bref, tant que tu laisses le INFO tranquille, DSM reste zen.
Étape 4 : Et maintenant ?
Avec ta PKI maison qui tourne comme une horloge suisse, tu vas pouvoir :
- Étendre facilement ta gestion des certificats : Ajoute autant de templates Vault que nécessaire, chacun adapté à un service ou un environnement spécifique.
- Déployer partout : Sur des machines physiques, des VM, des containers, des API internes, des reverse proxies, bref, tous les points qui ont besoin de TLS.
- Automatiser la maintenance : Intègre cette gestion dans un repo Git, un pipeline CI/CD, et finis les manips manuelles et les oublis. Moi je vous en propose un ...roulement de tambour... : ANSIBLE !
Pourquoi c'est cool ? Parce que tu gagnes en sécurité (plus de certificats périmés), en fiabilité (moins d'erreurs humaines), et en temps (moins de support à gérer). Et en prime, tu prépares ton infrastructure pour évoluer vers du Kubernetes, des clusters multi-serveurs, et des architectures modernes.
Dans le prochain article, on passera à la vitesse supérieure : on intégrera un
ACME challenge
pour obtenir des certificats publics juste avec Vault (pas de cerbot ou autres), signés par une
vraie autorité de certification (genre
Let's Encrypt). Fini les certificats auto-signés, place à la
gloire publique pour exposer sur Internet nos applications !
Stay tuned !
Debug & Commandes utiles
Si jamais ça coince ou que tes certificats ne sont pas pris en compte, voici quelques commandes clés pour redémarrer les services essentiels sur ton Synology qui risquent de ce bloquer:
/usr/syno/bin/synosystemctl restart nginx
synopkg start FileService
synopkg start ContainerManager
Ces commandes permettent de relancer :
- NGINX : le serveur web qui gère notamment l'interface DSM et la prise en charge des certificats TLS.
- FileService : le service de gestion des fichiers, souvent impacté lors de changements dans les accès sécurisés.
- ContainerManager : le gestionnaire des conteneurs Docker, nécessaire pour que Vault-Agent et autres services fonctionnent correctement.
Redémarrer ces services évite d'avoir à redémarrer complètement ton NAS, ce qui est beaucoup plus pratique et rapide.
Quand ça coince, c'est souvent NGINX qui se retrouve avec des certificats dans un état ambigu : un bout à
moitié remplacé, un autre qui traîne… Résultat, il ne sait plus quoi charger et plante en silence. Tu
peux confirmer ça avec journalctl, mais franchement, le plus rapide, c'est de faire un
reset en bonne et due forme.
Voici la procédure simple pour revenir à un état propre :
- Commence par vider manuellement ton dossier de certificats (ou le renommer si tu veux garder une copie).
- Va dans l'interface DSM, section Panneau de configuration > Sécurité > Certificat.
- DSM va détecter l'absence de certificats et générer automatiquement un nouveau certificat auto-signé via son propre CA.
- Redémarre NGINX pour qu'il prenne en compte les nouveaux certificats :
/usr/syno/bin/synosystemctl restart nginx
Et enfin — oui, c'est contre-intuitif mais important — vide à nouveau le dossier de certificats car il va te faire plein de fichiers dont tu n'as pas besoin.
Et voilà ! Tu es revenu à zéro proprement, avec un DSM content, un NGINX relancé, et un Vault prêt à redéposer ses petits PEM tout frais.
Cette astuce combinée aux commandes de redémarrage te permet de restaurer rapidement un état fonctionnel, notamment si un certificat est corrompu ou mal configuré, sans provoquer d'interruption longue sur ton système.
Pas de panique : ce ne sont que des certificats. Tant que tu ne remplaces pas les certificats utilisés par Synology pour ses services internes, rien de vraiment casse-cou — tu peux y aller franco, tu ne vas pas le casser ton NAS !