Deploying HEIG Classroom¶
This section is for the operator — the person hosting the portal. Teachers and students never touch anything described here: once the platform is deployed, onboarding a teaching organization happens entirely from the portal (see the GitHub App page, Onboarding an organization).
What a deployment looks like¶
One small VM runs everything (ADR-009): the Node monolith (API + built SPA),
PostgreSQL and a daily backup job under Docker Compose, behind a native Caddy
for TLS. State lives in PostgreSQL only (ADR-004); secrets travel through the
environment and a secrets/ directory, never through git (ADR-010).
Caddy (TLS) ──► app (Fastify + SPA, :3000) ──► PostgreSQL
▲ ▲
GitHub webhooks / OIDC login pg_dump backups
Steps¶
- Provision the VM — Ubuntu/Debian, 2 GB of swap if RAM is short, UFW
with SSH/80/443, Docker + compose plugin, Caddy. The full command list
lives in
deploy.mdat the repository root. - DNS — point the portal's hostname at the VM (A/AAAA records).
- Clone and configure — clone the repository into
/opt/heig-classroom, copy.env.exampleto.env.prodand fill it in: PostgreSQL password, cookie secret, OIDC provider (SWITCH edu-ID in production), super-admin e-mail, Scaleway TEM credentials for e-mail, session TTL. - Create the GitHub App — once, globally. Follow
the GitHub App page; the App ID, private key, slug,
webhook secret and OAuth client land in
.env.prodandsecrets/. - First start —
docker compose -f compose.prod.yml --env-file .env.prod up -d --build. Migrations run at boot (MIGRATE_ON_START=1); checkhttps://<host>/healthzreturnsdatabase: up, jobs: up. - Backups — the compose
backupservice does a dailypg_dumpwith 30 days of retention; wire a copy off the VM (rclone to an object store) to meet the RPO.
Updating¶
cd /opt/heig-classroom && git pull
docker compose -f compose.prod.yml --env-file .env.prod up -d --build
Rollback = git checkout <previous-tag> and the same command. Migrations are
additive; when in doubt, restore the previous night's dump.