# Production scripts Helper scripts that talk to the Hetzner VPS hosting Supabase + LiveKit. All commands read shared config from `config.sh`. ## Setup (once) 1. Copy your SSH key to the server so scripts don't prompt for a password: ``` ssh-keygen -t ed25519 # only if you don't already have one # PROD now points at the netralax.de VPS (user "debian"; see config.sh). ssh-copy-id debian@141.95.34.204 ssh debian@141.95.34.204 'echo ok' ``` 2. Make the scripts executable: ``` chmod +x scripts/prod/*.sh ``` 3. Edit `scripts/prod/config.sh` when the server IP or domains change. ## Scripts ### `push-migrations.sh []` Uploads `supabase/migrations/*.sql` to `/tmp/migrations` on the server and runs each file through `docker compose exec db psql`. Pass an optional filter (substring match) to only apply specific timestamps. ### `push-edge-function.sh ` Uploads `supabase/functions//` to `/opt/supabase/volumes/functions//` and restarts the edge-runtime container. ### `gen-jwt.sh ` Wrapper around `scripts/gen-jwt.py`. Prints fresh 10-year `anon` and `service_role` HS256 JWTs for the given secret. Paste the results into `/opt/supabase/.env` (`ANON_KEY` / `SERVICE_ROLE_KEY`) and the desktop `.env` (`SUPABASE_ANON_KEY`). ### `create-invite.sh [] []` `INSERT`s a signup-invite row into `public.invites`. Defaults: 50 uses, 365-day expiry. ### `logs.sh [] []` Follows logs from either the `supabase` or `livekit` compose stack. ### `restart.sh []` Restarts one service, or (without a service) brings the whole stack down and back up. ### `tunnel-db.sh []` Opens `ssh -L :localhost:5432`. Default local port is `5433`. Leave it running while you use `psql` / `supabase db push` / etc. ### `tunnel-mailpit.sh []` Opens a tunnel to the Mailpit web UI. Default local port is `8025`. ### `rotate-livekit-keys.sh` Generates a fresh LiveKit API key + secret, rewrites the `keys:` block in `/opt/livekit/livekit.yaml`, and restarts the SFU. After running, also update the Supabase `.env` (`LIVEKIT_API_KEY` / `LIVEKIT_API_SECRET`) and `restart.sh supabase functions` so the mint-livekit-token Edge Function sees the new values. ## Typical workflows **Ship a new migration** ``` # add supabase/migrations/20260501_my_change.sql locally ./scripts/prod/push-migrations.sh 20260501 ``` **Ship a new Edge Function change** ``` # edit supabase/functions/mint-livekit-token/index.ts locally ./scripts/prod/push-edge-function.sh mint-livekit-token ``` **Debug a failing magic-link** ``` ./scripts/prod/logs.sh supabase auth 200 ./scripts/prod/tunnel-mailpit.sh # open http://localhost:8025 ``` **Rotate LiveKit credentials** ``` ./scripts/prod/rotate-livekit-keys.sh # follow the printed hint to update supabase .env + restart functions ```