Add Vaultwarden self-hosted password vault at vault.ladkau.de

- New vaultwarden role — Vaultwarden container with SQLite storage, admin
  panel protected by token, Keycloak SSO enabled on second deploy after
  the OIDC client secret is available (SSO_ENABLED conditionally set so
  first provisioning deploy works without Keycloak being configured yet)
- Traefik routes vault.ladkau.de with lax rate limiting (SPA loads many assets)
- vault.ladkau.de added to DNS table, check-services.sh, status dashboard,
  and check-vault.sh (admin token required; SSO secret is post-provisioning)
- Configuration runbook: step 2.6 for Keycloak client, section 6 for
  Vaultwarden setup including admin panel, SSO login, and client configuration
This commit is contained in:
ml
2026-06-28 15:39:42 +02:00
parent 187c6bdea4
commit 1c36b7bbcb
10 changed files with 137 additions and 6 deletions
+8
View File
@@ -8,6 +8,7 @@ domain_sso: "sso.{{ domain_base }}"
domain_mail: "mail.{{ domain_base }}"
domain_registry: "cr.{{ domain_base }}"
domain_k8s: "k8s.{{ domain_base }}"
domain_vault: "vault.{{ domain_base }}"
# Let's Encrypt
acme_email: matthias.ladkau@gmail.com
@@ -97,5 +98,12 @@ registry_data_dir: /opt/registry
# k8s (placeholder)
k8s_data_dir: /opt/k8s
# Vaultwarden (self-hosted Bitwarden-compatible password vault)
vaultwarden_version: "latest"
vaultwarden_data_dir: /opt/vaultwarden
# Secrets — store values in ansible/group_vars/all/vault.yml (Ansible Vault)
# vaultwarden_admin_token: "" # generate: openssl rand -hex 32
# vaultwarden_sso_client_secret: "" # added after Keycloak is configured — see runbook-configuration.md step 2.6
# Status dashboard (public — cloud.ladkau.de root)
dashboard_data_dir: /opt/dashboard
+2 -1
View File
@@ -22,7 +22,8 @@ SERVICES = [
("Keycloak", "https://{{ domain_sso }}/realms/master", 200, "https://{{ domain_sso }}"),
("Roundcube", "https://{{ domain_mail }}", 200, "https://{{ domain_mail }}"),
("Registry", "https://{{ domain_registry }}/v2/", 401, "https://{{ domain_registry }}"),
("k8s", "https://{{ domain_k8s }}", 200, "https://{{ domain_k8s }}"),
("k8s", "https://{{ domain_k8s }}", 200, "https://{{ domain_k8s }}"),
("Vaultwarden", "https://{{ domain_vault }}", 200, "https://{{ domain_vault }}"),
]
{% raw %}
@@ -0,0 +1,7 @@
---
- name: Restart vaultwarden
community.docker.docker_compose_v2:
project_src: "{{ vaultwarden_data_dir }}"
state: present
pull: missing
recreate: always
+29
View File
@@ -0,0 +1,29 @@
---
- name: Create Vaultwarden data directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: root
group: root
mode: "0755"
loop:
- "{{ vaultwarden_data_dir }}"
- "{{ vaultwarden_data_dir }}/data"
tags: vaultwarden
- name: Deploy Docker Compose file
ansible.builtin.template:
src: docker-compose.yml.j2
dest: "{{ vaultwarden_data_dir }}/docker-compose.yml"
owner: root
group: root
mode: "0644"
notify: Restart vaultwarden
tags: vaultwarden
- name: Start Vaultwarden
community.docker.docker_compose_v2:
project_src: "{{ vaultwarden_data_dir }}"
state: present
pull: missing
tags: vaultwarden
@@ -0,0 +1,37 @@
# Managed by Ansible — do not edit manually
services:
vaultwarden:
image: vaultwarden/server:{{ vaultwarden_version }}
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://{{ domain_vault }}"
# Admin panel at /admin/ — use a long random token
ADMIN_TOKEN: "{{ vaultwarden_admin_token }}"
# Disable public sign-up — accounts created via SSO or admin panel
SIGNUPS_ALLOWED: "false"
{% if vaultwarden_sso_client_secret | default('') %}
# SSO via Keycloak — enabled after Keycloak client is configured (step 2.6)
SSO_ENABLED: "true"
SSO_CLIENT_ID: "vaultwarden"
SSO_CLIENT_SECRET: "{{ vaultwarden_sso_client_secret }}"
SSO_AUTHORITY: "https://{{ domain_sso }}/realms/ladkau"
{% else %}
SSO_ENABLED: "false"
{% endif %}
volumes:
- {{ vaultwarden_data_dir }}/data:/data
networks:
- traefik_public
labels:
- "traefik.enable=true"
- "traefik.http.routers.vaultwarden.rule=Host(`{{ domain_vault }}`)"
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
- "traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
# Lax rate limit — Vaultwarden SPA loads many assets on first visit
- "traefik.http.routers.vaultwarden.middlewares=rate-limit-lax@docker"
networks:
traefik_public:
external: true
+1
View File
@@ -12,4 +12,5 @@
- mail
- registry
- k8s
- vaultwarden
- dashboard