personal_infra/ansible/roles/mempool/README.md

70 lines
2.9 KiB
Markdown
Raw Normal View History

mempool: convert to a role, de-Uptime-Kuma the health checks 745-line playbook becomes 37 lines (the role, plus the Caddy play for the edge host) and a 408-line role with docker/deploy/healthcheck phases and six templates. mempool_vars.yml is deleted; its content is the role's defaults. Three health checks are kept, not collapsed: Mempool is three moving parts and knowing which one is down is the point. Each has its own script, unit, timer and push_url, driven by a mempool_healthchecks list. The Uptime Kuma specifics are gone - the embedded Python creating monitors over the API, the /tmp credentials file, the push-URL file read back and parsed, three Environment= rewrites - and the three live push URLs are preserved from the vault, so reporting is unchanged. `Enable and start health check timers` and `Display deployment status` were both guarded by uptime_kuma_enabled despite being deployment tasks. Third service in a row with that pattern: the deprecation banner was applied to contiguous blocks, so anything sitting near the push plumbing was disabled with it. Ungated. TWO OWNERSHIP PROBLEMS, different in kind: - MINE: I wrote `owner: root` on docker-compose.yml where the original says `owner: "{{ ansible_user }}"`. A straight violation of extract-mechanically- change-nothing, caught only by reading the check-mode diff line by line. Reverted to match the original. - PRE-EXISTING, and dangerous: the playbook declared `owner: "{{ ansible_user }}"` (1000) on the MariaDB data directory, which the container owns as uid 999. Confirmed against `git show HEAD:` before concluding it was not mine. It had drifted since the containers were created and went unnoticed because the playbook had not been run since. This was not academic. The first real run pulled a newer mariadb:10.11 and recreated mempool-db; with the chown still in place MariaDB would have come back to a data directory it could not write. The role now ensures the directory exists and leaves ownership to the container. Verified after the run: /opt/mempool/mysql is still 999:999 and all three containers are healthy. This is a deliberate behaviour change, not part of the extraction. It is in this commit rather than a follow-up because the faithful version was never safe to run, so there was no intermediate state worth recording as verified. mempool_frontend_port moved to services_config.yml: two hosts need it (this role deploys the frontend, the Caddy play proxies to it from the edge host) and a role default is invisible to the second play. caddy_site's parameter assert caught this loudly - "'mempool_frontend_port' is undefined" - rather than silently. Verified: check-mode diff clean apart from unavoidable check-mode artifacts; first run ok=24 changed=5, zero failures; second run changed=2 - the two bare `command:` tasks (pull, compose up) that have no changed_when and always report changed. That is the idempotent floor. All three health checks report ExecMainStatus 0 with their push URLs intact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 18:49:11 +02:00
# `mempool`
Deploys the [Mempool](https://mempool.space) block explorer as a three-container
Docker Compose stack — MariaDB, backend, frontend — on `mempool-box`, and keeps a
health check on each.
Converted from `deploy_mempool_playbook.yml` (745 lines) under Plan 6. The
playbook is now 37 lines: this role, plus a second play that publishes the
frontend through Caddy on the edge host.
## Phases
| | |
|---|---|
| `docker.yml` | Docker engine: repo, key, packages, service |
| `deploy.yml` | directories, `docker-compose.yml`, pull, up, wait-for-healthy |
| `healthcheck.yml` | three check scripts, three services, three timers |
## Three health checks, not one
Mempool is three moving parts and knowing *which* one is down is the point, so
each gets its own check, unit and timer, driven by the `mempool_healthchecks`
list:
| | checks |
|---|---|
| `mariadb` | `docker inspect` health status of `mempool-db` |
| `backend` | `GET /api/v1/backend-info` |
| `frontend` | `GET /` |
Each records its answer in its exit code, which systemd keeps:
`systemctl is-failed mempool-backend-healthcheck.service`. Reporting elsewhere
is one field per check, `push_url`, and is the plug-in point for whatever
monitoring exists. Empty means check, exit honestly, report nowhere. The URLs
are credentials, so callers pass them from the vault.
Nothing here is specific to a monitoring product. The embedded Python that
created monitors over the Uptime Kuma API, the `/tmp` credentials file, the
push-URL file read back and parsed, and three systemd `Environment=` rewrites
are gone.
## MariaDB owns its own data directory
`{{ mempool_mysql_dir }}` is bind-mounted into the container, which runs as uid
**999** and must create files there. The playbook this replaced declared
`owner: "{{ ansible_user }}"` (1000) on it, which had drifted from reality ever
since the containers were created — unnoticed, because the playbook had not been
run since.
That was not academic. The first real run of this role pulled a newer
`mariadb:10.11` and recreated `mempool-db`; had the chown still been in place,
MariaDB would have come back to a directory it could not write. The role now
ensures the directory exists and leaves ownership to the container.
## `mempool_frontend_port` lives in `services_config.yml`
Two hosts need it: this role deploys the frontend on `mempool-box`, and the Caddy
play proxies to it from the edge host. A role default is invisible to the second
play, so the value lives in `service_settings.mempool.frontend_port` and the role
default derives from it.
## Expect `changed=2` on a converged host
`Pull Mempool images` and `Deploy Mempool containers with docker compose` are
bare `command:` tasks with no `changed_when`, so they always report changed.
That is the idempotent floor, not drift. Everything else reports `ok`.
**`mariadb:10.11` is a moving tag**, so a run can pull a newer patch release and
recreate the database container. Pin it if that is not what you want.