# Deployment Two compose files live here, for two distinct scenarios: | File | Purpose | |---|---| | `docker-compose.prod.yml` | Pulls pre-built images from GHCR. This is what runs on the home server. | | `docker-compose.dev.yml` | Dev stack with Postgres only — auth runs on local credentials. | Images are built by `.github/workflows/build-and-push.yml` on every push to `main` and published to: - `ghcr.io//familynido-api:latest` - `ghcr.io//familynido-web:latest` Each push also produces an immutable `sha-` tag for rollbacks. ## First-time server setup Prerequisites on the server (Ubuntu, Docker, Traefik on the `${TRAEFIK_NETWORK}` network with a Let's Encrypt cert resolver). 1. **Create a Personal Access Token** on GitHub with scope `read:packages`. GHCR is private for private repos, so the server needs to authenticate. 2. **Log in to GHCR on the server** (one-time, the credentials are cached in `~/.docker/config.json`): ```bash echo | docker login ghcr.io -u --password-stdin ``` 3. **Prepare the deploy folder** (e.g. `/opt/familynido/`): ```bash sudo mkdir -p /opt/familynido sudo chown $USER:$USER /opt/familynido cd /opt/familynido ``` Copy `deploy/docker-compose.prod.yml` and `deploy/.env.example` from this repo into that folder, rename the example to `.env`, and fill it in with the real PocketId/Postgres credentials. 4. **Pull and start**: ```bash docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml up -d ``` 5. Traefik picks the service up via the labels and serves it at the `${TRAEFIK_HOST}` you configured once Let's Encrypt issues the cert. > **OIDC client id.** The default `OIDC_CLIENT_ID` is `familynido`. If you > use PocketID or another upstream IdP, create a client with that id (or > change the value here to match what your IdP exposes). ## Google Calendar credentials The calendar module mirrors events from Google Calendar (read-only). The backend needs an OAuth client to drive the consent flow: 1. Create a project at https://console.cloud.google.com and enable the **Google Calendar API**. 2. In **APIs & Services → OAuth consent screen**, configure an external app and add the scope `https://www.googleapis.com/auth/calendar.readonly`. Point the privacy/terms URLs at the pages your deployment serves under `/legal/privacidad.html` and `/legal/condiciones.html`. Both live in `web/familynido-web/public/legal/` in the repo and are deployed automatically with the web image. 3. In **APIs & Services → Credentials**, create an **OAuth 2.0 Client ID** of type *Web application*. Set the authorized redirect URI to exactly `https:///api/calendar/google/callback`. 4. Copy the client id and secret into `.env`: ```env GOOGLE_CLIENT_ID=... GOOGLE_CLIENT_SECRET=... GOOGLE_OAUTH_REDIRECT_URI=https:///api/calendar/google/callback ``` 5. Restart the API container so the new env vars are picked up: ```bash docker compose -f docker-compose.prod.yml up -d --force-recreate api ``` The callback path is already proxied by the existing `/api/` block in `deploy/nginx/default.conf`, so no extra reverse-proxy config is needed. ## Updating after a push to `main` Until Watchtower is wired up (separate commit), updates are a manual pull: ```bash cd /opt/familynido docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml up -d ``` ## Rolling back Each build tags the images with `sha-`. To roll back to a previous build without reverting the main branch: ```bash # 1. Pin the images to a known-good SHA in docker-compose.prod.yml, # e.g. ghcr.io/.../familynido-api:sha-a57d52e # 2. docker compose -f docker-compose.prod.yml up -d ``` ## Database migrations Not yet automated. After a deploy that includes a new EF migration, run them manually from the repo on the dev machine pointed at the prod DB, or (TODO) add `db.Database.Migrate()` to `Program.cs` gated by config.