podman builds an OCI image by default and drops the Dockerfile's HEALTHCHECK
instruction, so the first deploy failed at "Wait for the container healthcheck
to pass" with "container ... has no defined healthcheck" even though the app was
up and healthy.
- Declare the same check on the greatbear.container unit (HealthCmd plus
interval, timeout, retries, start period), the convention hops and menu-admin
already use.
- Flush handlers right after starting, before the gate: the unit template's
restart handler otherwise runs at the end of the play, so a run that changes
only the unit would test the stale container.
Mirrors hops 7366596, so the two deployments keep the same shape.
deploy.sh no longer needs a manual push before it, and no made-up tag:
- It pushes the current branch, refuses a dirty tracked tree, and requires
HEAD == origin/main before anything is built, so the image can only be
built for a commit the remote actually has. --force and --no-push skip the
guards.
- The image is tagged :<commit> as well as :latest, and ansible takes
-e image_tag=<commit>, so a deploy pins the exact revision; rollback is the
same play with an older commit.
- Makefile builds `git archive HEAD` instead of cloning the remote (the push
guard makes the local commit the remote state) and defaults PLATFORM to
linux/arm64, because emily is aarch64 — the same default mozimo uses. Drop
build-check-local; build-check already builds the committed tree.
- Makefile: podman build + push instead of docker buildx. build-production
clones the git remote and builds from it; build-check / build-check-local
build without pushing. Single-architecture (PLATFORM-overridable) rather
than a multi-arch manifest.
- deploy.sh: connect as the unprivileged container user; no become.
- ansible: target emily, rootless Podman Quadlet behind the fleet's shared
Caddy unit (caddy/playbook.yml in ansible-playbooks).
- register role writes greatbear.network (NetworkName=greatbear_net) and
the caddy.container.d drop-in that puts Caddy on it.
- greatbear role: podman login/pull, ~/podman-data/greatbear + .env,
greatbear.container (UserNS=keep-id:uid=0,gid=0, EnvironmentFile,
Network, Volume, no published ports), systemctl --user start and a
podman healthcheck gate, with a diagnostics rescue block.
- caddy role appends the site blocks to the shared Caddyfile and reloads;
handlers reload vs. recreate Caddy (a new network drop-in re-creates it).
- drop the network role, the community.docker requirements and the
ansible/files/ templates.
- .containerignore replaces .dockerignore (Buildah reads it natively).
- README: Podman build, rootless Quadlet deploy. No data migration step —
there is no PocketBase state to carry over.
- playbook.yml (hosts: monoco) + vars/default.yml, requirements.yml
- roles: network (shared docker network), greatbear (registry pull,
bind mount /var/lib/greatbear/pb_data, .env upload, health wait),
caddy (blockinfile snippet into the shared Caddyfile + docker exec reload)
- image honors PB_DATA_DIR and runs as root to match the bind-mount pattern
- frontend on www.greatbear.in (+apex) with /api/* and /_* proxied to
PocketBase; admin.greatbear.in redirects to the admin UI
- TanStack Start (React 19, Tailwind 4) frontend recreated from Stitch design
- PocketBase backend with schema migration + idempotent content seed
- Single Docker image running both services (non-root, healthchecked)
- deploy.sh to build & push to registry.tanshu.com
- Ansible playbook (roles: app, caddy) deploying to www.greatbear.in
with Caddy TLS entries for the site and the PocketBase admin