Commit Graph

5 Commits

Author SHA1 Message Date
JP
82680d9430 Correct stale deploy docs and document the new env knobs
deploy/README.md described a rewrites() block that no longer exists, and told
the reader to verify the image bucket's anonymous-download policy was set -
which is precisely the exposure that was closed. Following it would have
re-opened every stored image to the public internet.

Replaced with what is actually true: /minio-images is a session-gated route
handler with per-user key-prefix ownership, the bucket must have no anonymous
policy, and MinIO must stay bound to loopback. Also noted that the suggested
`mc anonymous get` check does not work on this host - the alias has no
credentials and returns Access Denied either way - and gave an external curl
that actually tells you something.

The same stale rationale sat in deploy.sh's build comment. Building without the
env file is still right, just for a different reason: nothing needs baking in.

Added the MCP and OAuth journal greps, an unauthenticated discovery check, and
a note that a 307 there means /.well-known fell out of PUBLIC_ROUTES. Documented
in .env.example that NEXTAUTH_URL must be the exact public origin with no
trailing slash, since it is now the OAuth issuer and MCP resource identifier,
plus the MCP_CHATGPT_TOOLS opt-out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1Ee4Mc1X1SX8HgYa52zu7
2026-08-09 19:04:42 +00:00
JP
80fd99bc40 Fix deploy: sudo to root once and su down, not sudo -u
sudoers grants drinkadmin NOPASSWD only as root, so every 'sudo -u
drinktracker' in the deploy prompted for a password. Restructured to
pipe one script per phase to 'sudo -n bash -s' and use su inside, which
needs no privilege change and cuts the SSH round-trips.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 17:59:48 +00:00
JP
87f951bf94 Run natively under systemd; Docker was unworkable in this LXC
Docker in this unprivileged Proxmox LXC was broken two independent ways:
AppArmor could not load the docker-default profile, so the daemon could
not start any new container, and runc could not set the
net.ipv4.ip_unprivileged_port_start sysctl, which is why every service
needed network_mode: host. `docker build` was impossible outright since
Docker 29 removed the classic builder. The stack only survived because
the containers predated the breakage - a reboot would have left the app
down, and nothing could be redeployed.

Postgres, MinIO and the app now run natively under systemd. Deploys
build out-of-place into releases/<sha> and swap a symlink, so the build
happens while the old release keeps serving and downtime is the ~3s
restart rather than the ~3min build. Rollback is the same swap in
reverse with no rebuild.

Dockerfile and docker-compose.prod.yml are unchanged and still work on
a normal host; the compose app service gains `build: .` so it can come
up on a VPS that cannot reach the LAN-only Gitea registry.

Documents three traps found during the migration: rewrites() in
next.config.mjs is evaluated at build time so MINIO_ENDPOINT changes
silently do nothing, prisma migrate deploy would fail because
production has no _prisma_migrations table, and the image proxy relies
on the bucket's anonymous-download policy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 17:58:34 +00:00
JP
f3865c7901 Fix deploy: avoid cd into /root as the deploy user
The remote shell runs as drinkadmin, which cannot enter /root even
though sudo can operate there, so 'cd $REMOTE_DIR && sudo docker ...'
failed at the cd. Pass the build context and compose file as paths
instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 17:06:01 +00:00
JP
45d9bd12d7 Add deploy script and skill for the production LXC
There is no CI, so a git push deploys nothing - the image has to be built
and the stack restarted separately. This captures that as one command
rather than a sequence to remember.

The image is built on the LXC and tagged with the registry name the
compose file already references, so compose finds it locally and never
pulls. That means no registry credentials are needed on either machine.

Also records the two things that cost the most time to work out: the
public hostname resolves to the reverse proxy rather than the container
(192.168.2.169), and the live stack runs from /root/drinktracker while
the checkouts under /home/drinkadmin are stale.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 17:02:20 +00:00