# TeeOff VPS deployment This project can be served on `https://teeoff.no` with Docker Compose and Caddy. ## 1. DNS at one.com Create or update these records: - `A` record for the root domain (`@` / empty hostname) -> `85.137.228.98` - `CNAME` for `www` -> `teeoff.no` If `teeoff.no` currently has old `A`, `AAAA`, web-forward, or alias records pointing elsewhere, remove or replace them. If you do not actively use IPv6 on the VPS, remove any stale `AAAA` record for `teeoff.no` and `www`. one.com documents A/CNAME management here: - https://help.one.com/hc/en-us/articles/360000799298-How-do-I-create-an-A-record - https://help.one.com/hc/en-us/articles/360000803517-How-do-I-create-a-CNAME-record ## 2. Required environment values On the VPS, create `.env` in the project root and make sure these values are correct: ```env PUBLIC_BASE_URL=https://teeoff.no NEXT_PUBLIC_SITE_URL=https://teeoff.no DATABASE_URL=postgresql://teeoff_admin:...@db:5432/teeoff POSTGRES_USER=teeoff_admin POSTGRES_PASSWORD=... POSTGRES_DB=teeoff JWT_SECRET=... PUBLIC_SESSION_SECRET=... ACME_EMAIL=you@example.com ``` If public comments or Google login are used, keep the SMTP and Google OAuth values configured too. Important Google OAuth update: - Authorized redirect URI should include `https://teeoff.no/api/public/auth/google/callback` ## 3. Start the production stack Use the production compose file: ```bash docker compose -f docker-compose.prod.yml up -d --build ``` This stack exposes only: - `80/tcp` - `443/tcp` The app containers stay internal and are reached through Caddy only. ## 4. Reverse proxy layout The Caddy config is in `deploy/Caddyfile`. Routing is: - `https://teeoff.no/api/admin/uploads/images` -> Next.js - all other `https://teeoff.no/api/*` -> FastAPI - everything else -> Next.js frontend That exception matters because the image upload endpoint is implemented in Next.js, while the rest of the API lives in FastAPI. The `/api` prefix must be preserved when proxying, because both apps define routes with `/api/...` paths. ## 5. VPS hardening Recommended minimum host steps on Ubuntu 24.04: ```bash sudo apt update && sudo apt upgrade -y sudo apt install -y ufw fail2ban sudo ufw allow OpenSSH sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable ``` Important Docker note: published Docker ports can bypass `ufw` if you expose them directly on the host. That is why the production compose file publishes only Caddy's `80` and `443`. Useful official references: - Ubuntu UFW docs: https://ubuntu.com/server/docs/how-to/security/firewalls/ - Docker firewall warning: https://docs.docker.com/engine/network/packet-filtering-firewalls/ - Docker port publishing warning: https://docs.docker.com/engine/network/port-publishing/ - Caddy automatic HTTPS: https://caddyserver.com/docs/automatic-https ## 6. SSH hardening Do this after you have verified SSH key login works: - create a non-root sudo user if you do not already use one - disable password authentication in `/etc/ssh/sshd_config` - disable root SSH login if you do not need it - restart SSH Typical settings: ```text PasswordAuthentication no PermitRootLogin no PubkeyAuthentication yes ``` Then: ```bash sudo systemctl restart ssh ``` ## 7. Verification checklist After DNS has propagated and the stack is up: ```bash curl -I http://teeoff.no curl -I https://teeoff.no curl -I https://www.teeoff.no curl -I https://teeoff.no/api/health ``` Expected results: - `http://teeoff.no` redirects to HTTPS - `https://www.teeoff.no` redirects to `https://teeoff.no` - `https://teeoff.no/api/health` returns the API health payload ## 8. Existing compose file `docker-compose.yml` is still useful for the earlier/local setup. For the VPS cutover, prefer: ```bash docker compose -f docker-compose.prod.yml up -d --build ```