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.
This commit is contained in:
307
docs/vaultwarden-sso-status.md
Normal file
307
docs/vaultwarden-sso-status.md
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
# Vaultwarden SSO Feature Status and Configuration
|
||||||
|
|
||||||
|
**Document Date:** December 21, 2025
|
||||||
|
**Last Updated:** December 21, 2025
|
||||||
|
**Status:** SSO Configured, Waiting for Stable Release
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
|
||||||
|
Vaultwarden has been successfully deployed with **SSO integration pre-configured** for Authentik. However, SSO functionality is currently **only available in testing images** and not yet in the stable release. This document explains the current state, our decision to wait for stable, and how to activate SSO when it becomes available.
|
||||||
|
|
||||||
|
## Current Deployment Status
|
||||||
|
|
||||||
|
### What's Working
|
||||||
|
- ✅ Vaultwarden deployed successfully at `https://vault.jnss.me`
|
||||||
|
- ✅ PostgreSQL backend via Unix socket
|
||||||
|
- ✅ Admin panel accessible and working
|
||||||
|
- ✅ Email/password authentication working
|
||||||
|
- ✅ SMTP notifications configured
|
||||||
|
- ✅ All SSO environment variables correctly configured
|
||||||
|
- ✅ Authentik OAuth2 provider created and ready
|
||||||
|
|
||||||
|
### What's Not Working (By Design)
|
||||||
|
- ❌ SSO login option not appearing on login page
|
||||||
|
- ❌ "Use single sign-on" button missing
|
||||||
|
|
||||||
|
**Reason:** Using stable image (`vaultwarden/server:latest` v1.34.3) which does not include SSO code.
|
||||||
|
|
||||||
|
## Investigation Summary (Dec 21, 2025)
|
||||||
|
|
||||||
|
### Problem Reported
|
||||||
|
User deployed Vaultwarden with `vaultwarden_sso_enabled: true` and configured Authentik integration following official guides, but no SSO option appeared on the login page.
|
||||||
|
|
||||||
|
### Root Cause Identified
|
||||||
|
After investigation including:
|
||||||
|
- Service status check (healthy, running normally)
|
||||||
|
- Environment variable verification (all SSO vars present and correct)
|
||||||
|
- Configuration review (matches Authentik integration guide perfectly)
|
||||||
|
- API endpoint inspection (`/api/config` returns `"sso":""`)
|
||||||
|
- Official documentation review
|
||||||
|
|
||||||
|
**Finding:** SSO feature is only compiled into `vaultwarden/server:testing` images, not stable releases.
|
||||||
|
|
||||||
|
### Evidence
|
||||||
|
|
||||||
|
From [Vaultwarden Official Wiki](https://github.com/dani-garcia/vaultwarden/wiki):
|
||||||
|
|
||||||
|
> **Testing features**
|
||||||
|
>
|
||||||
|
> Features available in the `testing` docker image:
|
||||||
|
> - Single Sign-On (SSO), see [Documentation](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-SSO-support-using-OpenId-Connect)
|
||||||
|
|
||||||
|
From [SSO Documentation Page](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-SSO-support-using-OpenId-Connect):
|
||||||
|
|
||||||
|
> ⚠️ **Important**
|
||||||
|
>
|
||||||
|
> ‼️ ‼️ ‼️
|
||||||
|
> SSO is currently only available in the `:testing` tagged images!
|
||||||
|
> The current stable `v1.34.3` **does not** contain the SSO feature.
|
||||||
|
> ‼️ ‼️ ‼️
|
||||||
|
|
||||||
|
### API Response Analysis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# API config endpoint shows SSO not available
|
||||||
|
curl -s http://127.0.0.1:8080/api/config | grep -o '"sso":"[^"]*"'
|
||||||
|
# Returns: "sso":"" ← Empty = feature not compiled in
|
||||||
|
|
||||||
|
# Environment variables are set correctly
|
||||||
|
podman exec vaultwarden env | grep -i sso
|
||||||
|
SSO_ENABLED=true
|
||||||
|
SSO_ONLY=false
|
||||||
|
SSO_CLIENT_ID=DDOQXdwFn6pi4FtSvo7PK5b63pRzyD552xapTZGr
|
||||||
|
SSO_CLIENT_SECRET=02D308Sle2w2NPsi7UaXb3bvKKK4punFDT2LiVqKpzvEFqgPpyLysA8Z5yS4g8t4LYmsI9txLE02l5MtWP5R2RBavLhYHjNFHcwEmvYB94bOJw45YmgiGePaW4NHKcfY
|
||||||
|
SSO_AUTHORITY=https://auth.jnss.me/application/o/vaultwarden/
|
||||||
|
SSO_SCOPES="openid email profile offline_access"
|
||||||
|
# ... etc (all correct)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Conclusion:** Environment configured correctly, feature simply not available in stable release.
|
||||||
|
|
||||||
|
## Decision: Wait for Stable Release
|
||||||
|
|
||||||
|
### Rationale
|
||||||
|
|
||||||
|
**Why NOT switch to testing image:**
|
||||||
|
1. **Production stability** - This is a password manager handling sensitive credentials
|
||||||
|
2. **Testing images are volatile** - Frequent updates, potential bugs
|
||||||
|
3. **No ETA for stable** - SSO marked as "testing feature" indefinitely
|
||||||
|
4. **Current auth works fine** - Email/password login is secure and functional
|
||||||
|
5. **Configuration is ready** - When SSO reaches stable, it will work immediately
|
||||||
|
|
||||||
|
**Why keep SSO configured:**
|
||||||
|
1. **Future-ready** - No additional work needed when SSO stabilizes
|
||||||
|
2. **No harm** - Environment variables are ignored by stable image
|
||||||
|
3. **Documentation** - Clear record of SSO setup for future reference
|
||||||
|
4. **Authentik provider ready** - Already created and configured
|
||||||
|
|
||||||
|
### Alternatives Considered
|
||||||
|
|
||||||
|
| Option | Pros | Cons | Decision |
|
||||||
|
|--------|------|------|----------|
|
||||||
|
| Use `testing` image | SSO available now | Unstable, potential data loss, frequent breaking changes | ❌ Rejected |
|
||||||
|
| Wait for stable | Stable, reliable, secure | No SSO until unknown future date | ✅ **Selected** |
|
||||||
|
| Remove SSO config | Cleaner config | Requires reconfiguration later | ❌ Rejected |
|
||||||
|
| Dual deployment | Test SSO separately | Resource waste, complexity | ❌ Rejected |
|
||||||
|
|
||||||
|
## Current Configuration
|
||||||
|
|
||||||
|
### Ansible Role Variables
|
||||||
|
|
||||||
|
Location: `roles/vaultwarden/defaults/main.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Container version (stable, no SSO)
|
||||||
|
vaultwarden_version: "latest"
|
||||||
|
|
||||||
|
# SSO enabled (ready for when feature reaches stable)
|
||||||
|
vaultwarden_sso_enabled: true
|
||||||
|
vaultwarden_sso_only: false
|
||||||
|
vaultwarden_sso_client_id: "{{ vault_vaultwarden_sso_client_id }}"
|
||||||
|
vaultwarden_sso_client_secret: "{{ vault_vaultwarden_sso_client_secret }}"
|
||||||
|
vaultwarden_sso_authority: "https://auth.jnss.me/application/o/vaultwarden/"
|
||||||
|
vaultwarden_sso_scopes: "openid email profile offline_access"
|
||||||
|
vaultwarden_sso_signups_match_email: true
|
||||||
|
vaultwarden_sso_allow_unknown_email_verification: false
|
||||||
|
vaultwarden_sso_client_cache_expiration: 0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vault Variables (Encrypted)
|
||||||
|
|
||||||
|
Location: `group_vars/homelab/vault.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# SSO credentials from Authentik
|
||||||
|
vault_vaultwarden_sso_client_id: "DDOQXdwFn6pi4FtSvo7PK5b63pRzyD552xapTZGr"
|
||||||
|
vault_vaultwarden_sso_client_secret: "02D308Sle2w2NPsi7UaXb3bvKKK4punFDT2LiVqKpzvEFqgPpyLysA8Z5yS4g8t4LYmsI9txLE02l5MtWP5R2RBavLhYHjNFHcwEmvYB94bOJw45YmgiGePaW4NHKcfY"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authentik Provider Configuration
|
||||||
|
|
||||||
|
**Provider Details:**
|
||||||
|
- **Name:** Vaultwarden
|
||||||
|
- **Type:** OAuth2/OpenID Connect Provider
|
||||||
|
- **Client Type:** Confidential
|
||||||
|
- **Client ID:** `DDOQXdwFn6pi4FtSvo7PK5b63pRzyD552xapTZGr`
|
||||||
|
- **Application Slug:** `vaultwarden`
|
||||||
|
- **Redirect URI:** `https://vault.jnss.me/identity/connect/oidc-signin`
|
||||||
|
|
||||||
|
**Scopes Configured:**
|
||||||
|
- ✅ `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'`
|
||||||
|
|
||||||
|
**Token Settings:**
|
||||||
|
- Access token validity: > 5 minutes
|
||||||
|
- Refresh token enabled via `offline_access` scope
|
||||||
|
|
||||||
|
**Authority URL:** `https://auth.jnss.me/application/o/vaultwarden/`
|
||||||
|
|
||||||
|
### Deployed Environment (VPS)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deployed environment file
|
||||||
|
Location: /opt/vaultwarden/.env
|
||||||
|
|
||||||
|
# All SSO variables present and correct
|
||||||
|
SSO_ENABLED=true
|
||||||
|
SSO_AUTHORITY=https://auth.jnss.me/application/o/vaultwarden/
|
||||||
|
SSO_SCOPES="openid email profile offline_access"
|
||||||
|
# ... etc
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to Activate SSO (Future)
|
||||||
|
|
||||||
|
When Vaultwarden SSO reaches stable release:
|
||||||
|
|
||||||
|
### Automatic Activation (Recommended)
|
||||||
|
|
||||||
|
1. **Monitor Vaultwarden releases** for SSO in stable:
|
||||||
|
- Watch: https://github.com/dani-garcia/vaultwarden/releases
|
||||||
|
- Look for: SSO feature in stable image changelog
|
||||||
|
|
||||||
|
2. **Update container** (standard maintenance):
|
||||||
|
```bash
|
||||||
|
ansible-playbook rick-infra.yml --tags vaultwarden --ask-vault-pass
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Verify SSO is available**:
|
||||||
|
```bash
|
||||||
|
ssh root@69.62.119.31 "curl -s http://127.0.0.1:8080/api/config | grep sso"
|
||||||
|
# Should return: "sso":"https://vault.jnss.me" or similar
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Test SSO**:
|
||||||
|
- Navigate to: https://vault.jnss.me
|
||||||
|
- Log out if logged in
|
||||||
|
- Enter verified email address
|
||||||
|
- Click "Use single sign-on" button
|
||||||
|
- Should redirect to Authentik login
|
||||||
|
|
||||||
|
**No configuration changes needed** - Everything is already set up correctly.
|
||||||
|
|
||||||
|
### Manual Testing (Use Testing Image)
|
||||||
|
|
||||||
|
If you want to test SSO before stable release:
|
||||||
|
|
||||||
|
1. **Backup current deployment**:
|
||||||
|
```bash
|
||||||
|
ansible-playbook playbooks/backup-vaultwarden.yml # Create if needed
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Change to testing image** in `roles/vaultwarden/defaults/main.yml`:
|
||||||
|
```yaml
|
||||||
|
vaultwarden_version: "testing"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Deploy**:
|
||||||
|
```bash
|
||||||
|
ansible-playbook rick-infra.yml --tags vaultwarden --ask-vault-pass
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Test SSO** (same as above)
|
||||||
|
|
||||||
|
5. **Revert to stable** when testing complete:
|
||||||
|
```yaml
|
||||||
|
vaultwarden_version: "latest"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Warning:** Testing images may contain bugs, data corruption risks, or breaking changes. Not recommended for production password manager.
|
||||||
|
|
||||||
|
## Verification Commands
|
||||||
|
|
||||||
|
### Check Current Image Version
|
||||||
|
```bash
|
||||||
|
ssh root@69.62.119.31 "podman inspect vaultwarden --format '{{.ImageName}}'"
|
||||||
|
# Expected: docker.io/vaultwarden/server:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check SSO API Status
|
||||||
|
```bash
|
||||||
|
ssh root@69.62.119.31 "curl -s http://127.0.0.1:8080/api/config | grep -o '\"sso\":\"[^\"]*\"'"
|
||||||
|
# Current: "sso":"" (empty = not available)
|
||||||
|
# Future: "sso":"https://vault.jnss.me" (URL = available)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check SSO Environment Variables
|
||||||
|
```bash
|
||||||
|
ssh root@69.62.119.31 "podman exec vaultwarden env | grep -i sso | sort"
|
||||||
|
# Should show all SSO_* variables configured correctly
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Vaultwarden Version
|
||||||
|
```bash
|
||||||
|
ssh root@69.62.119.31 "podman exec vaultwarden /vaultwarden --version"
|
||||||
|
# Current: Vaultwarden 1.34.3
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation Updates
|
||||||
|
|
||||||
|
The following files have been updated to document this finding:
|
||||||
|
|
||||||
|
1. **`roles/vaultwarden/README.md`**
|
||||||
|
- Added warning banner in SSO configuration section
|
||||||
|
- Updated troubleshooting section with SSO status checks
|
||||||
|
- Documented stable vs testing image behavior
|
||||||
|
|
||||||
|
2. **`roles/vaultwarden/VAULT_VARIABLES.md`**
|
||||||
|
- Added SSO feature status warning
|
||||||
|
- Documented that credentials are ready but inactive
|
||||||
|
|
||||||
|
3. **`roles/vaultwarden/defaults/main.yml`**
|
||||||
|
- Added comments explaining SSO availability
|
||||||
|
|
||||||
|
4. **`docs/vaultwarden-sso-status.md`** (this document)
|
||||||
|
- Complete investigation findings
|
||||||
|
- Configuration reference
|
||||||
|
- Activation procedures
|
||||||
|
|
||||||
|
## Timeline
|
||||||
|
|
||||||
|
- **2025-07-30:** Vaultwarden v1.34.3 released (current stable)
|
||||||
|
- **2025-12-21:** Vaultwarden deployed with SSO pre-configured
|
||||||
|
- **2025-12-21:** Investigation completed, SSO status documented
|
||||||
|
- **TBD:** SSO feature reaches stable release (no ETA)
|
||||||
|
- **Future:** Automatic SSO activation on next deployment
|
||||||
|
|
||||||
|
## Related Documentation
|
||||||
|
|
||||||
|
- [Vaultwarden Official Wiki](https://github.com/dani-garcia/vaultwarden/wiki)
|
||||||
|
- [SSO Documentation](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-SSO-support-using-OpenId-Connect)
|
||||||
|
- [Authentik Integration Guide](https://integrations.goauthentik.io/security/vaultwarden/)
|
||||||
|
- [Vaultwarden Testing Features](https://github.com/dani-garcia/vaultwarden/wiki#testing-features)
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
For questions about this deployment:
|
||||||
|
- Infrastructure repo: `/home/fitz/rick-infra`
|
||||||
|
- Role location: `roles/vaultwarden/`
|
||||||
|
- Service: `vault.jnss.me`
|
||||||
|
- Host: `arch-vps` (69.62.119.31)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Status:** SSO configured and ready, waiting for upstream stable release. No action required.
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
# - Nextcloud cloud storage
|
# - Nextcloud cloud storage
|
||||||
# - Authentik SSO/authentication
|
# - Authentik SSO/authentication
|
||||||
# - Gitea git hosting
|
# - Gitea git hosting
|
||||||
|
# - Vaultwarden password manager
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# ansible-playbook playbooks/homelab.yml
|
# ansible-playbook playbooks/homelab.yml
|
||||||
@@ -30,8 +31,13 @@
|
|||||||
# name: gitea
|
# name: gitea
|
||||||
# tags: ['gitea', 'git', 'development']
|
# tags: ['gitea', 'git', 'development']
|
||||||
|
|
||||||
- name: Deploy Nextcloud
|
# - name: Deploy Nextcloud
|
||||||
|
# include_role:
|
||||||
|
# name: nextcloud
|
||||||
|
# tags: ['nextcloud', 'cloud', 'storage']
|
||||||
|
|
||||||
|
- name: Deploy Vaultwarden
|
||||||
include_role:
|
include_role:
|
||||||
name: nextcloud
|
name: vaultwarden
|
||||||
tags: ['nextcloud', 'cloud', 'storage']
|
tags: ['vaultwarden', 'vault', 'password-manager', 'security']
|
||||||
|
|
||||||
|
|||||||
331
roles/vaultwarden/README.md
Normal file
331
roles/vaultwarden/README.md
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
# 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`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 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`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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):
|
||||||
|
```yaml
|
||||||
|
# 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:**
|
||||||
|
> - [Vaultwarden Wiki - SSO Documentation](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-SSO-support-using-OpenId-Connect)
|
||||||
|
> - [Vaultwarden Testing Features](https://github.com/dani-garcia/vaultwarden/wiki#testing-features)
|
||||||
|
>
|
||||||
|
> **Decision:** This deployment keeps SSO configured but uses stable image until SSO feature is production-ready.
|
||||||
|
|
||||||
|
Following the [Authentik integration guide](https://integrations.goauthentik.io/security/vaultwarden/):
|
||||||
|
|
||||||
|
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**:
|
||||||
|
```yaml
|
||||||
|
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`:
|
||||||
|
```yaml
|
||||||
|
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):
|
||||||
|
```yaml
|
||||||
|
vaultwarden_sso_only: true # Requires SSO, disables email+password
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Redeploy**:
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull new image and restart
|
||||||
|
ansible-playbook rick-infra.yml --tags vaultwarden
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Service logs
|
||||||
|
journalctl -u vaultwarden -f
|
||||||
|
|
||||||
|
# Container logs
|
||||||
|
podman logs vaultwarden -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl restart vaultwarden
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Container won't start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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:
|
||||||
|
```bash
|
||||||
|
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
|
||||||
|
|
||||||
|
- [Vaultwarden Documentation](https://github.com/dani-garcia/vaultwarden/wiki)
|
||||||
|
- [PostgreSQL Backend Guide](https://github.com/dani-garcia/vaultwarden/wiki/Using-the-PostgreSQL-Backend)
|
||||||
|
- [SSO Configuration](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-SSO-support-using-OpenId-Connect)
|
||||||
|
- [Socket Permissions Architecture](../../docs/socket-permissions-architecture.md)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
171
roles/vaultwarden/VAULT_VARIABLES.md
Normal file
171
roles/vaultwarden/VAULT_VARIABLES.md
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
# Vaultwarden Role - Required Vault Variables
|
||||||
|
|
||||||
|
This document lists all vault-encrypted variables required by the Vaultwarden role.
|
||||||
|
|
||||||
|
## Required Variables
|
||||||
|
|
||||||
|
These variables **must** be defined in your vault file (e.g., `group_vars/homelab/vault.yml`):
|
||||||
|
|
||||||
|
### Database Credentials
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# PostgreSQL database password for vaultwarden user
|
||||||
|
vault_vaultwarden_db_password: "your-secure-database-password-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Generation**:
|
||||||
|
```bash
|
||||||
|
openssl rand -base64 32
|
||||||
|
```
|
||||||
|
|
||||||
|
### Admin Panel Access
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Plain text admin token (will be hashed during deployment)
|
||||||
|
vault_vaultwarden_admin_token: "your-secret-admin-token"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Generation**:
|
||||||
|
```bash
|
||||||
|
# Generate a secure random token
|
||||||
|
openssl rand -base64 32
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important**:
|
||||||
|
- Store as **plain text** in vault (the role will hash it automatically)
|
||||||
|
- Use the same token to access `/admin` panel
|
||||||
|
- The token is automatically hashed on the **control node** using argon2id
|
||||||
|
- Hashing uses OWASP recommended settings (m=19456, t=2, p=1)
|
||||||
|
- Hashing is **idempotent**: same token always produces same hash
|
||||||
|
- The `argon2` package is automatically installed if not present on control node
|
||||||
|
- Never commit the vault file unencrypted to git
|
||||||
|
|
||||||
|
## Optional Variables
|
||||||
|
|
||||||
|
These variables are only needed if you enable specific features:
|
||||||
|
|
||||||
|
### SMTP Configuration
|
||||||
|
|
||||||
|
Required if `vaultwarden_smtp_enabled: true`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# SMTP password for sending emails
|
||||||
|
vault_vaultwarden_smtp_password: "smtp-password-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSO Integration (Authentik)
|
||||||
|
|
||||||
|
> ⚠️ **SSO Feature Status (December 2025)**
|
||||||
|
>
|
||||||
|
> SSO is only available in `vaultwarden/server:testing` images (not in stable yet).
|
||||||
|
> This role is configured with SSO ready for when it reaches stable release.
|
||||||
|
>
|
||||||
|
> Current deployment uses `vaultwarden_version: "latest"` (stable) - SSO credentials
|
||||||
|
> below are configured but SSO will not appear until feature reaches stable.
|
||||||
|
|
||||||
|
Required if `vaultwarden_sso_enabled: true`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# OAuth2 Client ID from Authentik
|
||||||
|
vault_vaultwarden_sso_client_id: "your-client-id-here"
|
||||||
|
|
||||||
|
# OAuth2 Client Secret from Authentik
|
||||||
|
vault_vaultwarden_sso_client_secret: "your-client-secret-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Setup** (following [Authentik integration guide](https://integrations.goauthentik.io/security/vaultwarden/)):
|
||||||
|
1. Create OAuth2/OpenID Provider in Authentik:
|
||||||
|
- Redirect URI: `https://vault.jnss.me/identity/connect/oidc-signin` (exact match)
|
||||||
|
- Add scope mappings: `openid`, `email`, `profile`, `offline_access` (required)
|
||||||
|
- Access token validity: > 5 minutes
|
||||||
|
- Note the **application slug** from the provider URL
|
||||||
|
2. Copy Client ID and Secret from Authentik
|
||||||
|
3. Add credentials to vault file
|
||||||
|
4. Set the SSO authority URL in role configuration:
|
||||||
|
```yaml
|
||||||
|
vaultwarden_sso_enabled: true
|
||||||
|
vaultwarden_sso_authority: "https://auth.jnss.me/application/o/<your-slug>/"
|
||||||
|
```
|
||||||
|
5. Deploy the role
|
||||||
|
6. **Wait for SSO to reach stable**, or use `vaultwarden_version: "testing"` to test now
|
||||||
|
|
||||||
|
**Important**:
|
||||||
|
- The SSO authority must include the full path with application slug
|
||||||
|
- The `offline_access` scope mapping is **required** for Vaultwarden SSO
|
||||||
|
- Access token must be valid for more than 5 minutes
|
||||||
|
- SSO is configured and ready but will activate when stable release includes it
|
||||||
|
|
||||||
|
## Example Vault File
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
# group_vars/homelab/vault.yml (encrypted with ansible-vault)
|
||||||
|
|
||||||
|
# Vaultwarden - Database
|
||||||
|
vault_vaultwarden_db_password: "xK9mP2nR5tY8wQ3vZ7cB6sA4dF1gH0jL"
|
||||||
|
|
||||||
|
# Vaultwarden - Admin Panel (plain text, will be hashed automatically)
|
||||||
|
vault_vaultwarden_admin_token: "MySecureAdminToken123!"
|
||||||
|
|
||||||
|
# Vaultwarden - SMTP (optional)
|
||||||
|
vault_vaultwarden_smtp_password: "smtp-app-password-here"
|
||||||
|
|
||||||
|
# Vaultwarden - SSO (optional)
|
||||||
|
vault_vaultwarden_sso_client_id: "vaultwarden"
|
||||||
|
vault_vaultwarden_sso_client_secret: "sso-secret-from-authentik"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vault File Management
|
||||||
|
|
||||||
|
### Encrypt Vault File
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-vault encrypt group_vars/homelab/vault.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Edit Vault File
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-vault edit group_vars/homelab/vault.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Decrypt Vault File (temporary)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-vault decrypt group_vars/homelab/vault.yml
|
||||||
|
# Make changes
|
||||||
|
ansible-vault encrypt group_vars/homelab/vault.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
1. **Never commit unencrypted vault files**
|
||||||
|
2. **Use strong passwords** (32+ characters for database, admin token)
|
||||||
|
3. **Rotate credentials periodically** (especially admin token)
|
||||||
|
4. **Limit vault password access** (use password manager)
|
||||||
|
5. **Use separate passwords** for different services
|
||||||
|
6. **Back up vault password** (secure location, not in git)
|
||||||
|
|
||||||
|
## Verifying Variables
|
||||||
|
|
||||||
|
Test if variables are properly loaded:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible -m debug -a "var=vault_vaultwarden_db_password" homelab --ask-vault-pass
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Variable not found error
|
||||||
|
|
||||||
|
- Ensure vault file is in correct location: `group_vars/homelab/vault.yml`
|
||||||
|
- Verify file is encrypted: `file group_vars/homelab/vault.yml`
|
||||||
|
- Check variable name matches exactly (case-sensitive)
|
||||||
|
- Provide vault password with `--ask-vault-pass`
|
||||||
|
|
||||||
|
### Admin token not working
|
||||||
|
|
||||||
|
- Verify the plain text token in vault matches what you're entering
|
||||||
|
- Check for extra whitespace in vault file
|
||||||
|
- Ensure the token was hashed successfully during deployment (check ansible output)
|
||||||
|
- Try redeploying the role to regenerate the hash
|
||||||
109
roles/vaultwarden/defaults/main.yml
Normal file
109
roles/vaultwarden/defaults/main.yml
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
---
|
||||||
|
# =================================================================
|
||||||
|
# Vaultwarden Password Manager Role - Default Variables
|
||||||
|
# =================================================================
|
||||||
|
# Self-contained Vaultwarden deployment with Podman and PostgreSQL
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Service Configuration
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Service user and directories
|
||||||
|
vaultwarden_user: vaultwarden
|
||||||
|
vaultwarden_group: vaultwarden
|
||||||
|
vaultwarden_home: /opt/vaultwarden
|
||||||
|
vaultwarden_data_dir: "{{ vaultwarden_home }}/data"
|
||||||
|
|
||||||
|
# Container configuration
|
||||||
|
# NOTE: SSO feature is only available in "testing" tag (as of Dec 2025)
|
||||||
|
# Using "latest" (stable) means SSO will not appear even if configured
|
||||||
|
# SSO settings below are configured and ready for when feature reaches stable
|
||||||
|
vaultwarden_version: "latest"
|
||||||
|
vaultwarden_image: "vaultwarden/server"
|
||||||
|
|
||||||
|
# Service management
|
||||||
|
vaultwarden_service_enabled: true
|
||||||
|
vaultwarden_service_state: "started"
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Database Configuration (Self-managed)
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
vaultwarden_db_name: "vaultwarden"
|
||||||
|
vaultwarden_db_user: "vaultwarden"
|
||||||
|
vaultwarden_db_password: "{{ vault_vaultwarden_db_password }}"
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Network Configuration
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
vaultwarden_domain: "vault.jnss.me"
|
||||||
|
vaultwarden_http_port: 8080
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Vaultwarden Core Configuration
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Admin panel access token (plain text, will be hashed during deployment)
|
||||||
|
vaultwarden_admin_token_plain: "{{ vault_vaultwarden_admin_token }}"
|
||||||
|
|
||||||
|
# Registration and invitation controls
|
||||||
|
vaultwarden_signups_allowed: false # Disable open registration
|
||||||
|
vaultwarden_invitations_allowed: true # Allow existing users to invite
|
||||||
|
vaultwarden_show_password_hint: false # Don't show password hints
|
||||||
|
|
||||||
|
# WebSocket support for live sync
|
||||||
|
vaultwarden_websocket_enabled: true
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Email Configuration (Optional)
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
vaultwarden_smtp_enabled: true
|
||||||
|
vaultwarden_smtp_host: "smtp.titan.email"
|
||||||
|
vaultwarden_smtp_port: 587
|
||||||
|
vaultwarden_smtp_from: "hello@jnss.me"
|
||||||
|
vaultwarden_smtp_username: "hello@jnss.me"
|
||||||
|
vaultwarden_smtp_password: "{{ vault_vaultwarden_smtp_password | default('') }}"
|
||||||
|
vaultwarden_smtp_security: "starttls" # Options: starttls, force_tls, off
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# SSO Configuration (Optional - Authentik Integration)
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
vaultwarden_sso_enabled: false
|
||||||
|
|
||||||
|
# SSO Provider Configuration (Authentik)
|
||||||
|
vaultwarden_sso_client_id: "{{ vault_vaultwarden_sso_client_id | default('') }}"
|
||||||
|
vaultwarden_sso_client_secret: "{{ vault_vaultwarden_sso_client_secret | default('') }}"
|
||||||
|
# Authority must include full path with application slug
|
||||||
|
vaultwarden_sso_authority: "https://{{ authentik_domain }}/application/o/vaultwarden/"
|
||||||
|
vaultwarden_sso_scopes: "openid email profile offline_access"
|
||||||
|
|
||||||
|
# Additional SSO settings (per Authentik integration guide)
|
||||||
|
vaultwarden_sso_only: false # Set to true to disable email+password login and require SSO
|
||||||
|
vaultwarden_sso_signups_match_email: true # Match first SSO login to existing account by email
|
||||||
|
vaultwarden_sso_allow_unknown_email_verification: false
|
||||||
|
vaultwarden_sso_client_cache_expiration: 0
|
||||||
|
|
||||||
|
# Domain whitelist for SSO signups (comma-separated domains, empty = all)
|
||||||
|
vaultwarden_sso_signups_domains_whitelist: ""
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Caddy Integration
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Caddy configuration (assumes caddy role provides these variables)
|
||||||
|
caddy_sites_enabled_dir: "/etc/caddy/sites-enabled"
|
||||||
|
caddy_log_dir: "/var/log/caddy"
|
||||||
|
caddy_user: "caddy"
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Infrastructure Dependencies (Read-only)
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# PostgreSQL socket configuration (managed by postgresql role)
|
||||||
|
postgresql_unix_socket_directories: "/var/run/postgresql"
|
||||||
|
postgresql_client_group: "postgres-clients"
|
||||||
|
postgresql_port: 5432
|
||||||
|
postgresql_unix_socket_enabled: true
|
||||||
16
roles/vaultwarden/handlers/main.yml
Normal file
16
roles/vaultwarden/handlers/main.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
# Vaultwarden Password Manager - Service Handlers
|
||||||
|
|
||||||
|
- name: reload systemd
|
||||||
|
systemd:
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
|
- name: restart vaultwarden
|
||||||
|
systemd:
|
||||||
|
name: vaultwarden
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
- name: reload caddy
|
||||||
|
systemd:
|
||||||
|
name: caddy
|
||||||
|
state: reloaded
|
||||||
25
roles/vaultwarden/meta/main.yml
Normal file
25
roles/vaultwarden/meta/main.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
# Vaultwarden Password Manager - Role Metadata
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- role: postgresql
|
||||||
|
- role: caddy
|
||||||
|
|
||||||
|
galaxy_info:
|
||||||
|
author: Rick Infrastructure Team
|
||||||
|
description: Vaultwarden password manager deployment with PostgreSQL and Caddy
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.14"
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: ArchLinux
|
||||||
|
versions:
|
||||||
|
- all
|
||||||
|
|
||||||
|
galaxy_tags:
|
||||||
|
- vaultwarden
|
||||||
|
- bitwarden
|
||||||
|
- password-manager
|
||||||
|
- security
|
||||||
|
- postgresql
|
||||||
|
- podman
|
||||||
51
roles/vaultwarden/tasks/database.yml
Normal file
51
roles/vaultwarden/tasks/database.yml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
# Database setup for Vaultwarden - PostgreSQL via Unix Socket
|
||||||
|
|
||||||
|
- name: Test PostgreSQL socket connectivity
|
||||||
|
postgresql_ping:
|
||||||
|
login_unix_socket: "{{ postgresql_unix_socket_directories }}"
|
||||||
|
login_user: "{{ vaultwarden_user }}"
|
||||||
|
become: true
|
||||||
|
become_user: "{{ vaultwarden_user }}"
|
||||||
|
|
||||||
|
- name: Create Vaultwarden database user via socket
|
||||||
|
postgresql_user:
|
||||||
|
name: "{{ vaultwarden_db_user }}"
|
||||||
|
password: "{{ vaultwarden_db_password }}"
|
||||||
|
login_unix_socket: "{{ postgresql_unix_socket_directories }}"
|
||||||
|
login_user: postgres
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
|
||||||
|
- name: Create Vaultwarden database via socket
|
||||||
|
postgresql_db:
|
||||||
|
name: "{{ vaultwarden_db_name }}"
|
||||||
|
owner: "{{ vaultwarden_db_user }}"
|
||||||
|
encoding: UTF8
|
||||||
|
template: template0
|
||||||
|
login_unix_socket: "{{ postgresql_unix_socket_directories }}"
|
||||||
|
login_user: postgres
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
|
||||||
|
- name: Grant Vaultwarden database privileges
|
||||||
|
postgresql_privs:
|
||||||
|
db: "{{ vaultwarden_db_name }}"
|
||||||
|
privs: ALL
|
||||||
|
type: database
|
||||||
|
role: "{{ vaultwarden_db_user }}"
|
||||||
|
login_unix_socket: "{{ postgresql_unix_socket_directories }}"
|
||||||
|
login_user: postgres
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
|
||||||
|
- name: Display database setup status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
Vaultwarden database setup complete!
|
||||||
|
|
||||||
|
Database: {{ vaultwarden_db_name }}
|
||||||
|
User: {{ vaultwarden_db_user }}
|
||||||
|
Connection: Unix socket ({{ postgresql_unix_socket_directories }})
|
||||||
|
|
||||||
|
Ready for Vaultwarden container deployment
|
||||||
57
roles/vaultwarden/tasks/hash_admin_token.yml
Normal file
57
roles/vaultwarden/tasks/hash_admin_token.yml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
# Hash admin token on Ansible control node using argon2
|
||||||
|
|
||||||
|
- name: Check if argon2 is available on control node
|
||||||
|
command: which argon2
|
||||||
|
register: argon2_check
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Install argon2 on control node if not present
|
||||||
|
package:
|
||||||
|
name: argon2
|
||||||
|
state: present
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
when: argon2_check.rc != 0
|
||||||
|
run_once: true
|
||||||
|
|
||||||
|
- name: Generate deterministic salt from domain
|
||||||
|
set_fact:
|
||||||
|
vaultwarden_salt_source: "{{ vaultwarden_domain }}-{{ vaultwarden_sso_authority }}"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Create base64-encoded salt for argon2
|
||||||
|
shell: echo -n "{{ vaultwarden_salt_source }}" | sha256sum | cut -d' ' -f1 | head -c 22
|
||||||
|
register: admin_token_salt
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
changed_when: false
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Hash admin token using argon2 (OWASP preset)
|
||||||
|
shell: echo -n "{{ vaultwarden_admin_token_plain }}" | argon2 "{{ admin_token_salt.stdout }}" -id -t 2 -k 19456 -p 1 -e
|
||||||
|
register: admin_token_hash_result
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
changed_when: false
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Extract hashed admin token
|
||||||
|
set_fact:
|
||||||
|
vaultwarden_admin_token_hashed: "{{ admin_token_hash_result.stdout | trim }}"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Display token hash status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
Admin token hashed successfully on control node
|
||||||
|
|
||||||
|
Hash algorithm: argon2id
|
||||||
|
Preset: OWASP (m=19456, t=2, p=1)
|
||||||
|
Format: PHC string (Vaultwarden compatible)
|
||||||
|
Idempotent: Same token always produces same hash
|
||||||
|
|
||||||
|
The hashed token will be used in the environment configuration
|
||||||
108
roles/vaultwarden/tasks/main.yml
Normal file
108
roles/vaultwarden/tasks/main.yml
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
---
|
||||||
|
# Vaultwarden Password Manager Role - Main Tasks
|
||||||
|
# Self-contained deployment with Podman and Unix sockets
|
||||||
|
|
||||||
|
- name: Setup vaultwarden user and directories
|
||||||
|
include_tasks: user.yml
|
||||||
|
tags: [user, setup]
|
||||||
|
|
||||||
|
- name: Setup database access and permissions
|
||||||
|
include_tasks: database.yml
|
||||||
|
tags: [database, setup]
|
||||||
|
|
||||||
|
- name: Pull vaultwarden container image
|
||||||
|
containers.podman.podman_image:
|
||||||
|
name: "{{ vaultwarden_image }}:{{ vaultwarden_version }}"
|
||||||
|
state: present
|
||||||
|
tags: [containers, image-pull]
|
||||||
|
|
||||||
|
- name: Hash admin token on host
|
||||||
|
include_tasks: hash_admin_token.yml
|
||||||
|
tags: [config, admin-token]
|
||||||
|
|
||||||
|
- name: Deploy environment configuration
|
||||||
|
template:
|
||||||
|
src: vaultwarden.env.j2
|
||||||
|
dest: "{{ vaultwarden_home }}/.env"
|
||||||
|
owner: "{{ vaultwarden_user }}"
|
||||||
|
group: "{{ vaultwarden_group }}"
|
||||||
|
mode: '0600'
|
||||||
|
backup: true
|
||||||
|
notify:
|
||||||
|
- restart vaultwarden
|
||||||
|
tags: [config]
|
||||||
|
|
||||||
|
- name: Create Quadlet systemd directory
|
||||||
|
file:
|
||||||
|
path: /etc/containers/systemd
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Deploy Quadlet container file
|
||||||
|
template:
|
||||||
|
src: vaultwarden.container
|
||||||
|
dest: /etc/containers/systemd/vaultwarden.container
|
||||||
|
mode: '0644'
|
||||||
|
notify:
|
||||||
|
- reload systemd
|
||||||
|
- restart vaultwarden
|
||||||
|
tags: [containers, deployment]
|
||||||
|
|
||||||
|
- name: Deploy Caddy configuration
|
||||||
|
template:
|
||||||
|
src: vaultwarden.caddy.j2
|
||||||
|
dest: "{{ caddy_sites_enabled_dir }}/vaultwarden.caddy"
|
||||||
|
owner: root
|
||||||
|
group: "{{ caddy_user }}"
|
||||||
|
mode: '0644'
|
||||||
|
backup: true
|
||||||
|
notify: reload caddy
|
||||||
|
tags: [caddy, reverse-proxy]
|
||||||
|
|
||||||
|
- name: Ensure PostgreSQL is running
|
||||||
|
systemd:
|
||||||
|
name: postgresql
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Wait for PostgreSQL socket to be ready
|
||||||
|
wait_for:
|
||||||
|
path: "{{ postgresql_unix_socket_directories }}/.s.PGSQL.{{ postgresql_port }}"
|
||||||
|
timeout: 30
|
||||||
|
when: postgresql_unix_socket_enabled
|
||||||
|
|
||||||
|
- name: Enable and start Vaultwarden service (system scope)
|
||||||
|
systemd:
|
||||||
|
name: vaultwarden
|
||||||
|
enabled: "{{ vaultwarden_service_enabled }}"
|
||||||
|
state: "{{ vaultwarden_service_state }}"
|
||||||
|
daemon_reload: true
|
||||||
|
tags: [containers, service]
|
||||||
|
|
||||||
|
- name: Wait for Vaultwarden to be ready
|
||||||
|
uri:
|
||||||
|
url: "http://127.0.0.1:{{ vaultwarden_http_port }}/"
|
||||||
|
method: GET
|
||||||
|
status_code: [200, 302]
|
||||||
|
timeout: 30
|
||||||
|
retries: 10
|
||||||
|
delay: 15
|
||||||
|
register: vaultwarden_health_check
|
||||||
|
tags: [verification, health-check]
|
||||||
|
|
||||||
|
- name: Display Vaultwarden deployment status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
Vaultwarden Password Manager deployed successfully!
|
||||||
|
|
||||||
|
Domain: {{ vaultwarden_domain }}
|
||||||
|
Database: {{ vaultwarden_db_name }} (Unix socket)
|
||||||
|
Container: {{ vaultwarden_image }}:{{ vaultwarden_version }}
|
||||||
|
Admin Panel: https://{{ vaultwarden_domain }}/admin
|
||||||
|
|
||||||
|
Ready for user registration and password management!
|
||||||
|
|
||||||
|
Next Steps:
|
||||||
|
- Access https://{{ vaultwarden_domain }}/admin with your admin token
|
||||||
|
- Configure additional settings (SMTP, SSO, etc.)
|
||||||
|
- Invite users or create accounts
|
||||||
|
tags: [verification]
|
||||||
28
roles/vaultwarden/tasks/user.yml
Normal file
28
roles/vaultwarden/tasks/user.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
# Vaultwarden User Management - Service-Specific User Setup
|
||||||
|
|
||||||
|
- name: Create vaultwarden group
|
||||||
|
group:
|
||||||
|
name: "{{ vaultwarden_group }}"
|
||||||
|
system: true
|
||||||
|
|
||||||
|
- name: Create vaultwarden user
|
||||||
|
user:
|
||||||
|
name: "{{ vaultwarden_user }}"
|
||||||
|
group: "{{ vaultwarden_group }}"
|
||||||
|
system: true
|
||||||
|
shell: /bin/bash
|
||||||
|
home: "{{ vaultwarden_home }}"
|
||||||
|
create_home: true
|
||||||
|
comment: "Vaultwarden password manager service"
|
||||||
|
|
||||||
|
- name: Create vaultwarden directories
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ vaultwarden_user }}"
|
||||||
|
group: "{{ vaultwarden_group }}"
|
||||||
|
mode: '0755'
|
||||||
|
loop:
|
||||||
|
- "{{ vaultwarden_home }}"
|
||||||
|
- "{{ vaultwarden_data_dir }}"
|
||||||
35
roles/vaultwarden/templates/vaultwarden.caddy.j2
Normal file
35
roles/vaultwarden/templates/vaultwarden.caddy.j2
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Vaultwarden Password Manager
|
||||||
|
{{ vaultwarden_domain }} {
|
||||||
|
# Notifications endpoint (WebSocket for live sync)
|
||||||
|
@websocket {
|
||||||
|
path /notifications/hub
|
||||||
|
}
|
||||||
|
reverse_proxy @websocket http://127.0.0.1:{{ vaultwarden_http_port }} {
|
||||||
|
header_up Upgrade {http.request.header.Upgrade}
|
||||||
|
header_up Connection {http.request.header.Connection}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Regular HTTP traffic
|
||||||
|
reverse_proxy http://127.0.0.1:{{ vaultwarden_http_port }} {
|
||||||
|
header_up Host {host}
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
header_up X-Forwarded-Proto https
|
||||||
|
header_up X-Forwarded-For {remote_host}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
header {
|
||||||
|
X-Frame-Options SAMEORIGIN
|
||||||
|
X-Content-Type-Options nosniff
|
||||||
|
X-XSS-Protection "1; mode=block"
|
||||||
|
Referrer-Policy strict-origin-when-cross-origin
|
||||||
|
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log {
|
||||||
|
output file {{ caddy_log_dir }}/vaultwarden.log
|
||||||
|
level INFO
|
||||||
|
format json
|
||||||
|
}
|
||||||
|
}
|
||||||
26
roles/vaultwarden/templates/vaultwarden.container
Normal file
26
roles/vaultwarden/templates/vaultwarden.container
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Vaultwarden Password Manager Container
|
||||||
|
After=network-online.target postgresql.service
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Container]
|
||||||
|
ContainerName=vaultwarden
|
||||||
|
Image={{ vaultwarden_image }}:{{ vaultwarden_version }}
|
||||||
|
EnvironmentFile={{ vaultwarden_home }}/.env
|
||||||
|
|
||||||
|
# Volume mounts
|
||||||
|
# Application data (includes database, attachments, sends, icons, etc.)
|
||||||
|
Volume={{ vaultwarden_data_dir }}:/data:Z
|
||||||
|
|
||||||
|
# Infrastructure socket (PostgreSQL access with 777 permissions on host)
|
||||||
|
Volume={{ postgresql_unix_socket_directories }}:{{ postgresql_unix_socket_directories }}:Z
|
||||||
|
|
||||||
|
# Expose HTTP port to localhost only (Caddy will reverse proxy)
|
||||||
|
PublishPort=127.0.0.1:{{ vaultwarden_http_port }}:80
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
TimeoutStartSec=300
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
73
roles/vaultwarden/templates/vaultwarden.env.j2
Normal file
73
roles/vaultwarden/templates/vaultwarden.env.j2
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# Vaultwarden Environment Configuration
|
||||||
|
# Generated by Ansible - DO NOT EDIT MANUALLY
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Database Configuration (PostgreSQL via Unix Socket)
|
||||||
|
# =================================================================
|
||||||
|
DATABASE_URL=postgresql://{{ vaultwarden_db_user }}:{{ vaultwarden_db_password }}@/{{ vaultwarden_db_name }}?host={{ postgresql_unix_socket_directories }}
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Domain Configuration
|
||||||
|
# =================================================================
|
||||||
|
DOMAIN=https://{{ vaultwarden_domain }}
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Admin Configuration
|
||||||
|
# =================================================================
|
||||||
|
ADMIN_TOKEN={{ vaultwarden_admin_token_hashed }}
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Registration and Invitation Controls
|
||||||
|
# =================================================================
|
||||||
|
SIGNUPS_ALLOWED={{ vaultwarden_signups_allowed | lower }}
|
||||||
|
INVITATIONS_ALLOWED={{ vaultwarden_invitations_allowed | lower }}
|
||||||
|
SHOW_PASSWORD_HINT={{ vaultwarden_show_password_hint | lower }}
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# WebSocket Configuration (for live sync)
|
||||||
|
# =================================================================
|
||||||
|
WEBSOCKET_ENABLED={{ vaultwarden_websocket_enabled | lower }}
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# SMTP Configuration (Optional)
|
||||||
|
# =================================================================
|
||||||
|
{% if vaultwarden_smtp_enabled %}
|
||||||
|
SMTP_HOST={{ vaultwarden_smtp_host }}
|
||||||
|
SMTP_PORT={{ vaultwarden_smtp_port }}
|
||||||
|
SMTP_FROM={{ vaultwarden_smtp_from }}
|
||||||
|
SMTP_SECURITY={{ vaultwarden_smtp_security }}
|
||||||
|
{% if vaultwarden_smtp_username %}
|
||||||
|
SMTP_USERNAME={{ vaultwarden_smtp_username }}
|
||||||
|
SMTP_PASSWORD={{ vaultwarden_smtp_password }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# SSO Configuration (Optional - Authentik Integration)
|
||||||
|
# =================================================================
|
||||||
|
{% if vaultwarden_sso_enabled %}
|
||||||
|
SSO_ENABLED=true
|
||||||
|
SSO_ONLY={{ vaultwarden_sso_only | lower }}
|
||||||
|
SSO_CLIENT_ID={{ vaultwarden_sso_client_id }}
|
||||||
|
SSO_CLIENT_SECRET={{ vaultwarden_sso_client_secret }}
|
||||||
|
SSO_AUTHORITY={{ vaultwarden_sso_authority }}
|
||||||
|
SSO_SCOPES="{{ vaultwarden_sso_scopes }}"
|
||||||
|
SSO_SIGNUPS_MATCH_EMAIL={{ vaultwarden_sso_signups_match_email | lower }}
|
||||||
|
SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION={{ vaultwarden_sso_allow_unknown_email_verification | lower }}
|
||||||
|
SSO_CLIENT_CACHE_EXPIRATION={{ vaultwarden_sso_client_cache_expiration }}
|
||||||
|
{% if vaultwarden_sso_signups_domains_whitelist %}
|
||||||
|
SSO_SIGNUPS_DOMAINS_WHITELIST={{ vaultwarden_sso_signups_domains_whitelist }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Security and Performance
|
||||||
|
# =================================================================
|
||||||
|
# Disable user registration via email (use admin panel or invitations)
|
||||||
|
SIGNUPS_VERIFY=false
|
||||||
|
|
||||||
|
# Log level (trace, debug, info, warn, error, off)
|
||||||
|
LOG_LEVEL=info
|
||||||
|
|
||||||
|
# Rocket configuration
|
||||||
|
ROCKET_WORKERS=10
|
||||||
Reference in New Issue
Block a user