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. |
||
|---|---|---|
| .. | ||
| nginx | ||
| .env.example | ||
| api-entrypoint.sh | ||
| api.Dockerfile | ||
| docker-compose.dev.yml | ||
| docker-compose.prod.yml | ||
| README.md | ||
| web.Dockerfile | ||
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:latestghcr.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).
-
Create a Personal Access Token on GitHub with scope
read:packages. GHCR is private for private repos, so the server needs to authenticate. -
Log in to GHCR on the server (one-time, the credentials are cached in
~/.docker/config.json):echo <PAT> | docker login ghcr.io -u <github-username> --password-stdin -
Prepare the deploy folder (e.g.
/opt/familynido/):sudo mkdir -p /opt/familynido sudo chown $USER:$USER /opt/familynido cd /opt/familynidoCopy
deploy/docker-compose.prod.ymlanddeploy/.env.examplefrom this repo into that folder, rename the example to.env, and fill it in with the real PocketId/Postgres credentials. -
Pull and start:
docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml up -d -
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_IDisfamilynido. 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:
-
Create a project at https://console.cloud.google.com and enable the Google Calendar API.
-
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.htmland/legal/condiciones.html. Both live inweb/familynido-web/public/legal/in the repo and are deployed automatically with the web image. -
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. -
Copy the client id and secret into
.env:GOOGLE_CLIENT_ID=... GOOGLE_CLIENT_SECRET=... GOOGLE_OAUTH_REDIRECT_URI=https://<your-host>/api/calendar/google/callback -
Restart the API container so the new env vars are picked up:
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:
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:
# 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.