--- # --------------------------------------------------------------------------- # Rootless Podman / Quadlet # --------------------------------------------------------------------------- # Duplicated on purpose from caddy/vars/default.yml: a play cannot include that # file wholesale, because it also sets `host_directory` — to the Caddy data # directory — and every playbook defines that for itself. Keep these three in # sync with caddy/vars/default.yml. (Its fourth, podman_unprivileged_port_start, # belongs to the podman tasks, which this play does not run: Vaultwarden # publishes nothing host-side.) # # podman_user is derived from the connection: this play carries no become, so # the Quadlet units belong to whoever Ansible connects as. Requires gather_facts # (set in playbook.yml). podman_user: "{{ ansible_facts['user_id'] }}" podman_data_dir: "{{ ansible_facts['user_dir'] }}/podman-data" quadlet_dir: "{{ ansible_facts['user_dir'] }}/.config/containers/systemd" # --------------------------------------------------------------------------- # Vaultwarden (the Bitwarden-compatible server) # --------------------------------------------------------------------------- # The service keeps the Docker-era name everywhere — directory, container, unit, # Podman network and Postgres database are all `bitwarden`, and the Caddyfile # upstream is `bitwarden:80`. Only the image is `vaultwarden/server`. Renaming # it would touch the Caddyfile, the Postgres database and every client's saved # server URL, for no gain. host: vault.tanshu.com container_name: bitwarden unit_name: "{{ container_name }}.service" # Fully qualified on purpose: rootless Podman resolves short names against # unqualified-search-registries, and there is no TTY to answer a prompt when # the systemd unit starts. image: docker.io/vaultwarden/server:latest # The Quadlet file is .network. caddy/roles/register pins the # Podman network name to _net (so: bitwarden.network, # bitwarden_net). network_name: "{{ container_name }}" host_directory: "{{ podman_data_dir }}/{{ container_name }}" # The image's VOLUME is /data and ROCKET_PORT is 80, so this is both the bind # mount target and the port Caddy proxies to. data_dir: "{{ host_directory }}/data" container_port: 80 # DATABASE_URL carries the Postgres password, and the Quadlet unit is # world-readable in ~/.config, so it goes in this 0600 file instead and is read # by systemd through EnvironmentFile=. env_file: "{{ host_directory }}/bitwarden.env" # The shared Postgres unit this app attaches itself to (postgres/playbook.yml). # roles/postgres owns this app's drop-ins there and the "Restart Postgres" # handler that applies them. postgres_container: postgres postgres_unit: "{{ postgres_container }}.service" # The credentials the Docker-era playbook embedded in its db_url, kept as-is so # the already-restored `bitwarden` database and the app's own connection string # agree. Postgres is authoritative for this service; the SQLite file the image # would use by default is stale and deliberately not migrated (see readme.md). pg_user: postgres pg_password: '123456' pg_database: bitwarden # Hostname, not an IP, and the same `postgres` name the old db_url used: # postgres/roles/attach joins the postgres container to bitwarden_net, which is # what makes this resolve. (`db`, the shared NetworkAlias, resolves too.) database_url: "postgresql://{{ pg_user }}:{{ pg_password }}@{{ postgres_container }}:5432/{{ pg_database }}" # Vaultwarden validates that DOMAIN carries a scheme and serves its web vault # and API links from it. The old container set exactly this. domain: "https://{{ host }}" # The shared Caddy unit and its Caddyfile, both owned by caddy/playbook.yml. caddy_name: caddy caddyfile_path: "{{ podman_data_dir }}/{{ caddy_name }}/conf/Caddyfile" # No request-body limit: Caddy streams request bodies and imposes none by # default, so the 525M `client_max_body_size` the dead nginx front end carried # has no equivalent — and needs none. snippet_block: | {{ host }} { reverse_proxy {{ container_name }}:{{ container_port }} }