feat(rsvp): deploy rsvp.debyl.io, the invite-only party RSVP app

A single Go binary with SQLite, built and loaded as localhost/rsvpd:<VERSION>
by make deploy-remote in ~/src/rsvp-debylio. Both of its listeners are
published on 127.0.0.1 only: Caddy proxies the public one to everyone and the
admin one (/admin, no login) only to caddy_local_networks. A Caddyfile mistake
alone cannot expose admin, and neither can a port mistake alone.

Guests' invite links are the credential and they sit in the URL path, which
shapes the vhost:

- It does not import common_headers. That snippet sets Referrer-Policy
  same-origin, which would replace the app's no-referrer and let a token leak
  in a Referer header.
- Its access log rewrites request>uri to /i/REDACTED and drops the Location
  response header, since every POST 303s back to /i/<token>.
- Caddy's error logger is separate from the site's and wrote the raw URI to
  caddy.log when the upstream was down. The global log now excludes
  http.log.error.rsvp and a filtered rsvp-errors logger takes it instead.
  Verified with zero token occurrences in both logs, locally and live.

The data directory is owned directly by the host uid of the container's uid
10001 (subuid + 10000). Setting it to the podman user and chowning back each run
flipped ownership on every deploy and briefly locked the app out of its
database.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Bastian de Byl
2026-09-13 23:14:46 -04:00
co-authored by Claude Opus 5
parent a9f51b77e1
commit f59ade748b
4 changed files with 135 additions and 0 deletions
+7
View File
@@ -27,6 +27,12 @@ hass_path: "{{ podman_volumes }}/hass"
partsy_path: "{{ podman_volumes }}/partsy"
partsy_skudak_path: "{{ podman_volumes }}/partsy-skudak"
photos_path: "{{ podman_volumes }}/photos"
# rsvp.debyl.io -- invite-only RSVP app (~/src/rsvp-debylio). Both listeners are
# published on loopback only: Caddy proxies the public one, and the admin one
# only for LAN clients. Caddy runs with network: host, so 127.0.0.1 reaches them.
rsvp_path: "{{ podman_volumes }}/rsvp"
rsvp_public_port: 9080
rsvp_admin_port: 9081
# Named rather than hardcoded so the ML service can be stood up beside a broken
# one without editing tasks. On 2026-08-28 a worker thread wedged in
# uninterruptible sleep (D state) in exit_mmap, which made the container
@@ -185,6 +191,7 @@ home_server_name_io: home.debyl.io
parts_server_name_io: parts.debyl.io
photos_server_name_io: photos.debyl.io
gitea_debyl_server_name: git.debyl.io
rsvp_server_name: rsvp.debyl.io
# skudak.com domains (migration from skudakrennsport.com)
parts_skudak_server_name: parts.skudak.com