Nye-TeeOff/docs/vps-deploy-teeoff.md

141 lines
3.7 KiB
Markdown

# 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
```