Files
menu/ansible/vars/default.yml
T
tanshu 8c48cb2535 Make the healthcheck a command Quadlet can pass through
The first deploy put all three Sites up serving and permanently unhealthy: every
healthcheck run died with `/bin/sh: syntax error: unterminated quoted string`.
The unit file carried the closing quote, but podman's stored config did not.
Quadlet's parser strips a trailing double quote, so `node -e "fetch(...)"`
reached the container as an unterminated shell string. The sibling apps never hit
this because their HealthCmd is a bare `curl`.

The check is now `wget -q -O /dev/null http://127.0.0.1:<port>/healthz` — busybox
wget, no quoting, non-zero on anything but a 2xx — and the Dockerfile's own
HEALTHCHECK says the same thing. The vars comment, the unit template and the
deployment readme all say why it has to stay quote-free.

Found from the running container rather than the play output: `podman
healthcheck run` returned 1, `.State.Health.Log` held the sh error, and the app
log showed it listening on 127.0.0.1:3000 the whole time.
2026-10-16 11:22:48 +05:30

73 lines
3.2 KiB
YAML

---
# Defaults shared by every Site. Each Site's own file is named by the `var_file`
# in ansible/hosts, and its slug is its inventory name.
# ---------------------------------------------------------------------------
# Rootless Podman / Quadlet
# ---------------------------------------------------------------------------
# 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). A host that has already run caddy/playbook.yml from the
# ansible-playbooks repo has the rootless prerequisites.
podman_user: "{{ ansible_facts['user_id'] }}"
podman_data_dir: "{{ ansible_facts['user_dir'] }}/podman-data"
quadlet_dir: "{{ ansible_facts['user_dir'] }}/.config/containers/systemd"
# ---------------------------------------------------------------------------
# Image
# ---------------------------------------------------------------------------
registry: registry.tanshu.com
registry_username: ta-registry
registry_password: ff28a01f00c0f39315d94cd9dcb1e554968dba25676a8ea5f2be34e96a9a099f
image_name: '{{ registry }}/menu-admin'
tag: latest
# deploy.sh passes -e image_tag=<commit>; `tag` is the fallback when running the
# play by hand. Rollback = -e image_tag=<older-commit>.
image: '{{ image_name }}:{{ image_tag | default(tag) }}'
# ---------------------------------------------------------------------------
# The Site
# ---------------------------------------------------------------------------
# One image serves every Site; this picks which config inside it to run. The
# inventory name is the slug, so the container, its network and its data
# directory are all menu-<site>.
site: '{{ inventory_hostname }}'
app_name: 'menu-{{ site }}'
container_name: '{{ app_name }}'
unit_name: '{{ container_name }}.service'
network_name: '{{ app_name }}'
# The image's own account (`node`), which keep-id maps onto podman_user.
app_uid: 1000
app_gid: 1000
# Port inside the container. Caddy proxies to it over menu-<site>_net; nothing
# is published on the host.
site_port: 3000
# podman builds an OCI image by default and drops the Dockerfile's HEALTHCHECK
# instruction, so the same check is declared on the Quadlet unit and the play
# gates on `podman healthcheck run`.
#
# The command must not contain quotes. Quadlet's parser strips a trailing double
# quote from HealthCmd, so `node -e "fetch(...)"` reaches podman as an
# unterminated string and every check dies with "/bin/sh: syntax error:
# unterminated quoted string" — the container serves, and is permanently
# unhealthy. wget is busybox's, needs no quoting, and exits non-zero on anything
# but a 2xx.
health_cmd: 'wget -q -O /dev/null http://127.0.0.1:{{ site_port }}/healthz'
# ---------------------------------------------------------------------------
# Shared Caddy unit (caddy/playbook.yml in the ansible-playbooks repo)
# ---------------------------------------------------------------------------
caddy_name: caddy
caddyfile_path: '{{ podman_data_dir }}/{{ caddy_name }}/conf/Caddyfile'
# Appended to the shared Caddyfile by roles/caddy. The Site is served from the
# container name over menu-<site>_net; no host ports are involved.
snippet_block: |
{{ host }} {
reverse_proxy {{ container_name }}:{{ site_port }}
}