Files
rick-infra/roles/vaultwarden/README.md
Joakim bfd6f22f0e Add Vaultwarden password manager role with PostgreSQL and SSO support
- Implement complete Vaultwarden deployment using Podman Quadlet
- PostgreSQL backend via Unix socket with 777 permissions
- Caddy reverse proxy with WebSocket support for live sync
- Control-node admin token hashing using argon2 (OWASP preset)
- Idempotent token hashing with deterministic salt generation
- Full Authentik SSO integration following official guide
- SMTP email configuration support (optional)
- Invitation-only user registration by default
- Comprehensive documentation with setup and troubleshooting guides

Technical Details:
- Container: vaultwarden/server:latest from Docker Hub
- Database: PostgreSQL via /var/run/postgresql socket
- Port: 8080 (localhost only, proxied by Caddy)
- Domain: vault.jnss.me
- Admin token: Hashed on control node with argon2id
- SSO: OpenID Connect with offline_access scope support

Role includes automatic argon2 installation on control node if needed.
2025-12-22 21:33:27 +01:00

10 KiB

Vaultwarden Password Manager Role

Self-contained Vaultwarden (Bitwarden-compatible) password manager deployment using Podman and PostgreSQL.

Overview

This role deploys Vaultwarden as a Podman Quadlet container with:

  • PostgreSQL backend via Unix socket (777 permissions)
  • Caddy reverse proxy with HTTPS and WebSocket support
  • SSO integration ready (Authentik OpenID Connect)
  • SMTP support for email notifications (optional)
  • Admin panel for management

Architecture

Internet → Caddy (HTTPS) → Vaultwarden Container → PostgreSQL (Unix socket)
                                                  ↓
                                            /data volume

Components

  • Container Image: vaultwarden/server:latest (Docker Hub)
  • User: System user vaultwarden (non-root)
  • Port: 8080 (localhost only)
  • Domain: vault.jnss.me
  • Database: PostgreSQL via Unix socket at /var/run/postgresql
  • Data: /opt/vaultwarden/data

Dependencies

Managed Hosts:

  • postgresql role (provides database and Unix socket)
  • caddy role (provides reverse proxy)

Control Node:

  • argon2 command-line tool (automatically installed if not present)
    • Used to hash the admin token securely on the control node
    • Available in most package managers: pacman -S argon2, apt install argon2, etc.

Configuration

Required Variables

Must be defined in vault (e.g., group_vars/homelab/vault.yml):

# Database password
vault_vaultwarden_db_password: "secure-database-password"

# Admin token (plain text - will be hashed automatically during deployment)
vault_vaultwarden_admin_token: "your-secure-admin-token"

# SMTP password (if using email)
vault_vaultwarden_smtp_password: "smtp-password"  # optional

# SSO credentials (if using Authentik integration)
vault_vaultwarden_sso_client_id: "vaultwarden"  # optional
vault_vaultwarden_sso_client_secret: "sso-secret"  # optional

Optional Variables

Override in group_vars or host_vars:

# Domain
vaultwarden_domain: "vault.jnss.me"

# Container version
vaultwarden_version: "latest"

# Registration controls
vaultwarden_signups_allowed: false  # Disable open registration
vaultwarden_invitations_allowed: true  # Allow existing users to invite

# SMTP Configuration
vaultwarden_smtp_enabled: true
vaultwarden_smtp_host: "smtp.example.com"
vaultwarden_smtp_port: 587
vaultwarden_smtp_from: "vault@jnss.me"
vaultwarden_smtp_username: "smtp-user"

# SSO Configuration (Authentik)
vaultwarden_sso_enabled: true
vaultwarden_sso_authority: "https://auth.jnss.me"

Usage

Deploy Vaultwarden

# Full deployment
ansible-playbook rick-infra.yml --tags vaultwarden

# Or via site.yml
ansible-playbook site.yml --tags vaultwarden -l homelab

Access Admin Panel

  1. Set admin token in vault file (plain text):

    # Generate a secure token
    vault_vaultwarden_admin_token: "$(openssl rand -base64 32)"
    
  2. The role automatically hashes the token during deployment:

    • Hashing occurs on the control node using argon2 CLI
    • Uses OWASP recommended settings (19MiB memory, 2 iterations, 1 thread)
    • Idempotent: same token always produces the same hash
    • The argon2 package is automatically installed if not present
  3. Access: https://vault.jnss.me/admin (use the plain text token from step 1)

Configure SSO (Authentik Integration)

⚠️ IMPORTANT: SSO Feature Status (as of December 2025)

SSO is currently only available in vaultwarden/server:testing images. The stable release (v1.34.3) does NOT include SSO functionality.

Current Deployment Status:

  • This role is configured with SSO settings ready for when SSO reaches stable release
  • Using vaultwarden_version: "latest" (stable) - SSO will not appear
  • To test SSO now: Set vaultwarden_version: "testing" (not recommended for production)
  • To wait for stable: Keep current configuration, SSO will activate automatically when available

References:

Decision: This deployment keeps SSO configured but uses stable image until SSO feature is production-ready.

Following the Authentik integration guide:

  1. In Authentik: Create OAuth2/OpenID Provider

    • Name: Vaultwarden
    • Client Type: Confidential
    • Redirect URIs: https://vault.jnss.me/identity/connect/oidc-signin (must be strict/exact match)
    • Scopes: Under "Advanced protocol settings", ensure these scope mappings are selected:
      • authentik default OAuth Mapping: OpenID 'openid'
      • authentik default OAuth Mapping: OpenID 'email'
      • authentik default OAuth Mapping: OpenID 'profile'
      • authentik default OAuth Mapping: OpenID 'offline_access' ⚠️ Required
    • Access token validity: Set to more than 5 minutes
    • Note the Client ID, Client Secret, and application slug (from URL or provider settings)
  2. Update Vault Variables:

    vault_vaultwarden_sso_client_id: "<client-id-from-authentik>"
    vault_vaultwarden_sso_client_secret: "<client-secret-from-authentik>"
    
  3. Enable SSO and set authority in group_vars/homelab/main.yml:

    vaultwarden_sso_enabled: true
    # Replace 'vaultwarden' with your actual application slug
    vaultwarden_sso_authority: "https://auth.jnss.me/application/o/vaultwarden/"
    
  4. Optional: SSO-Only Mode (disable password login):

    vaultwarden_sso_only: true  # Requires SSO, disables email+password
    
  5. Redeploy:

    ansible-playbook rick-infra.yml --tags vaultwarden
    
  6. Test: Log out, enter a verified email on login page, click "Use single sign-on"

    • Note: With vaultwarden_version: "latest", SSO button will not appear (feature not in stable yet)

Security Considerations

Database Access

  • Uses PostgreSQL Unix socket with 777 permissions
  • Security maintained via password authentication (scram-sha-256)
  • See: docs/socket-permissions-architecture.md

Admin Token

  • Never commit plain admin token to git
  • Use Ansible Vault for vault_vaultwarden_admin_token
  • Rotate periodically via admin panel

User Registration

  • Default: Disabled (vaultwarden_signups_allowed: false)
  • Users must be invited by existing users or created via admin panel
  • Prevents unauthorized account creation

Maintenance

Backup

Backup the following:

# Database backup (via PostgreSQL role)
sudo -u postgres pg_dump vaultwarden > vaultwarden-backup.sql

# Data directory (attachments, icons, etc.)
tar -czf vaultwarden-data-backup.tar.gz /opt/vaultwarden/data

Update Container

# Pull new image and restart
ansible-playbook rick-infra.yml --tags vaultwarden

View Logs

# Service logs
journalctl -u vaultwarden -f

# Container logs
podman logs vaultwarden -f

Restart Service

systemctl restart vaultwarden

Troubleshooting

Container won't start

# Check container status
systemctl status vaultwarden

# Check container directly
podman ps -a
podman logs vaultwarden

# Verify database connectivity
sudo -u vaultwarden psql -h /var/run/postgresql -U vaultwarden -d vaultwarden -c "SELECT 1;"

Database connection errors

  1. Verify PostgreSQL is running: systemctl status postgresql
  2. Check socket exists: ls -la /var/run/postgresql/.s.PGSQL.5432
  3. Verify socket permissions: Should be srwxrwxrwx (777)
  4. Test connection as vaultwarden user (see above)

Can't access admin panel

  1. Verify admin token is set in vault file (plain text)
  2. Check that the token was hashed successfully during deployment
  3. Ensure you're using the plain text token to log in
  4. Redeploy to regenerate hash if needed

SSO not appearing / not working

Most Common Issue: Using Stable Image

SSO is only available in testing images. Check your deployment:

# Check current image version
podman inspect vaultwarden --format '{{.ImageName}}'

# Check API config for SSO support
curl -s http://127.0.0.1:8080/api/config | grep -o '"sso":"[^"]*"'
# Empty string "" = SSO not available in this image
# URL present = SSO is available

If using vaultwarden_version: "latest": SSO will not appear (feature not in stable yet)

  • To test SSO: Set vaultwarden_version: "testing" in role defaults or group/host vars
  • For production: Wait for SSO to reach stable release (recommended)

If using vaultwarden_version: "testing" and SSO still not working:

  1. Verify Authentik provider configuration:
    • Check that offline_access scope mapping is added
    • Verify redirect URI matches exactly: https://vault.jnss.me/identity/connect/oidc-signin
    • Ensure access token validity is > 5 minutes
  2. Verify SSO authority URL includes full path with slug:
    • Should be: https://auth.jnss.me/application/o/<your-slug>/
    • Not just: https://auth.jnss.me
  3. Check client ID and secret in vault match Authentik
  4. Verify all required scopes: openid email profile offline_access
  5. Check Vaultwarden logs for SSO-related errors:
    podman logs vaultwarden 2>&1 | grep -i sso
    
  6. Test SSO flow: Log out, enter verified email, click "Use single sign-on"

File Structure

roles/vaultwarden/
├── defaults/
│   └── main.yml              # Default variables
├── handlers/
│   └── main.yml              # Service restart handlers
├── meta/
│   └── main.yml              # Role dependencies
├── tasks/
│   ├── main.yml              # Main orchestration
│   ├── user.yml              # User and directory setup
│   └── database.yml          # PostgreSQL setup
├── templates/
│   ├── vaultwarden.container # Quadlet container definition
│   ├── vaultwarden.env.j2    # Environment configuration
│   └── vaultwarden.caddy.j2  # Caddy reverse proxy config
└── README.md                 # This file

References

License

MIT