2.5 KiB
2.5 KiB
Daily Quote
A small full-stack "quote of the day" app, built for the privatecloud VM private-cloud-daily-quote.
Stack
- Frontend: Vite + React, styled with MUI using a Material Design 3 theme (color roles, type scale, shape/elevation).
- API: Express (Node.js), serving both
/api/*and the built SPA on port 3000. - Database: Postgres 16, run via Docker Compose (
quotes,users,favoritestables — seedb/init.sql). - Platform auth: Zitadel, self-hosted via Docker, OIDC Authorization Code + PKCE. Gates "submit a quote" and "favorites"; browsing is public.
- Git hosting: Gitea, self-hosted via Docker (this repo's
origin). - CI/CD: Gitea Actions, using a local
act_runnercontainer. See.gitea/workflows/ci.yml. - Observability:
prom-clientmetrics at/api/metrics, scraped by Prometheus, visualized in a provisioned Grafana dashboard. - Backup: nightly
pg_dumpvia a systemd timer (quoteapp-backup.timer), 7-day retention, dumps to~/backups.
Local services (Docker)
| Service | Internal port | Host port | Notes |
|---|---|---|---|
| Postgres | 5432 | 5432 (loopback only) | app + zitadel databases |
| Zitadel | 8080 | 8080 | public via https://<host>:8080 |
| Gitea | 3000 | 3001 | public via https://<host>:3001 |
| Gitea SSH | 22 | 2222 (loopback only) | |
| act_runner | - | - | registered against Gitea Actions |
| Prometheus | 9090 | 9090 (loopback only) | |
| Grafana | 3000 | 3002 | public via https://<host>:3002, admin/admin |
Bring the stack up with:
docker compose up -d
Running the app
The app itself runs directly on the VM (not in Docker) as a systemd service on port 3000:
sudo systemctl status quote-app
To rebuild after a frontend change:
cd client && npm run build
sudo systemctl restart quote-app
Auth notes
Zitadel is reachable at https://<vm-host>:8080. Since exe.dev's proxy only marks one
port ("3000", the app) fully public, signing in requires being an authorized user of
this workspace to reach the Zitadel login page on port 8080 — browsing and reading
quotes on the main app is public regardless. A demo user (demo) was created for
testing; see .zitadel-demo-user (not committed) for its password.
Backups
./backup/backup.sh # run manually
systemctl list-timers quoteapp-backup.timer