All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 17s
153 lines
6.2 KiB
Markdown
153 lines
6.2 KiB
Markdown
# Teach
|
|
|
|
Digibord-webapp (Fastify + static frontend) met PostgreSQL, gecontaineriseerd en
|
|
via Forgejo Actions automatisch uitgerold: `dev` → test-VM, release → productie-VM.
|
|
|
|
## Structuur
|
|
|
|
```
|
|
teach/
|
|
├─ public/index.html # de digibord-app (voorheen teach.html)
|
|
├─ src/server.js # Fastify: serveert de app + /api + DB-pool
|
|
├─ db/001_init.sql # initieel Postgres-schema
|
|
├─ Dockerfile # productie-image (non-root, healthcheck)
|
|
├─ compose.yaml # lokaal draaien (app + postgres)
|
|
├─ deploy/compose.deploy.yaml # test/prod: pullt image uit de registry
|
|
├─ .forgejo/workflows/
|
|
│ ├─ dev.yaml # push naar dev → build + deploy test
|
|
│ └─ release.yaml # release → build + deploy prod
|
|
└─ .env.example
|
|
```
|
|
|
|
## Lokaal draaien
|
|
|
|
```bash
|
|
cp .env.example .env # pas POSTGRES_PASSWORD en DATABASE_URL aan
|
|
docker compose up --build
|
|
```
|
|
|
|
App op http://localhost:3000, healthcheck op `/healthz`, DB-check op `/readyz`.
|
|
|
|
## Architectuurkeuzes
|
|
|
|
- **Container i.p.v. losse static site**: omdat er een database bijkomt, is een
|
|
backend nodig (browser praat niet rechtstreeks met Postgres). De Fastify-app
|
|
serveert de HTML én biedt de `/api`, en praat met de DB.
|
|
- **Forgejo container registry**: CI bouwt de image één keer en pusht die; beide
|
|
VM's pullen exact dezelfde geteste image. Geen build op de productie-VM.
|
|
- **Pangolin/Traefik verzorgt de publieke HTTPS-ingang**. De meegeleverde nginx
|
|
vormt de interne proxylaag en luistert standaard op poort `8081`, zodat de
|
|
Pangolin/Traefik-route deze via het VM-/containernetwerk kan bereiken. De Fastify-app vertrouwt precies twee proxy-hops.
|
|
|
|
## Eenmalige setup
|
|
|
|
### 1. Repo aanmaken in Forgejo
|
|
Maak een leeg repo (bv. `ramon/teach`) en push (zie onderaan).
|
|
|
|
### 2. Registry / Actions variabelen en secrets
|
|
Onder **Settings → Actions → Variables** van het repo (of org):
|
|
|
|
| Variable | Waarde | Uitleg |
|
|
|------------|------------------|---------------------------------|
|
|
| `REGISTRY` | `10.0.20.22:3000`| Host van je Forgejo = registry |
|
|
|
|
De image heet dan `10.0.20.22:3000/bes-r/teach`.
|
|
|
|
Onder **Settings → Actions → Secrets**:
|
|
|
|
| Secret | Uitleg |
|
|
|--------------------|--------------------------------------------------------------|
|
|
| `REGISTRY_USER` | Forgejo-gebruiker met package-write rechten |
|
|
| `REGISTRY_TOKEN` | Token/wachtwoord voor die gebruiker (scope: packages) |
|
|
| `TEST_HOST` | IP/hostname van de test-VM |
|
|
| `TEST_USER` | SSH-gebruiker op de test-VM |
|
|
| `TEST_SSH_KEY` | Private SSH-key (deploy key) voor de test-VM |
|
|
| `TEST_DEPLOY_PATH` | Pad op de test-VM met `compose.deploy.yaml` + `.env` + `db/` |
|
|
| `PROD_HOST` | IP/hostname van de productie-VM |
|
|
| `PROD_USER` | SSH-gebruiker op de productie-VM |
|
|
| `PROD_SSH_KEY` | Private SSH-key voor de productie-VM |
|
|
| `PROD_DEPLOY_PATH` | Pad op de productie-VM met de deploy-bestanden |
|
|
|
|
> De runner moet de `docker`-CLI kunnen gebruiken (host-socket of docker-in-docker)
|
|
> en `actions/checkout` + `appleboy/ssh-action` kunnen ophalen. Pas `runs-on` in
|
|
> de workflows aan naar het label van jouw runner als dat niet `ubuntu-latest` is.
|
|
|
|
### 2b. HTTP-registry toestaan (insecure-registries)
|
|
Je Forgejo draait op **`http://10.0.20.22:3000`** (platte HTTP). Docker weigert
|
|
HTTP-registries tenzij je ze expliciet toestaat. Doe dit op **drie** plekken: de
|
|
**runner-host** (die pusht) en **beide VM's** (die pullen). Op elke Docker-host:
|
|
|
|
```bash
|
|
# /etc/docker/daemon.json
|
|
{
|
|
"insecure-registries": ["10.0.20.22:3000"]
|
|
}
|
|
```
|
|
|
|
```bash
|
|
sudo systemctl restart docker
|
|
```
|
|
|
|
> Zet je Forgejo later achter HTTPS met een echt domein, dan kan deze stap weg
|
|
> en gebruik je dat domein als `REGISTRY`.
|
|
|
|
### 3. Deploy-map op elke VM
|
|
Op zowel de test- als de productie-VM, in het pad dat je bij `*_DEPLOY_PATH`
|
|
opgeeft:
|
|
|
|
```bash
|
|
mkdir -p teach && cd teach
|
|
# kopieer deze twee uit de repo:
|
|
# deploy/compose.deploy.yaml -> compose.deploy.yaml
|
|
# db/ -> db/
|
|
# maak een .env aan:
|
|
cat > .env <<'EOF'
|
|
IMAGE=10.0.20.22:3000/bes-r/teach:dev # prod: laat CI dit op :vX.Y.Z zetten
|
|
POSTGRES_DB=teach
|
|
POSTGRES_USER=teach
|
|
POSTGRES_PASSWORD=<sterk-wachtwoord>
|
|
DATABASE_URL=postgres://teach:<sterk-wachtwoord>@db:5432/teach
|
|
APP_PORT=3000
|
|
WEB_BIND_IP=0.0.0.0
|
|
WEB_PORT=8081
|
|
TRUST_PROXY_HOPS=2
|
|
SUPER_USER=beheerder
|
|
SUPER_PASS=<uniek-sterk-eerste-wachtwoord>
|
|
EOF
|
|
```
|
|
|
|
CI werkt bij elke deploy de `IMAGE=`-regel bij, pullt en herstart.
|
|
|
|
### 4. Pangolin/Traefik publiceren
|
|
|
|
Publiceer `http://<interne-vm-ip>:8081` via Pangolin/Traefik en laat daar TLS
|
|
beëindigen. De interne nginx behoudt `X-Forwarded-Proto: https`, waarna de app
|
|
Secure/HttpOnly/SameSite-cookies, HSTS en overige securityheaders gebruikt.
|
|
|
|
- Beperk poort 8081 met de hostfirewall tot het Pangolin/Traefik- of tunnelnetwerk.
|
|
- Pas `TRUST_PROXY_HOPS` alleen aan wanneer de proxyketen werkelijk verandert.
|
|
- Bij een aparte Traefik-container kan een gedeeld intern Docker-netwerk nodig
|
|
zijn; zet `WEB_BIND_IP` niet ruimer dan noodzakelijk.
|
|
- `SUPER_PASS` is alleen nodig bij een lege database, wordt nooit gelogd en
|
|
moet via de beveiligde deploy-omgeving worden aangeleverd.
|
|
- De overgang naar v0.3.03-beta trekt bestaande browsersessies bewust in.
|
|
|
|
## Workflow / branching
|
|
|
|
- Werk op feature-branches, merge naar **`dev`** → automatisch naar test.
|
|
- Tevreden? Maak een **release** (tag `vX.Y.Z`) → automatisch naar productie.
|
|
|
|
## Push naar Forgejo (eerste keer)
|
|
|
|
```bash
|
|
git remote add origin http://10.0.20.22:3000/bes-r/teach.git
|
|
git push -u origin main
|
|
git push -u origin dev
|
|
```
|
|
|
|
## Volgende stap: data uit localStorage naar de database
|
|
|
|
De frontend bewaart borden/gebruikers nu nog in `localStorage`. Om echt een
|
|
gedeelde database te gebruiken, bouwen we `/api`-endpoints (boards, folders,
|
|
users) in `src/server.js` en laten we de frontend die aanroepen i.p.v.
|
|
`localStorage`. Het schema in `db/001_init.sql` is daarvoor het startpunt.
|