Quel gestionnaire de secrets auto-hébergé choisir ?
Comparez OpenBao, Infisical, SOPS avec age, les credentials systemd et un fichier env verrouillé pour choisir une solution adaptée à un seul VPS.
Ce qu’un gestionnaire de secrets auto-hébergé fait contrairement à un gestionnaire de mots de passe
Un gestionnaire de secrets auto-hébergé fournit des identifiants aux processus. Un gestionnaire de mots de passe les fournit aux utilisateurs. Tout le reste découle de cette différence. Un gestionnaire de mots de passe est déverrouillé par une personne présente et attentive. Un gestionnaire de secrets doit fournir le mot de passe d’une base de données à votre application à 03:00, alors que personne n’est réveillé.
Les modes de défaillance sont différents, et cette différence est importante. Un gestionnaire de mots de passe verrouillé est simplement gênant : vous saisissez de nouveau le mot de passe principal. Un gestionnaire de secrets scellé provoque une interruption de service : chaque service qui redémarre pendant qu’il est scellé démarre sans identifiants et reste arrêté. Utiliser Vaultwarden comme gestionnaire de mots de passe personnel résout bien le problème humain. Il ne résout pas le problème des machines, et n’a jamais été conçu pour cela. Si vous l’exécutez parallèlement à cette solution, les éléments à renforcer en priorité sont son jeton d’administration et son fichier de sauvegarde, plutôt que le contenu du coffre, que le client chiffre déjà. Renforcer la sécurité de Vaultwarden couvre ces deux éléments.
Pour un seul serveur, les options réalistes se répartissent en deux groupes. OpenBao et Infisical sont des services : une API, une base de données, TLS (transport layer security), une étape de connexion et un processus qu’il faut désormais maintenir actif. SOPS avec age, les credentials systemd et les secrets Docker sont des fichiers : chiffrés au repos, déchiffrés par un composant déjà en fonctionnement, sans élément supplémentaire à surveiller.
Voici directement la réponse. Pour une seule machine utilisée par une ou deux personnes, les options basées sur des fichiers sont généralement adaptées. Un OpenBao que personne ne déscelle correctement et dont personne ne fait la rotation est pire qu’un fichier d’environnement en mode 600, car il ajoute un composant mobile et une sauvegarde que vous configurerez probablement mal. Il ne vous apporte par ailleurs aucune rotation que vous n’effectuiez déjà manuellement.
Un fichier d’environnement en mode 600 est-il suffisant ?
Souvent, oui. La menace concernée est celle d’un autre utilisateur de la machine qui lirait le mot de passe de votre base de données. Les permissions des fichiers Unix empêchent cela, avant même que le réseau soit disponible.
sudo install -d -m 750 -o root -g myapp /etc/myapp
sudo install -m 640 -o root -g myapp /dev/null /etc/myapp/env
sudoedit /etc/myapp/envVérifiez-le des deux côtés :
sudo -u myapp cat /etc/myapp/env
sudo -u nobody cat /etc/myapp/envLa première commande affiche le contenu du fichier. La seconde affiche cat: /etc/myapp/env: Permission denied, car nobody n’appartient pas au groupe myapp et le fichier n’accorde aucune permission aux autres utilisateurs. C’est tout le modèle de sécurité, et il est réel.
La fuite se produit ensuite. Une unité systemd utilisant EnvironmentFile= copie ces valeurs dans l’environnement du processus, qui est lisible.
[Service]
User=myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/usr/local/bin/myappsudo cat /proc/$(pgrep -n myapp)/environ | tr '\0' '\n'Cette commande affiche vos secrets en clair, car /proc/<pid>/environ est lisible par root et par l’utilisateur sous lequel le processus s’exécute. Un outil de collecte des rapports de plantage qui joint l’environnement au rapport voit la même chose. Il en va de même pour tout outil exécuté sous le même compte. C’est pourquoi exclure les secrets des agents IA commence par les exclure de l’environnement. Associez le fichier à un utilisateur de service dédié disposant de faibles privilèges afin que « l’utilisateur sous lequel le processus s’exécute » ne soit pas root.
SOPS avec age : chiffrer les secrets que vous pouvez versionner dans git
SOPS (secrets operations) chiffre les valeurs d’un fichier YAML ou JSON et laisse les clés en clair. age est un outil de chiffrement léger qui fournit une seule paire de clés, sans serveur de clés. Ensemble, ils vous permettent de versionner secrets.enc.yaml avec votre code. git diff indique toujours quel paramètre a changé, sans révéler sa nouvelle valeur.
age est fourni dans Ubuntu 24.04. SOPS ne l’est pas. Téléchargez donc le .deb depuis la page des releases. La version 3.13.3 était la version courante en août 2026.
sudo apt update && sudo apt install -y age
curl -LO https://github.com/getsops/sops/releases/download/v3.13.3/sops_3.13.3_amd64.deb
sudo apt install -y ./sops_3.13.3_amd64.deb
sops --versionGénérez une paire de clés. age-keygen écrit la clé privée dans le fichier et affiche la clé publique. Vous verrez donc une ligne qui commence par Public key: age1....
mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt
chmod 600 ~/.config/sops/age/keys.txt
age-keygen -y ~/.config/sops/age/keys.txtPlacez la clé publique dans .sops.yaml, à la racine du dépôt. Vous n’aurez ainsi jamais besoin de mémoriser le destinataire sur la ligne de commande.
creation_rules:
- age: age1s3cqcks5genc6ru8chl0hkkd04zmxvczsvdxq99ekffe4gmvjpzsedk23csops encrypt secrets.yaml > secrets.enc.yaml
sops decrypt secrets.enc.yamlUne règle sans path_regex correspond à tout. C’est ce qu’il faut au début. Si vous en ajoutez un plus tard, faites-la correspondre au fichier que vous transmettez à sops. Les règles sont évaluées par rapport au chemin d’entrée, et non par rapport au fichier dans lequel vous redirigez la sortie.
À l’exécution, transmettez les valeurs à un seul processus, et à aucun autre :
sops exec-env secrets.enc.yaml './myapp'sops exec-env déchiffre les valeurs en mémoire et les définit dans l’environnement du processus enfant. Aucun texte en clair n’est donc écrit sur le disque. La réserve concernant l’environnement, présentée dans la section précédente, s’applique toujours à cet enfant.
Deux problèmes reviennent souvent. Sous systemd, l’erreur Failed to get the data key required to decrypt the SOPS file signifie presque toujours que SOPS a cherché dans le mauvais répertoire personnel, car une unité n’hérite pas de votre HOME. Définissez explicitement le chemin avec Environment=SOPS_AGE_KEY_FILE=/etc/sops/age.txt dans l’unité. Par ailleurs, modifier .sops.yaml ne rechiffre rien de ce qui existe déjà. Ajouter la clé publique d’un collègue ne concerne que les nouveaux fichiers. Exécutez donc sops updatekeys secrets.enc.yaml sur chaque fichier existant. Si votre configuration passe déjà par Ansible, chiffrer les mêmes valeurs avec Ansible Vault permet d’obtenir le même résultat sans ajouter un deuxième outil.
Identifiants systemd : des secrets qui n’atteignent jamais l’environnement
Ubuntu 24.04 fournit systemd 255, aucune installation n’est donc nécessaire. systemd-creds chiffre un secret sur l’hôte, puis systemd le déchiffre dans un répertoire privé que seul le service concerné peut lire.
sudo systemd-creds setup
sudo install -d -m 700 /etc/myapp
echo -n 'hunter2' | sudo systemd-creds encrypt --name=db_password - /etc/myapp/db_password.cred[Service]
User=myapp
LoadCredentialEncrypted=db_password:/etc/myapp/db_password.cred
ExecStart=/usr/local/bin/myappLe service lit la valeur dans un fichier nommé db_password, situé dans le répertoire indiqué par $CREDENTIALS_DIRECTORY. La valeur ne figure pas dans l’environnement. /proc/<pid>/environ n’affiche donc rien d’utile, et le texte en clair n’est jamais écrit sur le système de fichiers racine.
Vérifiez que le fichier peut être déchiffré avant de le référencer dans une unité :
sudo systemd-creds decrypt /etc/myapp/db_password.cred -Identifiez la clé utilisée pour le chiffrement, car cela détermine l’utilité de votre sauvegarde. Par défaut, --with-key=auto utilise la puce TPM2 (trusted platform module version 2) lorsqu’elle est présente et utilisable. Sinon, il utilise la clé de l’hôte. La plupart des instances VPS ne disposent pas de TPM2.
systemd-analyze has-tpm2no signifie que la clé de l’hôte a été utilisée. Cette clé se trouve dans /var/lib/systemd/credential.secret et seul root peut la lire. Si vous restaurez db_password.cred sur un nouveau VPS sans ce fichier, rien ne pourra jamais le déchiffrer. Copiez credential.secret dans la même sauvegarde, ou conservez le texte en clair à un emplacement toujours accessible.
Secrets Docker : fichiers sous /run/secrets
Compose lit un fichier sur l’hôte et le monte dans le conteneur à l’emplacement /run/secrets/<name>.
services:
app:
image: myapp:latest
environment:
DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./db_password.txtdocker compose exec app cat /run/secrets/db_password
docker compose exec app env | grep -i passwordLa première commande affiche le secret. La seconde affiche uniquement DB_PASSWORD_FILE=/run/secrets/db_password, ce qui est l’objectif : la valeur n’est jamais présente dans l’environnement du conteneur et n’apparaît donc pas dans la sortie de docker inspect. De nombreuses images officielles attendent déjà ce format. L’image Postgres lit POSTGRES_PASSWORD_FILE exactement de cette manière.
Soyez clair sur la nature de ce mécanisme. En dehors du mode Swarm, il n’y a aucun chiffrement, à aucun niveau : ./db_password.txt est un fichier en clair sur l’hôte. Sa seule protection repose sur ses permissions et son propriétaire. Définissez vous-même ces deux éléments, car Compose montera sans avertissement un fichier lisible par tous. Pour une comparaison plus complète avec le raccourci env_file, consultez le guide des fichiers d’environnement et des secrets Compose.
Ce que coûtent réellement OpenBao et Vault
OpenBao est le fork de HashiCorp Vault maintenu par la Linux Foundation. Le projet a été lancé après que HashiCorp a placé Vault sous la Business Source License en 2023. OpenBao reste sous MPL 2.0 (Mozilla Public License). La version 2.6.2 était la version actuelle en août 2026. Presque tout ce qui suit s’applique aussi à Vault, car le fork a conservé la même interface de commandes.
docker pull docker.io/openbao/openbaoLes paquets Debian et Ubuntu sont disponibles sur la page de téléchargement d’OpenBao si vous préférez gérer les mises à jour avec apt. Le serveur a besoin d’un fichier de configuration contenant un listener et un backend de stockage :
listener "tcp" {
address = "127.0.0.1:8200"
tls_cert_file = "/path/to/full-chain.pem"
tls_key_file = "/path/to/private-key.pem"
}
storage "raft" {
path = "/path/to/raft/data"
node_id = "raft_node_1"
}Démarrez-le ensuite une fois :
bao operator initPar défaut, cela divise la root key en 5 parts et exige 3 parts pour procéder au unseal. Ce sont les flags -key-shares et -key-threshold. OpenBao affiche les parts et le root token initial une seule fois, puis ne les affiche plus jamais.
Voici le point que la plupart des comparatifs omettent. Un serveur redémarré est un serveur sealed. OpenBao conserve la root key uniquement en mémoire. Après un redémarrage, il ne peut donc plus déchiffrer son propre stockage tant que quelqu’un ne lui a pas fourni le nombre requis de parts. Une mise à jour du kernel ou un kill pour manque de mémoire se termine donc par un serveur sealed et des applications qui ne peuvent plus se connecter.
Sur un VPS utilisé par une seule personne, le partage de Shamir ne protège rien, car les 5 parts finissent dans le même password manager appartenant à cette même personne. L’auto-unseal déplace la key vers un appareil ou un service de confiance. Dans un grand cloud, il s’agit généralement d’un service de gestion de clés managé. Sur votre VPS, il s’agit habituellement d’un fichier de clé stocké sur le même disque que les données qu’il protège. Il s’agit d’une réduction réelle de la sécurité, acceptée en échange d’un serveur qui redémarre automatiquement après un reboot. Faites ce choix en connaissance de cause et notez la décision prise.
Infisical : une interface, une base de données et une clé maître que vous devez conserver
Infisical est une plateforme de gestion des secrets avec une interface web, des projets, des environnements et un contrôle d’accès par utilisateur. Son auto-hébergement avec Compose est rapide :
curl -o docker-compose.prod.yml https://raw.githubusercontent.com/Infisical/infisical/main/docker-compose.prod.yml
curl -o .env https://raw.githubusercontent.com/Infisical/infisical/main/.env.example
docker compose -f docker-compose.prod.yml up -dModifiez .env avant d’exécuter cette dernière commande. Deux valeurs doivent être les vôtres, et l’une d’elles ne doit plus jamais changer ensuite :
openssl rand -hex 16
openssl rand -base64 32La première est ENCRYPTION_KEY, une chaîne hexadécimale de 16 octets. Il s’agit de la clé utilisée pour chiffrer vos secrets dans PostgreSQL. Si vous la perdez, une sauvegarde parfaite de la base de données devient un ensemble de données chiffrées inutilisables. Si vous la modifiez sur une instance en fonctionnement, les secrets existants ne peuvent plus être déchiffrés. La seconde est AUTH_SECRET, une chaîne base64 de 32 octets utilisée pour les sessions. SITE_URL doit être l’URL absolue que vous utiliserez réellement pour accéder au service, protocole inclus. Sinon, la redirection après la connexion échoue.
Infisical convient mieux qu’OpenBao lorsque votre besoin principal concerne les utilisateurs : une interface web pour une petite équipe et une séparation entre les environnements, plutôt que des identifiants de base de données qui expirent automatiquement. En contrepartie, vous devez gérer PostgreSQL, Redis et un certificat TLS, avec leurs mises à jour et leurs sauvegardes.
Que se passe-t-il lorsque le service de secrets est indisponible et que votre application redémarre
Cette question détermine si un service de secrets peut fonctionner sur un serveur unique. Les fichiers sont lisibles avant le démarrage du réseau. Ce n’est pas le cas d’un service.
Redémarrez le serveur. Votre application et OpenBao démarrent au même moment. L’application demande le mot de passe de sa base de données, OpenBao est encore scellé, la requête échoue et systemd redémarre l’application en boucle jusqu’à ce qu’une personne saisisse les fragments de déscellement. Rien n’est cassé. Mais rien ne fonctionne non plus.
Il existe deux façons réalistes de gérer ce cas. Ordonnez les unités et laissez l’application réessayer : After= le service de secrets, avec Restart=on-failure et un RestartSec= suffisamment long pour ne pas saturer l’API. Ou récupérez le secret au moment du déploiement plutôt qu’au démarrage : générez-le dans un fichier en mode 600 ou dans un identifiant d’authentification systemd, afin que le système en fonctionnement dépende d’un fichier plutôt que d’une API.
L’expiration d’un jeton pose le même problème, mais sur une durée plus longue. Les jetons et les baux OpenBao ont une durée de vie. Un processus qui s’exécute longtemps sans renouveler son accès le perd à un moment sans rapport avec un déploiement. Cet échec est déroutant précisément parce que rien n’a changé ce jour-là.
Sauvegarder le magasin lui-même
Chaque option repose sur une clé, et une sauvegarde sans cette clé ne sert à rien. Notez où se trouve la vôtre.
Avec un fichier env, le fichier contient le secret : la sauvegarde doit donc être chiffrée. Avec SOPS, le fichier chiffré peut être stocké n’importe où publiquement. La clé privée age située à ~/.config/sops/age/keys.txt est l’élément à ne surtout pas perdre. Pour les credentials systemd, sauvegardez /var/lib/systemd/credential.secret avec les fichiers .cred. Avec Infisical, effectuez un dump PostgreSQL et stockez ENCRYPTION_KEY séparément.
OpenBao avec un stockage raft crée son propre snapshot :
bao operator raft snapshot save backup.snap
bao operator raft snapshot restore backup.snapLe snapshot contient votre stockage chiffré. Sa restauration sur un nouveau serveur nécessite donc toujours les parts d’unseal de bao operator init. Une tâche nocturne qui copie les snapshots vers un stockage objet alors que les parts ne sont stockées nulle part ne constitue pas une sauvegarde. Testez la restauration sur un VPS temporaire avant de vous y fier.
Journalisation d’audit : qui a lu quel secret
Les fichiers ne fournissent aucune trace d’audit. Le mode et le propriétaire indiquent qui pourrait lire le secret. Ils n’indiquent jamais qui l’a effectivement lu. auditd avec une surveillance du chemin est le meilleur substitut, mais il indique qu’un fichier a été ouvert, pas quelle valeur a été utilisée.
OpenBao journalise chaque requête dans un audit device que vous activez explicitement :
bao audit enable file file_path=/var/log/openbao_audit.logDeux caractéristiques de ce journal modifient la façon dont vous exploitez le serveur. La plupart des chaînes présentes dans les requêtes et les réponses sont hachées avec HMAC-SHA256 et un salt. Vous pouvez donc comparer au journal une valeur que vous connaissez déjà, sans que le journal contienne lui-même la valeur en clair. Les entiers et les booléens sont écrits en clair. Un secret numérique n’est donc pas protégé par ce hachage.
Le piège opérationnel est le suivant : OpenBao ne répond pas aux requêtes lorsqu’aucun audit device activé ne peut les enregistrer. Un device qui échoue de manière bloquante fait attendre les requêtes jusqu’à ce que quelqu’un corrige le problème. Un disque plein sur /var/log arrête volontairement votre API de secrets. Réservez un espace propre au journal d’audit et configurez une règle logrotate dès le premier jour, pas après la première panne.
Quel gestionnaire de secrets auto-hébergé devez-vous utiliser ?
Comptez les machines et les personnes, puis choisissez.
- Une machine, une personne : utilisez un fichier d’environnement avec les permissions
600, détenu parrootet lisible par un utilisateur de service. Ajoutez les credentials systemd lorsque vous voulez que la valeur ne soit pas présente dans l’environnement du processus. - Une machine, de deux à cinq personnes, avec une configuration déjà versionnée dans git : utilisez SOPS avec age. Chaque personne possède une paire de clés, et
.sops.yamlrépertorie chaque clé publique autorisée à déchiffrer les données. - Plusieurs machines, un dépôt de configuration et aucun besoin de credentials qui expirent : utilisez toujours SOPS avec age, avec une clé destinataire par hôte. Ainsi, une clé d’hôte volée ne permet de déchiffrer que les fichiers de cet hôte.
- Plusieurs machines et plusieurs équipes qui ont réellement besoin de credentials de base de données avec une durée de validité, ainsi que d’une piste d’audit effectivement consultée : utilisez OpenBao et prévoyez une heure par mois de temps opérateur pour les opérations de unseal et les exercices de restauration.
La règle sous-jacente est la même dans les quatre cas. Utilisez la solution la plus simple qui répond à une exigence que vous pouvez formuler clairement, car un gestionnaire de secrets indisponible est impossible à distinguer d’un gestionnaire de secrets vide.
FAQ
Un gestionnaire de secrets auto-hébergé est-il utile pour un seul VPS ?
En général, non, si vous parlez d’un service comme OpenBao ou Infisical. Sur une seule machine utilisée par une ou deux personnes, un fichier d’environnement en mode 600 ou un identifiant chiffré de systemd offre la même protection contre un autre utilisateur local, sans étape de déscellement ni service supplémentaire à maintenir à jour. Un service de secrets devient réellement utile lorsque vous avez plusieurs machines et plusieurs personnes, ou lorsque vous avez besoin d’identifiants qui expirent sans qu’une personne doive les renouveler manuellement.
Quelle est la différence entre un gestionnaire de mots de passe et un gestionnaire de secrets ?
Un gestionnaire de mots de passe stocke les identifiants saisis par une personne, qui le déverrouille lorsqu’elle est présente. Un gestionnaire de secrets fournit des identifiants aux processus. Il doit donc fonctionner à 03:00 sans personne pour le surveiller. C’est cette contrainte qui les distingue : un gestionnaire de mots de passe verrouillé vous oblige à saisir de nouveau un mot de passe maître, tandis qu’un gestionnaire de secrets scellé arrête tous les services qui redémarrent pendant qu’il est scellé.
Que deviennent mes applications si OpenBao est scellé après un redémarrage ?
Elles ne peuvent pas récupérer leurs secrets. Elles échouent donc au démarrage, et systemd les redémarre en boucle jusqu’à ce qu’une personne fournisse le seuil de déscellement, qui est de 3 parts sur 5 par défaut. OpenBao conserve la clé root uniquement en mémoire. Chaque redémarrage le scelle donc de nouveau. Vous pouvez activer le déscellement automatique, en acceptant que, sur un VPS unique, la clé de déscellement se retrouve sur le même disque que les données. Vous pouvez aussi générer les secrets dans un fichier au moment du déploiement, afin que le démarrage ne dépende jamais de l’API.
Puis-je envoyer des fichiers chiffrés par SOPS dans un dépôt public ?
Les valeurs sont chiffrées. Elles sont donc protégées contre toute personne qui ne possède pas la clé privée age. Les clés, elles, ne sont pas chiffrées : un lecteur peut voir que vous détenez STRIPE_SECRET_KEY et SMTP_PASSWORD, ainsi que la fréquence à laquelle chacun change. Ces métadonnées sont acceptables pour la plupart des projets, mais pas pour certains. Conservez la clé privée age en dehors du dépôt et exécutez sops updatekeys sur chaque fichier existant chaque fois que vous ajoutez ou supprimez un destinataire.