Files
mozimo.in/ansible/roles/analytics/templates/vince.container.j2
T
tanshu d04314ab1c Deploy with rootless podman + Quadlet on emily
Retargets the build and the playbook off rootful Docker on monoco, following the
conventions already in place on emily's other services: Quadlet units in
~/.config/containers/systemd, per-service data in ~/podman-data, and a shared
Caddy that every service registers itself with — a network drop-in plus a
marked block in its Caddyfile. Nothing is published on the host; Caddy reaches
the containers by name over mozimo_net.

- Makefile: podman build + push instead of docker buildx, PLATFORMS=linux/arm64
  (both hosts are aarch64). podman has no built-in QEMU the way buildx's builder
  image does, so a foreign-platform failure now points at qemu-user-static.
- deploy.sh: pass COMMIT= to make, which the Makefile actually reads; it was
  passing TAG=, so the tag silently came from `git rev-parse` instead.
- ansible: hosts emily, become false, XDG_RUNTIME_DIR for rootless podman and
  systemctl --user. Docker modules become Quadlet templates with user-service
  handlers, and the network role now ships mozimo.network plus the Caddy drop-in
  rather than calling docker_network.
- UserNS=keep-id maps the container's uid 1000 (node) and root (vince) onto the
  host user, so PocketBase and Vince write host-owned files instead of
  subuid-owned ones; the play asserts the pinned uid still matches the host.
- ansible/README.md: the unit layout, the service-registration convention, and
  the monoco -> emily migration (PocketBase 23 MB + Vince 119 MB, DNS cutover,
  rollback).

Verified by a check-mode rehearsal against emily (13 ok / 8 changed / 0 failed)
and a disposable Quadlet unit on that host proving the uid mapping, the
EnvironmentFile and the isolated network. The real build and cutover have not
been run.
2026-10-16 10:11:39 +05:30

43 lines
1.4 KiB
Django/Jinja

# Vince (first-party analytics, Plausible protocol) — rootless Podman Quadlet.
# Managed by Ansible. Do not edit by hand.
#
# The image's ENTRYPOINT is the bare /vince binary (prints help and exits with
# no args), so the `serve` subcommand is required.
#
# Reachable only on {{ network_quadlet }}.network: Caddy proxies /stats/* on
# the apex host here (prefix stripped) and publishes the dashboard on
# {{ stats_host }}. There is no published port.
[Unit]
Description=Vince analytics
After=network-online.target
Wants=network-online.target
[Container]
ContainerName={{ vince_container }}
Image={{ vince_image }}
# Vince runs as root in the image and writes /data; mapping container root
# onto {{ podman_user }} keeps {{ vince_directory }} host-owned.
UserNS=keep-id:uid=0,gid=0
Exec=serve
Environment=VINCE_DATA=/data
Environment=VINCE_LISTEN=0.0.0.0:{{ vince_port }}
# serve (re)creates the admin account from these on every boot — the playbook
# vars are the source of truth, like the PocketBase superuser.
Environment=VINCE_ADMIN_NAME={{ vince_admin_name }}
Environment=VINCE_ADMIN_PASSWORD={{ vince_admin_password }}
# create the tracked site on startup (CSV list)
Environment=VINCE_DOMAINS={{ vince_site_domain }}
Environment=VINCE_URL=https://{{ stats_host }}
Volume={{ vince_directory }}:/data
Network={{ network_quadlet }}.network
[Service]
Restart=on-failure
[Install]
WantedBy=default.target