familynido/deploy/README.md
Pablo Fernández a308041d59 Initial commit
FamilyNido — a self-hosted PWA for a single household: shared calendar,
chores, meals, school agenda, health records and a family wall. One
instance per family, deployable with `docker compose` on any home
server.

Stack: .NET 10 (ASP.NET Core Minimal APIs) + EF Core 10 + PostgreSQL 16
on the backend, Angular 21 (standalone, signals, zoneless) + Tailwind
CSS v4 on the frontend, SignalR for realtime, optional OIDC alongside
local credentials, integration via a versioned `/api/v1/**` public API.

See README.md for the module overview and how to deploy.
2026-05-13 00:23:14 +02:00

117 lines
4 KiB
Markdown

# 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/<GHCR_OWNER>/familynido-api:latest`
- `ghcr.io/<GHCR_OWNER>/familynido-web:latest`
Each push also produces an immutable `sha-<shortsha>` 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 <PAT> | docker login ghcr.io -u <github-username> --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://<your-host>/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://<your-host>/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-<shortsha>`. 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.