--- # --------------------------------------------------------------------------- # 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: Postgres listens on # 5432 and publishes nothing.) # # 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" # --------------------------------------------------------------------------- # PostgreSQL # --------------------------------------------------------------------------- # The name the rest of the repo already uses for this container in its # `postgres_container` vars, and the name every app resolves over the network. postgres_container: postgres postgres_unit: "{{ postgres_container }}.service" # The major version is the one knob, because the image tag and the PGDATA # directory have to agree. # # 18 is deliberate. monoco runs 17.5 and the data is brought across with a # logical dump — a PGDATA copy cannot cross a major version. See # migrate-from-monoco.md for the one-time move. # # `-alpine` still floats within 18.x, which is what you want for security # patches; pin a digest here if the image itself must be immutable. postgres_major: '18' # 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. postgres_image: "docker.io/library/postgres:{{ postgres_major }}-alpine" # The uid the server actually writes as — not the image's configured user. The # Alpine image creates the "postgres" account at uid/gid 70 ("70 is the standard # uid/gid for postgres in Alpine"), and the entrypoint starts as root, chowns # PGDATA to it, then drops privileges. keep-id maps that uid onto podman_user, # so PGDATA ends up owned by podman_user on the host and never by a subuid. That # is what keeps backups working without podman unshare or sudo. postgres_uid: 70 postgres_gid: 70 host_directory: "{{ podman_data_dir }}/{{ postgres_container }}" # Postgres 18 moved both the image's VOLUME and its default PGDATA: # # 17 Volume /var/lib/postgresql/data PGDATA /var/lib/postgresql/data/pgdata # 18+ Volume /var/lib/postgresql PGDATA /var/lib/postgresql//docker # # So the mount is now the parent directory and the version lives in the path. # That is what the 18 entrypoint expects: it refuses to start — "there appears # to be PostgreSQL data in ..." — if it finds a cluster in the old layout, and # the versioned subdirectory is what makes a later `pg_upgrade --link` work # without mount-boundary trouble. postgres_mount: /var/lib/postgresql # Everything under the mount that identifies this cluster, kept as one value so # the container path and the host path cannot drift apart. postgres_versioned_subdir: "{{ postgres_major }}/docker" pgdata: "{{ postgres_mount }}/{{ postgres_versioned_subdir }}" pgdata_host_dir: "{{ host_directory }}/{{ postgres_versioned_subdir }}" # Secrets do not go in the unit file: it is world-readable, and `podman inspect` # prints the environment anyway. They go in a 0600 file the unit reads with # EnvironmentFile=. postgres_env_file: "{{ host_directory }}/postgres.env" # Quadlet drop-in directory for the Postgres unit. Services attach themselves # here; see the "How services attach themselves" section of readme.md. # Postgres itself never lists its app networks. postgres_dropin_dir: "{{ quadlet_dir }}/{{ postgres_container }}.container.d" # Credentials. This is the placeholder the app playbooks already embed in their # db_url / POSTGRES_PASSWORD, kept as-is so a migrated app connects unchanged. # monoco's cluster uses the same one, so the dump restores and the apps connect # with no password reset. Replace it here and in those playbooks together when # the fleet moves to a real secret. pg_user: postgres pg_password: '123456' pg_database: postgres # The first start runs initdb, and a database wants time to shut down cleanly. postgres_timeout_start: 120 postgres_timeout_stop: 60