|
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 38s
De twee platen die ik zelf had aangemerkt plus de overige zwakke plekken uit de visuele controle. Audit blijft schoon op alle drie de niveaus: geen onbereikbare vakken, geen onzichtbare of afdwalende lijnen. Dieren met vier poten in plaats van twee latjes: - savanne: giraf en zebra hebben nu vier poten met een knik en een hoef, een langere en slankere giraffennek die breed uitloopt in de schouder, een kop met snuit, ossenhoorns en oor, en een manestreep bij de zebra. - dinosaurusvallei: vier poten met voeten en een staart die echt versmalt. Vormen die verkeerd lazen: - boom van vier seizoenen: de kroon was een gladde cirkel met een kruis erin en las als een bal. De vier seizoenskwarten hebben nu een geschulpte buitenrand, dus het leest als bladerdek. De losse plukken op de rand zijn vervangen door bladclusters binnen elk kwart, waardoor ook de inkepingen verdwenen die ontstonden waar plukken en bladvormen elkaar overlapten. - koraalrif: het zeepaardje was een smal buisje dat als worm las. Nu een stevige romp met een aparte gekrulde staart, de rugvin op de rug in plaats van dwars door het lichaam, en meer buikringen. - vrienden in zee: de schildpad stond klem tegen de rechterrand; hij is groter en verder naar binnen geschoven, met grotere schildplaten. Lege vlakken gevuld, want er was niets te kleuren: - kleine tuindieren: zon, wolk en een vlinder in de bovenhelft. - koraalrif: een schooltje visjes in de lege bovenhoek; de bellen zijn meegeschoven. - feesttaart: een tafelkleed met schulprand in de onderste strook. - grote graafmachine: zonnestralen, zoals bij de andere zonnen. Losse elementen vastgezet: - regenwoud: de bladeren aan de rechterkant zweefden los naast de stam en sluiten nu aan, met bladnerven op niveau 3. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS |
||
|---|---|---|
| .forgejo/workflows | ||
| db | ||
| deploy | ||
| docs/curriculum | ||
| public | ||
| src | ||
| test | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| compose.yaml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| VERSION | ||
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
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) enactions/checkout+appleboy/ssh-actionkunnen ophalen. Pasruns-onin de workflows aan naar het label van jouw runner als dat nietubuntu-latestis.
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:
# /etc/docker/daemon.json
{
"insecure-registries": ["10.0.20.22:3000"]
}
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:
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_HOPSalleen aan wanneer de proxyketen werkelijk verandert. - Bij een aparte Traefik-container kan een gedeeld intern Docker-netwerk nodig
zijn; zet
WEB_BIND_IPniet ruimer dan noodzakelijk. SUPER_PASSis 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)
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.