# Deployment Guide

Run the **entire FC Foz Platform on a single server** — frontend, backend,
MongoDB and file storage — behind Caddy with automatic HTTPS, on your domain
**fcfoz.com**.

```
                         Internet
                            │  https://fcfoz.com
                     ┌──────▼───────┐
                     │    Caddy      │  (TLS, reverse proxy)
                     │   :80 :443    │
                     └──┬────────┬───┘
             /api/*, /uploads/*   │  everything else
                     │            │
              ┌──────▼─────┐  ┌───▼────────┐
              │  backend    │  │  frontend  │  (nginx serving the SPA)
              │(ASP.NET Core)│ └────────────┘
              └──────┬──────┘
              ┌──────▼──────┐
              │  MongoDB    │  (+ uploads volume)
              └─────────────┘
```

Because the frontend and API share one origin (`https://fcfoz.com`), there are
**no CORS or mixed-content issues** — the app calls the API at `/api`.

You need:

- A **server** (VPS) running Linux with a public IP (e.g. Ubuntu 22.04, 2 GB RAM).
- The domain **fcfoz.com** (DNS managed by you).
- Optionally a **Firebase** project for Google sign-in (email/password works without it).

---

## Test on your local network first (no domain)

Before buying/pointing a domain, you can run the **exact same stack** over plain
HTTP on your LAN. It serves the whole app (frontend + API + uploads) on port 80
from one machine — access it from any device on the network by the machine's IP.

On the machine that will host it (needs only Docker):

```bash
# From the server itself (localhost):
docker compose -f docker-compose.local.yml up -d --build
# open http://localhost/

# To reach it from OTHER devices and have uploaded images resolve, pass the
# machine's LAN IP so upload URLs are absolute:
SERVER_URL=http://192.168.1.87 docker compose -f docker-compose.local.yml up -d --build
# open http://192.168.1.87/ from your phone/laptop on the same Wi-Fi
```

Notes:
- Default admin: `admin@foz.pt` / `admin123`.
- Email/password login works. **Google sign-in won't** on a bare IP (Firebase
  only authorizes real domains) — that's expected; it works once you're on `fcfoz.com`.
- Port 80 already used? Start on another port:
  `HTTP_PORT=8080 SERVER_URL=http://192.168.1.87:8080 docker compose -f docker-compose.local.yml up -d --build`
- Stop it: `docker compose -f docker-compose.local.yml down` (add `-v` to wipe its data).

When you're happy, continue below to go live on **fcfoz.com** with HTTPS.

---

## Step 1 — Point fcfoz.com at your server

In your domain registrar / DNS provider, create two **A records** pointing at
your server's public IP:

| Type | Name  | Value              |
| ---- | ----- | ------------------ |
| A    | `@`   | `<your server IP>` |
| A    | `www` | `<your server IP>` |

Wait until they resolve:

```bash
dig +short fcfoz.com
dig +short www.fcfoz.com
```

Both must return your server IP before continuing (TLS issuance depends on it).

---

## Step 2 — Install Docker on the server

```bash
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER      # log out/in afterwards
```

Open the firewall for SSH + web traffic:

```bash
sudo ufw allow 22,80,443/tcp       # if you use ufw
sudo ufw enable
```

---

## Step 3 — Get the code and configure

```bash
git clone <your-repo-url> foz-fc-platform
cd foz-fc-platform

cp .env.production.example .env
nano .env
```

Set at least these values in `.env`:

| Variable | Set to |
| --- | --- |
| `DOMAIN` | `fcfoz.com` |
| `ACME_EMAIL` | a real email (Let's Encrypt notices) |
| `MONGO_PASSWORD` | a strong database password |
| `JWT_SECRET` | long random string — `openssl rand -base64 48` |
| `SEED_ADMIN_EMAIL` / `SEED_ADMIN_PASSWORD` | your first admin account |

The `VITE_*` values are prefilled with the club's public keys (Firebase, reCAPTCHA,
workers). Adjust only if you use different services. `CORS_ORIGINS`,
`FIREBASE_PROJECT_ID` and the API URL are already set for `fcfoz.com`.

---

## Step 4 — Build & start everything

```bash
docker compose -f docker-compose.prod.yml up -d --build
```

First run takes a few minutes (it builds the frontend and backend images). Caddy
then automatically provisions TLS certificates for `fcfoz.com` and `www.fcfoz.com`.

---

## Step 5 — Verify

```bash
curl https://fcfoz.com/api/health          # -> {"status":"ok"}
```

Open **https://fcfoz.com** in a browser — the site should load and be able to
register/login. Watch logs if needed:

```bash
docker compose -f docker-compose.prod.yml logs -f caddy backend frontend
```

> **Storage:** uploads are saved to the `uploads_data` volume and served at
> `https://fcfoz.com/uploads/...`. The database lives in `mongo_data`. Both
> persist across restarts and rebuilds.

---

## Step 6 — Google sign-in (optional)

If you use Google login, in the **Firebase Console → Authentication → Settings →
Authorized domains**, add `fcfoz.com` (and `www.fcfoz.com`). Ensure
`FIREBASE_PROJECT_ID` in `.env` matches `VITE_FIREBASE_PROJECT_ID`.

Email/password login needs none of this — it works out of the box.

---

## Updating the site

The frontend bakes its config in at **build time**, so after changing code or any
`VITE_*` value you must rebuild:

```bash
cd foz-fc-platform
git pull
docker compose -f docker-compose.prod.yml up -d --build
```

---

## Backups

**Database**

```bash
docker exec foz-fc-mongo sh -c \
  'mongodump -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" \
   --authenticationDatabase admin --archive' > backup-$(date +%F).archive
```

**Uploaded files**

```bash
docker run --rm -v foz-fc-platform_uploads_data:/data -v "$PWD":/backup alpine \
  tar czf /backup/uploads-$(date +%F).tgz -C /data .
```

Restore the DB with `mongorestore --archive < backup.archive` (piped into the container).

---

## Common commands

```bash
docker compose -f docker-compose.prod.yml ps           # status
docker compose -f docker-compose.prod.yml logs -f       # all logs
docker compose -f docker-compose.prod.yml restart backend
docker compose -f docker-compose.prod.yml down          # stop (add -v to WIPE data)
```

---

## Security checklist

- [ ] Strong, unique `MONGO_PASSWORD` and `JWT_SECRET` (never the examples).
- [ ] Change the seeded admin password after first login.
- [ ] MongoDB is not published to the host (kept internal in the prod compose).
- [ ] Firewall allows only 22 / 80 / 443.
- [ ] `.env` is never committed (git-ignored).

---

## Troubleshooting

| Symptom | Likely cause / fix |
| --- | --- |
| TLS certificate not issued | DNS A records for `fcfoz.com` **and** `www.fcfoz.com` must resolve to the server, and ports 80/443 must be open. Check `docker compose -f docker-compose.prod.yml logs caddy`. |
| Site loads but data/login fails | Check `docker compose ... logs backend`; confirm MongoDB is healthy. |
| Uploaded images 404 | Confirm the `uploads_data` volume exists and `DOMAIN` is correct (upload URLs use `https://<DOMAIN>`). |
| Google sign-in fails | Add `fcfoz.com` to Firebase Authorized domains; ensure project ids match. |
| Changed a `VITE_*` value but nothing changed | Rebuild: `docker compose -f docker-compose.prod.yml up -d --build` (Vite inlines env at build time). |

---

For local development, see the root `README.md` (Quick start) — it uses
`docker-compose.yml` (Mongo on `27018`) and the Vite dev server on `:8080`.
