diff --git a/deploy/nginx/kanban.internal.conf b/deploy/nginx/kanban.internal.conf new file mode 100644 index 00000000..06e49043 --- /dev/null +++ b/deploy/nginx/kanban.internal.conf @@ -0,0 +1,75 @@ +# Mesh-only vhost for vibe-kanban, fronted by the hanzalova edge proxy (office site). +# Cert: internal `lair` CA, minted from the operator box and renewed by +# step@kanban.timer (architecture internal-tls.md — dot-free instance label). +# Whole-app reverse proxy to the vibe-kanban remote-server on bob, which serves +# both its API and the built SPA. Mirrors the hermes.internal vhost pattern. +# ln -sf ../sites-available/kanban.internal.conf /etc/nginx/sites-enabled/ +# +# TLS terminates here, not in the app: upstream's compose puts Caddy in front for +# Let's Encrypt, which we drop entirely — this is a mesh-only name on the internal +# CA. remote-server is told SERVER_PUBLIC_BASE_URL=https://kanban.internal so the +# links it generates match what the client actually reached. +# +# Electric streams shape updates over long-lived HTTP; the long read timeout and +# disabled buffering below are what keep those from being cut or batched. + +# The relay is a separate service on the same host. It is mounted on a PATH of +# this vhost rather than given its own name: every relay URL on both sides is +# composed as {base}/v1/..., and the relay has no notion of its own public +# address, so a prefix is invisible to it. Same-origin also means no CORS and no +# second certificate -- and a future kanban.l4ir.net inherits the relay by +# copying the location block below. +upstream kanban_relay_up { + server bob.hanzalova.internal:27181; + keepalive 16; +} + +upstream kanban_up { + server bob.hanzalova.internal:27180; + keepalive 16; +} + +server { + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + server_name kanban.internal; + + ssl_certificate /etc/nginx/tls/cert/kanban.internal.pem; + ssl_certificate_key /etc/nginx/tls/key/kanban.internal.pem; + ssl_protocols TLSv1.3; + ssl_trusted_certificate /etc/pki/ca-trust/source/anchors/root-internal.pem; + + client_max_body_size 100m; + # Electric shape subscriptions are long-poll/streaming; don't cut them short. + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + + # Trailing slash on proxy_pass strips /relay-api/, so the relay sees the + # /v1/... routes it nests. Must precede location / . + location /relay-api/ { + proxy_pass http://kanban_relay_up/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + # The relay control channel is a long-lived websocket. + proxy_buffering off; + } + + location / { + proxy_pass http://kanban_up; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + # Sync streams must reach the browser as they arrive, not in buffers. + proxy_buffering off; + } +} diff --git a/deploy/vibe-kanban-relay.container b/deploy/vibe-kanban-relay.container index 17f3c0de..02c9edae 100644 --- a/deploy/vibe-kanban-relay.container +++ b/deploy/vibe-kanban-relay.container @@ -27,7 +27,7 @@ Wants=network-online.target Requires=vibe-kanban-db.service [Container] -Image=git.lair.cafe/lair/vibe-kanban-relay:REPLACE_WITH_IMMUTABLE_TAG +Image=git.lair.cafe/lair/vibe-kanban-relay:0.1.44-ge06652a ContainerName=vibe-kanban-relay Network=vibe-kanban.network # Published to the LAN so the hanzalova edge proxy can reach it; the browser and diff --git a/deploy/vibe-kanban.container b/deploy/vibe-kanban.container index 03ebd8a8..2d727a2d 100644 --- a/deploy/vibe-kanban.container +++ b/deploy/vibe-kanban.container @@ -23,7 +23,7 @@ Wants=network-online.target Requires=vibe-kanban-db.service [Container] -Image=git.lair.cafe/lair/vibe-kanban-remote:0.1.44-gccff6fc +Image=git.lair.cafe/lair/vibe-kanban-remote:0.1.44-ge06652a ContainerName=vibe-kanban Network=vibe-kanban.network PublishPort=27180:8081