Replaces the docker_container role on monoco with a Quadlet systemd user unit on emily, and moves state from /var/lib/bitwarden to ~/podman-data/bitwarden. Postgres is authoritative for the vault and already moved with the cluster restore, so only the file data comes across -- and the stale db.sqlite3 that has sat beside it for years is deliberately excluded from that copy. The role warns if it finds the file in the data directory rather than failing, because with DATABASE_URL set it is inert but looks exactly like a restore source. The image runs as container-root and writes /data as root, so UserNS=keep-id:uid=0,gid=0 maps that onto the connecting user and leaves nothing owned by a subuid. Both integrations go through the shared includes rather than local copies -- caddy/roles/register for the network and the Caddy drop-in, postgres/roles/attach for the database -- so this app writes the same drop-in bytes as every other service and a new service never means editing Caddy or Postgres. That is also what lets the Docker-era roles/network go: it existed to attach an already-created container to a network (docker_network's connected:/appends:), which podman_network has no equivalent for. The dead files/nginx.conf.j2 goes with it -- Caddy handles the WebSocket upgrade and imposes no request-body limit, so its 525M client_max_body_size needs no replacement. Three ordering details are load-bearing: - The register include runs in pre_tasks, before the unit is started. Quadlet fails unit *generation*, not merely startup, when a referenced .network file does not exist yet, so starting first reports "unit not found". - roles/postgres flushes handlers immediately after attaching. The restart that joins Postgres to this network is a handler, so by default it runs at the end of the play, after the app has already started and failed to resolve the database. - The play waits on the image's own health check (podman healthcheck run) rather than on systemctl is-active. Vaultwarden runs its Diesel migrations before Rocket answers, and Restart=always means even a crash-looping container is reported active. DATABASE_URL and DOMAIN move into a 0600 environment file read through EnvironmentFile=, since the Quadlet unit is world-readable and DATABASE_URL carries the password. The credentials are unchanged, so the restored database connects with no reset. readme.md carries the monoco -> emily file copy command by command.
32 lines
1.3 KiB
YAML
32 lines
1.3 KiB
YAML
---
|
|
# Caddy is its own playbook (caddy/playbook.yml) and a rootless Quadlet unit
|
|
# there. These handlers run as the connection user, so `systemctl --user` and
|
|
# `podman exec` work without any XDG_RUNTIME_DIR juggling.
|
|
|
|
# Notified by this role when the Caddyfile changes. A reload keeps existing
|
|
# connections; a restart would briefly drop every hosted site.
|
|
#
|
|
# Note the config path: /etc/caddy/Caddyfile is the mount inside the container,
|
|
# not {{ caddyfile_path }}, which is the host side of it.
|
|
- name: Reload Caddy configuration
|
|
ansible.builtin.command: >-
|
|
podman exec {{ caddy_name }} caddy reload --config /etc/caddy/Caddyfile
|
|
changed_when: true
|
|
listen: "Reload Caddy"
|
|
|
|
# Notified by caddy/roles/register when this service's network unit, or the
|
|
# drop-in that attaches Caddy to it, is written. Quadlet has no live equivalent
|
|
# of `docker network connect`, so the container has to be recreated — a brief
|
|
# restart of every hosted site, not just this one. See caddy/readme.md,
|
|
# "Trade-off worth knowing".
|
|
#
|
|
# Defined after the reload above so that when both are notified the cheap
|
|
# config reload happens first.
|
|
- name: Restart Caddy
|
|
ansible.builtin.systemd_service:
|
|
name: "{{ caddy_name }}.service"
|
|
scope: user
|
|
state: restarted
|
|
daemon_reload: true
|
|
listen: Restart Caddy
|