act_runner already mounts /var/run/docker.sock into every job container, so
declaring it again in the workflow made the daemon refuse to create the
container at all: "Duplicate mount point: /var/run/docker.sock". The deploy
directory still has to be declared, and still at its own host path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Until now a server change reached the NAS only when someone ran ./release.sh --web
from a machine on the church network. That made the deploy depend on which laptop
was awake and where it was, which is the same fragility that let the nightly Drive
backup go stale unnoticed.
An act_runner now runs in Docker on the NAS itself and picks up this workflow, so
a push to main rebuilds the container regardless of where the push came from.
The workflow keeps the protections the old remote deploy script had, because they
are the ones that matter: server/data and server/.env are excluded from the copy
and then explicitly checked for afterwards, and the container is recreated with
'up -d --build' rather than 'down' first, so an interrupted deploy leaves the old
container serving instead of tearing the stack down. rsync runs without --delete,
matching the tarball deploy it replaces — a stale file is survivable, a wiped
data/ is not.
This covers the web app only. The iOS and Android apps bundle a copy of the UI at
build time, so they still need ./release.sh and a store release; server-side
changes reach them immediately, since they call this same server live.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The setup notes described moving the project as a tarball and never mentioned
git, because until now there was no repo. They now lead with the clone URL and
what a push needs — the credential helper, a token, and the hostname rather
than 10.3.8.90, since the stored credential is keyed to the hostname and a
remote written against the bare IP prompts every time.
server/.gitignore only excluded data/*.json, which was enough for the checklist
file and nothing else. Running the server locally creates data/uploads, data/docs
and data/backups beside it, so an attached PDF or a backup would have been
committed on the next add. The whole directory is ignored now. That data lives
on the NAS; a stale copy of it restored over production is the accident worth
designing out.
Also records that the NAS password is a keychain item rather than a file, so a
future machine knows to store it instead of hunting for the line that used to
be in build-deploy.sh.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The project has lived only as a folder on the Mac Studio and, briefly, as a
transfer tarball. This is the first commit: the Express server and its web
front end, the Capacitor iOS and Android wrappers, and the release and backup
scripts.
The repo is the source, not a backup of the machine. Left out on purpose, by
the .gitignore files that were already in the tree: node_modules, build output,
mobile/www (regenerated from server/public on every build), and server/data,
which holds the live checklists and belongs on the NAS rather than in git.
Every credential is excluded too — server/.env, the Play upload keystore and
its properties file, the App Store Connect key and ios-signing.config. The one
secret that was not in an ignored file was the NAS SSH password, hard-coded in
build-deploy.sh and grepped back out of it by backup-to-drive.sh. Both now read
it from the login keychain (service checklist-nas, account Christian), falling
back to NAS_PASS in the environment, so rotating it is one keychain entry
rather than a history rewrite.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>