# Vaultwarden — VPS (ROOTLESS PODMAN) port of the home server's ~/Server/vaultwarden, # staged 2026-08-12. # # This is the live instance serving vault.gbrown.org. The home server copy is retired. # # Rootless adaptations: # - :Z on the data mount (SELinux Enforcing). # - /etc/localtime mount dropped in favour of TZ (AGENTS.md §8). # - No published port; NPM proxies to http://vaultwarden:80 over nginx-bridge. # - Image starts as root and drops privileges internally, so no userns_mode needed. # # ADMIN_TOKEN lives in the mode-600 .env (which ~/Server/backup copies, so restores # have it). volume/config.json also holds admin_token and OVERRIDES the env value; # saving settings in the /admin panel writes it there. Keep the two in sync. networks: nginx-bridge: external: true services: vaultwarden: image: docker.io/vaultwarden/server:latest container_name: vaultwarden hostname: vaultwarden domainname: vault.gbrown.org networks: - nginx-bridge environment: - TZ=America/New_York - DOMAIN=https://vault.gbrown.org - LOGIN_RATELIMIT_MAX_BURST=10 - LOGIN_RATELIMIT_SECONDS=60 - WEB_VAULT_ENABLED=true - SIGNUPS_ALLOWED=false - WEBSOCKET_ENABLED=true - ADMIN_TOKEN=${ADMIN_TOKEN:?set ADMIN_TOKEN in .env} # ── SSO via Authentik (app slug "vaultwarden", admin group only) ───── # SSO replaces the email step only. The vault is still unlocked with the # master password, because that is what the vault is encrypted with. # SSO_ONLY stays off so password login keeps working for everyone. # Existing accounts link by email, and Authentik must send # email_verified=true for that (its "email_custom" scope mapping does). # The authority needs its trailing slash. - SSO_ENABLED=true - SSO_ONLY=false - SSO_AUTHORITY=https://auth.gbrown.org/application/o/vaultwarden/ - SSO_SCOPES=openid profile email offline_access - SSO_CLIENT_ID=${SSO_CLIENT_ID:?set SSO_CLIENT_ID in .env} - SSO_CLIENT_SECRET=${SSO_CLIENT_SECRET:?set SSO_CLIENT_SECRET in .env} # ── SMTP via the UseSend proxy on this host ─────────────────────────── # These used to live in volume/config.json (written by the admin panel). # config.json OVERRIDES env, so those keys were removed from it; leaving # them would silently win over everything below. # # Reached by the smtp.usesend.gbrown.org network alias, not the container # name, so the *.gbrown.org wildcard cert passes hostname verification -- # which is why ACCEPT_INVALID_* can stay false. # # FROM must be on a UseSend-verified domain. Bare gbrown.org is NOT # verified; vault.gbrown.org is. - SMTP_HOST=smtp.usesend.gbrown.org - SMTP_PORT=587 - SMTP_SECURITY=starttls - SMTP_USERNAME=usesend - SMTP_PASSWORD=${USESEND_API_KEY:?set USESEND_API_KEY in .env} - SMTP_FROM=admin@vault.gbrown.org - SMTP_FROM_NAME=Gib's Vault Admin - SMTP_TIMEOUT=15 - SMTP_ACCEPT_INVALID_CERTS=false - SMTP_ACCEPT_INVALID_HOSTNAMES=false - SMTP_EMBED_IMAGES=true labels: com.centurylinklabs.watchtower.enable: "true" volumes: - ./volume:/data:Z tty: true restart: unless-stopped