[serve] interval_secs = 300 prune_days = 30 listen = "0.0.0.0:9100" peer_heartbeat_secs = 60 route_check_interval_secs = 300 dashboard = false # api_token loaded from POM_API_TOKEN env var # The database is at a fixed absolute path, not wherever XDG_DATA_HOME happens # to point. The unit sets XDG_DATA_HOME=/var/lib and an interactive shell does # not, so before this was configured `pom serve` and a hand-run `pom test` on # this host opened two different files and neither said so: the suites ran, # passed, and reported into a database nothing served. [storage] db_path = "/var/lib/pom/pom.db" [instance] name = "hetzner" [targets.mnw] label = "Makenotwork Production" expected_routes = ["/", "/discover", "/login", "/docs"] [[targets.mnw.dns]] name = "makenot.work" record_type = "A" expected = [] [[targets.mnw.dns]] name = "forums.makenot.work" record_type = "A" expected = [] [[targets.mnw.dns]] name = "git.makenot.work" record_type = "A" expected = [] [[targets.mnw.cors]] url = "https://fsn1.your-objectstorage.com/makenotwork-files/cors-probe" origin = "https://makenot.work" method = "PUT" [targets.mnw.whois] domain = "makenot.work" warn_days = 30 [targets.mnw.health] url = "https://makenot.work/api/health" timeout_secs = 10 [targets.mnw.health.expect] status_code = 200 json_fields = { "status" = "operational", "checks.database" = "true" } [targets.mnw.health.trending] baseline_window_hours = 168 spike_threshold = 2.0 [targets.mnw.tls] host = "makenot.work" [targets.mnw.tests] # Present in prod's live /etc/pom/pom.toml and previously missing here, which # made this file unsafe to deploy: installing it would have silently dropped the # remote CI check from prod. Keep the two in step. ssh = "max@100.106.221.39" command = "/home/max/staging/run-ci.sh" timeout_secs = 600 staleness_days = 7 [targets.mnw.backups] # Where the backups actually are, verified on prod 2026-07-29: the nightly job # writes /var/lib/mnw/backups/makenotwork/makenotwork-.sql.gz. This said # /opt/makenotwork/backups, a path that does not exist on that host, so the # check reported the target degraded for a directory it could not find while the # real backups went unwatched. The app lives at /opt/mnw/current, not # /opt/makenotwork; the old path looks like a pre-rename leftover. # # pom matches files by the "-" or "_" prefix inside this # directory, so the directory is the per-database one, not its parent. directory = "/var/lib/mnw/backups/makenotwork" databases = ["makenotwork"] max_age_hours = 25 interval_secs = 3600 [targets.mnw.scan_pipeline] # Polls /admin/uploads/health.json for queue depth, stuck-scan count, # held backlog, and per-layer error rates. Thresholds per # scan-pipeline-audit.md ยง 6. Localhost on the makenotwork port to # skip the Caddy + Cloudflare path (internal-only signal). base_url = "http://127.0.0.1:3000" interval_secs = 300 timeout_secs = 10 [targets.mnw.synckit_fleet] # Which SyncKit SDK versions are actually syncing. SyncKit is client-side # only, so there is no deployed version to poll; the server aggregates the # version off each sync request's User-Agent and this reads that. Authed # with alerts.alerts_ingest_token, so the check does not spawn without one. # Informational: an old version in the field never degrades the target, only # a readout PoM cannot take does. Localhost for the same reason as above. base_url = "http://127.0.0.1:3000" window_days = 30 interval_secs = 3600 timeout_secs = 10 [targets.mnw-cli] label = "MNW CLI SSH Server" [[targets.mnw-cli.dns]] name = "cli.makenot.work" record_type = "A" expected = [] [targets.mnw-cli.ssh_banner] host = "127.0.0.1" port = 22 timeout_secs = 5 [targets.mt] label = "Multithreaded Forum" expected_routes = ["/"] [targets.mt.health] url = "http://127.0.0.1:3400/api/health" timeout_secs = 5 [targets.mt.health.expect] status_code = 200 # `tls_trust_anchors` is whether the host CA bundle gave mt any outbound TLS # anchors. mt ships none of its own, so a thin or stale bundle takes out the # OAuth token exchange that logs users in, while the box still boots, serves # pages, and answers 200 here. mt deliberately does not degrade `status` for it # (a bad bundle is a whole-fleet condition, and failing the load-balancer check # would turn a login outage into a total one), so this assertion is the only # thing that makes the condition visible before a user finds it. json_fields = { "status" = "operational", "database" = "true", "tls_trust_anchors" = "true" } [targets.mt.tls] host = "forums.makenot.work" [targets.mt.tests] ssh = "max@100.106.221.39" command = "cd /home/max/staging/multithreaded && cargo test --workspace 2>&1" timeout_secs = 300 staleness_days = 7 [targets.htpy] label = "htpy.app" [[targets.htpy.dns]] name = "htpy.app" record_type = "A" expected = [] [targets.htpy.whois] domain = "htpy.app" warn_days = 30 [targets.htpy.health] # htpy-web moved twice and this URL followed neither move: it listens on 3200, # not 8080, and /archive/ now 308s to /viewer/. Checking the old # address failed on connect, so the target has been reading "unreachable" with an # open incident since 2026-03-29 while htpy.app itself served fine. Verified # 2026-07-29: this returns 200 with "htpy" in the body from fw13, astra and # hetzner, and 3200 is in the tailnet ACL's inter-server port list. url = "http://100.99.153.68:3200/viewer/S_2" timeout_secs = 10 [targets.htpy.health.expect] status_code = 200 body_contains = "htpy" [targets.htpy.tls] host = "htpy.app" [peers.astra] address = "100.106.221.39:9100" on_missing = "alert" # token = "" [peers.macbook] address = "100.100.246.136:9100" on_missing = "log" # token = "" [alerts] # postmark_token loaded from POM_POSTMARK_TOKEN env var to = "pom-alerts@makenot.work" # MNW operator-log sink: also pushes alerts to POST {mnw_url}/api/internal/alerts. # The token loads from POM_ALERTS_INGEST_TOKEN and must match ALERTS_INGEST_TOKEN # in /etc/mnw/makenotwork.env; both mnw_url and the token must be present, else # the sink stays disabled. # # Not the public URL. Caddy answers 404 to /api/internal/* by design (see the # @internal matcher in the Caddyfile), so the sink has to address the app port # directly. Measured 2026-08-15: POST https://makenot.work/api/internal/alerts # is 404, POST http://127.0.0.1:3000/api/internal/alerts is 401 without a token. mnw_url = "http://127.0.0.1:3000" # WAM ticket sink: failure alerts become tickets instead of email. WAM listens on # this host, and its token loads from POM_WAM_TOKEN, which must match the WAM # node's token. Leave wam_url unset until the deployed WAM actually requires # auth: the binary at /opt/wam/wam is an April build that predates the # require_auth middleware, so it accepts unauthenticated writes. # wam_url = "http://127.0.0.1:7890"