Files
info-share-spot/DEPLOY.md
T
adminandClaude Opus 5 13fca11c81 Fix deploy config to match the actual VPS (Caddy, not Traefik)
The server fronts everything with Caddy (container root-caddy-1), has no
Dockge and no Traefik, and keeps compose stacks in /docker — not
/opt/stacks. Every traefik.* label in this compose file was inert, so the
container would build and run while never being routed.

Join the external `web` network Caddy is on so it can reach the container
by name (info-share-spot:3000) and publish no host port. Routing now
lives in /root/Caddyfile on the server.

Rewrite DEPLOY.md against the real topology, including the Caddyfile
validate-before-reload step — a bad Caddyfile takes down every site on
the box, and Caddy serves a stale in-memory config until something
reloads it, which hides the breakage until the next restart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 09:15:40 -04:00

3.7 KiB

Deploying to the avriahost VPS (Docker + Caddy)

This app is a TanStack Start (SSR) app. The Docker build produces a self-contained Node server (.output/server/index.mjs) via the Nitro node-server preset and runs it in a container on port 3000. Caddy sits in front and gives it automatic HTTPS.

Earlier revisions of this file described a Hostinger-catalog Docker + Dockge + Traefik setup. That is not what the server runs. There is no Dockge and no Traefik on this box, and traefik.* compose labels are silently ignored by Caddy — the container builds and runs perfectly while never being routed.

The actual server

Host 2.25.155.250 (srv1720881.hstgr.cloud), hostname avriahost, Ubuntu 24.04
Reverse proxy Caddy, container root-caddy-1, owns :80/:443, automatic Let's Encrypt
Caddy config /root/Caddyfile (compose project dir /root)
Compose stacks /docker/<name> — not /opt/stacks
This stack /docker/info-share-spot
Public URL https://info-share-spot.srv1720881.hstgr.cloud
Git host self-hosted Gitea at http://2.25.155.250:32774 (SSH on port 44139)

Caddy shares the external web Docker network with this app, so it reaches the container by name — info-share-spot:3000. The app therefore publishes no host port at all.

Routing

The route lives in /root/Caddyfile:

info-share-spot.srv1720881.hstgr.cloud {
	reverse_proxy info-share-spot:3000
}

Always validate before reloading — a bad Caddyfile takes down every site on the box, and Caddy keeps serving a stale in-memory config until something reloads it, which hides the breakage until the next restart:

docker exec root-caddy-1 caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
docker exec -w /etc/caddy root-caddy-1 caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile

Deploying an update

cd /docker/info-share-spot
git pull
docker compose up -d --build

First build takes a few minutes (bun install + Vite/Nitro SSR build on 2 cores).

git pull needs credentials: the Gitea repo is private, so the VPS needs its own read-only deploy key. The public key is at /root/.ssh/gitea_deploy.pub; add it under the repo's Settings → Deploy Keys (read-only), then point the remote at SSH:

git remote set-url origin ssh://git@2.25.155.250:44139/admin/info-share-spot.git

Until that key is installed, push code up from a workstation instead:

rsync -az --exclude .env.secret /path/to/info-share-spot/ root@2.25.155.250:/docker/info-share-spot/
ssh root@2.25.155.250 'chown -R root:root /docker/info-share-spot'

Environment

  • The committed .env holds only the public-safe SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY (the publishable key is designed for browsers). Compose substitutes them from that file at build and run time.
  • Real secrets go in .env.secret next to the compose file — gitignored, loaded by compose if present, never committed. Add SUPABASE_SERVICE_ROLE_KEY there if you later use the server-side admin client.
  • Supabase project is qgmcpounpkgsjlwosjdi. Note this is a different project from the ACMACC one used by the avria.cloud app — don't cross the wires.

Notes

  • Google sign-in needs the Google provider enabled in the Supabase dashboard (Auth → Providers) and the production URL added under Auth → URL Configuration. Email/password works without any of that.
  • The first account created at /auth becomes the admin. This has already happened on this project.
  • edu.avriahost.com on this server returns 502 — it proxies to host.docker.internal:8080 and nothing listens there. Unrelated to this app.