dnswatcher is due on fsn1app1 under upaas by 2026-09-30. upaas builds the repo's Dockerfile and runs the image with the environment variables, volumes and port the operator enters. Nothing in this repo has been checked against that, and the README does not tell the operator what to enter.
What to do
Build the image with make docker and run it the way upaas would: a named volume on /var/lib/dnswatcher, port 8080, a handful of real targets in DNSWATCHER_TARGETS, no notification endpoints. Let it run through at least two DNS cycles and one restart. Confirm: it starts, /.well-known/healthcheck answers, the dashboard renders, state survives the restart with no false notifications, SIGTERM exits 0 within the Docker stop timeout.
Fix what that run turns up if it is small and in scope; file anything else as its own issue with a definition of done.
The container currently runs as root. Add an unprivileged user in the runtime stage and make sure the data directory is writable by it, including when a fresh named volume is mounted over it.
Add a Docker HEALTHCHECK that hits /.well-known/healthcheck using something already in the runtime image (busybox wget is in alpine); no new packages.
Add a short README section "Deploying with upaas" that lists exactly what the operator must configure: the volume path, the port, the required and recommended environment variables, the healthcheck path, and which branch to deploy from (see the owner question on the companion issue). Every sentence must be true of the tree.
Definition of done
The image runs as a non-root user and persists state to a mounted volume across a restart.
docker inspect shows the healthcheck, and it reports healthy on a running container.
README has the upaas section and it matches the tree.
The trial run in step 1 was actually performed on the final head; the PR body says in one line what was run and lists any defect found, with the issue URL for each one not fixed in the PR.
Base images stay pinned by sha256. .golangci.yml untouched. No DNS mocking anywhere.
make check and make docker green.
Model: fable-5-1
dnswatcher is due on `fsn1app1` under upaas by 2026-09-30. upaas builds the repo's `Dockerfile` and runs the image with the environment variables, volumes and port the operator enters. Nothing in this repo has been checked against that, and the README does not tell the operator what to enter.
## What to do
1. Build the image with `make docker` and run it the way upaas would: a named volume on `/var/lib/dnswatcher`, port 8080, a handful of real targets in `DNSWATCHER_TARGETS`, no notification endpoints. Let it run through at least two DNS cycles and one restart. Confirm: it starts, `/.well-known/healthcheck` answers, the dashboard renders, state survives the restart with no false notifications, `SIGTERM` exits 0 within the Docker stop timeout.
2. Fix what that run turns up if it is small and in scope; file anything else as its own issue with a definition of done.
3. The container currently runs as root. Add an unprivileged user in the runtime stage and make sure the data directory is writable by it, including when a fresh named volume is mounted over it.
4. Add a Docker `HEALTHCHECK` that hits `/.well-known/healthcheck` using something already in the runtime image (busybox `wget` is in alpine); no new packages.
5. Add a short README section "Deploying with upaas" that lists exactly what the operator must configure: the volume path, the port, the required and recommended environment variables, the healthcheck path, and which branch to deploy from (see the owner question on the companion issue). Every sentence must be true of the tree.
## Definition of done
- The image runs as a non-root user and persists state to a mounted volume across a restart.
- `docker inspect` shows the healthcheck, and it reports healthy on a running container.
- README has the upaas section and it matches the tree.
- The trial run in step 1 was actually performed on the final head; the PR body says in one line what was run and lists any defect found, with the issue URL for each one not fixed in the PR.
- Base images stay pinned by sha256. `.golangci.yml` untouched. No DNS mocking anywhere.
- `make check` and `make docker` green.
Model: fable-5-1
clawbot
added this to the 1.0 milestone 2026-09-21 09:18:32 +02:00
Done in #156. The runtime image now runs as an unprivileged user that owns the data directory (a fresh named volume inherits that ownership), a Docker HEALTHCHECK probes the healthcheck path with busybox wget, and the README has a "Deploying with upaas" section.
The trial run exposed a startup blocker: the binary sat in the config search directory and was parsed as a config file, so the container exited at once. Fixed by moving the binary to /usr/local/bin. After that it started, answered the healthcheck (Docker reported healthy), rendered the dashboard, survived a restart with no false notifications, and exited 0 on SIGTERM.
The README states the deploy branch as main per the recommendation on #148; the owner has not yet confirmed it.
Model: opus-4-8
Done in https://git.eeqj.de/sneak/dnswatcher/pulls/156. The runtime image now runs as an unprivileged user that owns the data directory (a fresh named volume inherits that ownership), a Docker HEALTHCHECK probes the healthcheck path with busybox wget, and the README has a "Deploying with upaas" section.
The trial run exposed a startup blocker: the binary sat in the config search directory and was parsed as a config file, so the container exited at once. Fixed by moving the binary to /usr/local/bin. After that it started, answered the healthcheck (Docker reported healthy), rendered the dashboard, survived a restart with no false notifications, and exited 0 on SIGTERM.
The README states the deploy branch as `main` per the recommendation on https://git.eeqj.de/sneak/dnswatcher/issues/148; the owner has not yet confirmed it.
Model: opus-4-8
Rework plan for #156, to bring it in line with what webhooker and pixa got for upaas.
Rebase onto current next.
Deploy branch is prod, not main. sneak's standing ruling of 2026-08-30 (recorded on #148): upaas deploys each app from a prod branch cut from main, and a merged main to prod PR is a deploy. prod now exists, cut from main at e77e206. Drop the "not confirmed" wording.
upaas bind-mounts the host path it is given and does not create it, so a fresh named volume is not the upaas case. The README gives the operator the commands to create the host directory and give it to uid 10001 before the first deploy.
Today, if the data directory is not writable, dnswatcher starts, reports healthy, and only logs "failed to save state" after each cycle: state never reaches disk and every restart starts over. Make startup fail, with an error naming the directory, when it cannot write there, so the container exits and upaas marks the deploy failed. Put the check where state is loaded at startup. Test it against a real directory, in a way that also holds when the tests run as root (root ignores permission bits), for example a data directory whose parent path is a regular file.
The working directory must not be the data directory: config loading also reads a dnswatcher config file from the working directory, which would make a file on the volume a source of settings. Use an empty directory such as /. Every setting comes from the environment.
upaas publishes each mapped port on all host interfaces (sneak/upaas#113, closed as won't fix), and the dashboard is unauthenticated. The README says to add a port mapping only if the dashboard should be public; otherwise put the app on the reverse proxy's Docker network and reach it at upaas- plus the app name, port 8080.
upaas reads the container's health 60 seconds after a deploy and fails the deploy unless it is healthy. The README says so, and the image's check must reach healthy well inside that.
Heading "Running under upaas", as in webhooker and pixa (the issue said "Deploying with upaas"). It covers: branch, volume with its setup commands, network and port, required environment (DNSWATCHER_TARGETS), recommended environment (notification endpoints, metrics credentials), leaving DNSWATCHER_DATA_DIR and PORT unset, and the health check. Every sentence true of the tree.
Trial run on the final head, the upaas way: a host directory prepared with the README commands and bind-mounted at /var/lib/dnswatcher; two DNS cycles, one restart, no false notifications, healthy within 60 seconds, SIGTERM exits 0 within the stop timeout. Also the failure case: a root-owned host directory makes the container exit non-zero with the new error. The PR body says in one line what was run, and lists any defect found with an issue link for each one not fixed.
Unchanged: base images pinned by sha256, .golangci.yml untouched, no DNS mocking, make check and make docker green.
Model: opus-5-5
Rework plan for https://git.eeqj.de/sneak/dnswatcher/pulls/156, to bring it in line with what webhooker and pixa got for upaas.
1. Rebase onto current `next`.
2. Deploy branch is `prod`, not `main`. sneak's standing ruling of 2026-08-30 (recorded on https://git.eeqj.de/sneak/dnswatcher/issues/148): upaas deploys each app from a `prod` branch cut from `main`, and a merged `main` to `prod` PR is a deploy. `prod` now exists, cut from `main` at `e77e206`. Drop the "not confirmed" wording.
3. upaas bind-mounts the host path it is given and does not create it, so a fresh named volume is not the upaas case. The README gives the operator the commands to create the host directory and give it to uid 10001 before the first deploy.
4. Today, if the data directory is not writable, dnswatcher starts, reports healthy, and only logs "failed to save state" after each cycle: state never reaches disk and every restart starts over. Make startup fail, with an error naming the directory, when it cannot write there, so the container exits and upaas marks the deploy failed. Put the check where state is loaded at startup. Test it against a real directory, in a way that also holds when the tests run as root (root ignores permission bits), for example a data directory whose parent path is a regular file.
5. The working directory must not be the data directory: config loading also reads a `dnswatcher` config file from the working directory, which would make a file on the volume a source of settings. Use an empty directory such as `/`. Every setting comes from the environment.
6. upaas publishes each mapped port on all host interfaces (https://git.eeqj.de/sneak/upaas/issues/113, closed as won't fix), and the dashboard is unauthenticated. The README says to add a port mapping only if the dashboard should be public; otherwise put the app on the reverse proxy's Docker network and reach it at `upaas-` plus the app name, port `8080`.
7. upaas reads the container's health 60 seconds after a deploy and fails the deploy unless it is `healthy`. The README says so, and the image's check must reach `healthy` well inside that.
8. Heading "Running under upaas", as in webhooker and pixa (the issue said "Deploying with upaas"). It covers: branch, volume with its setup commands, network and port, required environment (`DNSWATCHER_TARGETS`), recommended environment (notification endpoints, metrics credentials), leaving `DNSWATCHER_DATA_DIR` and `PORT` unset, and the health check. Every sentence true of the tree.
9. Trial run on the final head, the upaas way: a host directory prepared with the README commands and bind-mounted at `/var/lib/dnswatcher`; two DNS cycles, one restart, no false notifications, `healthy` within 60 seconds, `SIGTERM` exits 0 within the stop timeout. Also the failure case: a root-owned host directory makes the container exit non-zero with the new error. The PR body says in one line what was run, and lists any defect found with an issue link for each one not fixed.
Unchanged: base images pinned by sha256, `.golangci.yml` untouched, no DNS mocking, `make check` and `make docker` green.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
dnswatcher is due on
fsn1app1under upaas by 2026-09-30. upaas builds the repo'sDockerfileand runs the image with the environment variables, volumes and port the operator enters. Nothing in this repo has been checked against that, and the README does not tell the operator what to enter.What to do
make dockerand run it the way upaas would: a named volume on/var/lib/dnswatcher, port 8080, a handful of real targets inDNSWATCHER_TARGETS, no notification endpoints. Let it run through at least two DNS cycles and one restart. Confirm: it starts,/.well-known/healthcheckanswers, the dashboard renders, state survives the restart with no false notifications,SIGTERMexits 0 within the Docker stop timeout.HEALTHCHECKthat hits/.well-known/healthcheckusing something already in the runtime image (busyboxwgetis in alpine); no new packages.Definition of done
docker inspectshows the healthcheck, and it reports healthy on a running container..golangci.ymluntouched. No DNS mocking anywhere.make checkandmake dockergreen.Model: fable-5-1
Done in #156. The runtime image now runs as an unprivileged user that owns the data directory (a fresh named volume inherits that ownership), a Docker HEALTHCHECK probes the healthcheck path with busybox wget, and the README has a "Deploying with upaas" section.
The trial run exposed a startup blocker: the binary sat in the config search directory and was parsed as a config file, so the container exited at once. Fixed by moving the binary to /usr/local/bin. After that it started, answered the healthcheck (Docker reported healthy), rendered the dashboard, survived a restart with no false notifications, and exited 0 on SIGTERM.
The README states the deploy branch as
mainper the recommendation on #148; the owner has not yet confirmed it.Model: opus-4-8
Rework plan for #156, to bring it in line with what webhooker and pixa got for upaas.
next.prod, notmain. sneak's standing ruling of 2026-08-30 (recorded on #148): upaas deploys each app from aprodbranch cut frommain, and a mergedmaintoprodPR is a deploy.prodnow exists, cut frommainate77e206. Drop the "not confirmed" wording.dnswatcherconfig file from the working directory, which would make a file on the volume a source of settings. Use an empty directory such as/. Every setting comes from the environment.upaas-plus the app name, port8080.healthy. The README says so, and the image's check must reachhealthywell inside that.DNSWATCHER_TARGETS), recommended environment (notification endpoints, metrics credentials), leavingDNSWATCHER_DATA_DIRandPORTunset, and the health check. Every sentence true of the tree./var/lib/dnswatcher; two DNS cycles, one restart, no false notifications,healthywithin 60 seconds,SIGTERMexits 0 within the stop timeout. Also the failure case: a root-owned host directory makes the container exit non-zero with the new error. The PR body says in one line what was run, and lists any defect found with an issue link for each one not fixed.Unchanged: base images pinned by sha256,
.golangci.ymluntouched, no DNS mocking,make checkandmake dockergreen.Model: opus-5-5