# ============================================================ # Vaultwarden — vault.opytex.org # ============================================================ # Déploiement : # sops exec-env secrets.env.yaml 'docker compose up -d' # services: vaultwarden: image: vaultwarden/server:1.35.7 container_name: vaultwarden restart: unless-stopped security_opt: - no-new-privileges:true volumes: - vaultwarden_data:/data env_file: - env_file environment: # Les deux seules valeurs sensibles. `${VAR:?}` fait échouer le # démarrage si `sops exec-env` a été oublié, au lieu de recréer le # conteneur avec des valeurs vides. # # Régénérer le token admin en hash argon2 : # docker run --rm -it vaultwarden/server:1.35.7 /vaultwarden hash --preset owasp ADMIN_TOKEN: ${ADMIN_TOKEN:?} SSO_CLIENT_SECRET: ${SSO_CLIENT_SECRET:?} networks: - traefik-proxy - smtp labels: - traefik.enable=true - traefik.docker.network=traefik-proxy # --- Router principal (UI + API clients Bitwarden) --- # `priority` explicite : sans elle, Traefik la déduit de la longueur de # la règle — 23 pour Host(`vault.opytex.org`), contre 26 forcés sur le # router /admin. Trois caractères de marge seulement : un domaine plus # long ferait passer ce router devant, et /admin perdrait le forward auth. - traefik.http.routers.vaultwarden.entrypoints=web-secure - traefik.http.routers.vaultwarden.rule=Host(`vault.opytex.org`) - traefik.http.routers.vaultwarden.priority=10 - traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt - traefik.http.routers.vaultwarden.service=vaultwarden - traefik.http.routers.vaultwarden.middlewares=crowdsec@file # --- /admin : CrowdSec + forward auth Authentik --- # Porte de secours si le SSO tombe (SSO_ONLY=true côté env_file). - traefik.http.routers.vaultwarden-admin.entrypoints=web-secure - traefik.http.routers.vaultwarden-admin.rule=Host(`vault.opytex.org`) && PathPrefix(`/admin`) - traefik.http.routers.vaultwarden-admin.priority=26 - traefik.http.routers.vaultwarden-admin.tls.certresolver=letsencrypt - traefik.http.routers.vaultwarden-admin.service=vaultwarden - traefik.http.routers.vaultwarden-admin.middlewares=crowdsec@file,authentik@file # --- Callback Authentik (outpost) --- - traefik.http.routers.vaultwarden-outpost.entrypoints=web-secure - traefik.http.routers.vaultwarden-outpost.rule=Host(`vault.opytex.org`) && PathPrefix(`/outpost.goauthentik.io/`) - traefik.http.routers.vaultwarden-outpost.priority=25 - traefik.http.routers.vaultwarden-outpost.tls.certresolver=letsencrypt - traefik.http.routers.vaultwarden-outpost.service=vaultwarden-outpost-svc - traefik.http.services.vaultwarden.loadbalancer.server.port=80 - traefik.http.services.vaultwarden-outpost-svc.loadbalancer.server.url=http://authentik:9000 volumes: # PAS de `labels:` ici, volontairement. # # Les labels de volume ne s'appliquent qu'à la création. En déclarer un sur # `vaultopytexorg_vaultwarden_data`, qui existe depuis longtemps, ne l'aurait # pas seulement laissé sans effet : Compose détecte la divergence entre le # volume et sa déclaration, et propose de le RECRÉER — donc de détruire le # coffre. Répondre « y » à cette question est irréversible. # # La sauvegarde de ce volume passe donc par MANUAL_VOLUMES dans backup.conf. # Le label reste la bonne méthode, mais seulement pour un volume neuf. vaultwarden_data: networks: traefik-proxy: external: true smtp: external: true