# Deployment Plan ## Chosen Method **Gitea Actions**, opgesplitst in twee workflow-bestanden: - `.gitea/workflows/continuous_integration.yaml` — draait de build/test/lint-gate, automatisch bij elke pull request (ongeacht branch) en bij elke push/merge naar `master`, of handmatig via `workflow_dispatch`. De `deploy-test`-job zelf blijft daarnaast ook beperkt tot `master`/`workflow_dispatch` via een eigen `if`-check. - `.gitea/workflows/deploy.yaml` — een herbruikbare (`workflow_call`) job die de `dist/` build via SCP (over SSH) uploadt naar de webroot van een omgeving. Sinds deze stap is er een echte, geautomatiseerde upload naar een **testomgeving**: een Raspberry Pi die de statische site serveert via nginx, achter een tweede Raspberry Pi die als nginx reverse proxy fungeert. ## How It Works 1. Bij elke pull request draait automatisch de build/test/lint-gate (`prepare` → `build` → `test`), zodat merge requests direct gevalideerd worden. 2. Zodra een pull request naar `master` gemerged wordt (of de workflow handmatig via `workflow_dispatch` gestart wordt), draait aanvullend de `deploy-test` job. 3. `deploy-test` roept de herbruikbare `deploy.yaml` workflow aan met `artifact_name`/`environment`/`deploy_path`, en geeft via `secrets: inherit` de Pi-inloggegevens door. Deze drie waarden (samen met de artifact-naam/pad die de `build`-job gebruikt) staan als variabelen in het `env:`-blok bovenaan `continuous_integration.yaml` (`ARTIFACT_NAME`, `ARTIFACT_PATH`, `DEPLOY_ENVIRONMENT`, `DEPLOY_PATH`), en worden via een kleine `config`-job als job-outputs doorgegeven aan `deploy-test` (nodig omdat de `env`-context zelf niet werkt in de `with:`-sectie van een reusable-workflow-aanroep). `DEPLOY_PATH` zelf is geen hardcoded waarde meer, maar wordt gelezen uit de Gitea repository variable `DEPLOY_PATH_TEST` (`Repository → Settings → Actions → Variables`), zodat het uploadpad aangepast kan worden zonder de workflow te wijzigen — zie `deployment-instructions.md`. 4. `deploy.yaml` downloadt de artifact en uploadt de inhoud via een `scp`-commando (met `sshpass` voor het wachtwoord) in een gewone shell-stap naar de webserver-Pi op het interne netwerk (`192.168.1.103`, poort `2224`). Dit vervangt de eerdere `appleboy/scp-action` (Docker-container-action), die faalde op de zelf-gehoste Podman-runner (`failed to attach to container: unable to upgrade to tcp, received 409`). 5. nginx op de webserver-Pi serveert de bestanden vanaf `/mnt/storage1/www/html/test/slpsoftware`; de reverse-proxy-Pi stuurt binnenkomend verkeer door naar deze webserver-Pi. Voorbeeldconfiguraties staan in `operations/deployment/nginx/` en zijn de daadwerkelijk in gebruik zijnde configuraties (niet langer illustratieve concepten). 6. De reverse-proxy-Pi is ook verantwoordelijk voor SSL: certificaten worden net als voorheen aangevraagd via certbot (Let's Encrypt) en HTTP-verkeer wordt doorverwezen naar HTTPS. ## Environments - **Test** (geautomatiseerd, altijd): zoals hierboven beschreven. Draait automatisch bij elke merge naar `master` en bij elke handmatige `workflow_dispatch`-run. Domeinnaam: `test.slpsoftware.nl` (SSL via certbot op de reverse-proxy-Pi). - **Productie** (geautomatiseerd, opt-in): via een eigen `build-production`- en `deploy-production`-job in `continuous_integration.yaml`, die `deploy.yaml` aanroepen met `environment: production`. In tegenstelling tot de testdeploy draait dit **niet** automatisch bij een push naar `master` — alleen wanneer je de workflow handmatig start via `workflow_dispatch` mét het `deploy_production`-vinkje aangevinkt. Dit is bewust: zo kan niemand per ongeluk productie deployen door simpelweg naar `master` te pushen. Reden voor een aparte `build-production`-job (in plaats van hetzelfde artifact als de testbuild te hergebruiken): `VITE_APP_ENV` is een build-time Vite-variabele, dus één bundel kan niet tegelijk als `test` én `production` getagd zijn in Sentry/analytics. Domeinnaam: `slpsoftware.nl` (SSL eveneens via certbot). Productie-nginx-voorbeeldconfiguratie: `nginx/production-nginx.conf.example` (vóór certbot) en `nginx/production-nginx.conf.post-certbot.example` (referentie, hoe het bestand er na certbot uitziet) — dekt alléén de react-frontend-site; de daadwerkelijke productieserver regelt op hetzelfde domein ook mail/iRedAdmin-proxying, wat buiten de scope van deze feature valt. Vereist eenmalig de Gitea-variable `DEPLOY_PATH_PRODUCTION` (zie `deployment-instructions.md`) — zonder deze faalt de upload. ## Automation Level Volledig geautomatiseerd voor de testomgeving: build, test, lint én upload naar de test-Pi gebeuren zonder handmatige tussenstap, zodra er gemerged wordt naar `master` (of handmatig getriggerd wordt). Productie is ook geautomatiseerd, maar alleen als bewuste, expliciete actie (handmatige `workflow_dispatch` met het `deploy_production`-vinkje) — nooit automatisch bij een push. ## Rollback Strategy Zie `rollback-plan.md` — voor de testomgeving kan een eerdere commit/branch opnieuw gebouwd en geüpload worden door de workflow opnieuw te triggeren. ## Secrets & Configuration Voor de testomgeving zijn de volgende Gitea Actions Secrets (repository-niveau) vereist: - `PI_MAIN_ADDRESS` — `192.168.1.103` (intern IP van de webserver-Pi) - `PI_MAIN_PORT` — `2224` - `PI_MAIN_USERNAME` — `webadmin` - `PI_MAIN_PASSWORD` — het SSH-wachtwoord van deze gebruiker Deze secrets heten bewust `PI_MAIN_*` in plaats van `PI_TEST_*`: alle webhosts gebruiken op dit moment dezelfde inloggegevens (dezelfde Pi), dus de naam is niet omgeving-specifiek. Mocht dat in de toekomst veranderen, dan worden alsnog omgeving-specifieke secrets geïntroduceerd. Dit is bewust wachtwoord-authenticatie (voor nu, zoals gekozen), zodat de testomgeving snel werkend is. Zie "Future Work" in `deployment-instructions.md` voor de overstap naar SSH-key-authenticatie. ## Resolved Item — Productie-deploy Geautomatiseerd `continuous_integration.yaml` bevat nu een `build-production`- en `deploy-production`-job, alleen actief bij een handmatige `workflow_dispatch`-run met het `deploy_production`-vinkje aangevinkt (zie "Environments" hierboven). Aangezien de webhost (Pi Main) dezelfde blijft als de testomgeving, worden de bestaande `PI_MAIN_*` secrets hergebruikt — pas dit pas aan naar omgeving-specifieke secrets als productie daadwerkelijk op een andere host komt. Domeinnaam (`slpsoftware.nl`) en SSL-aanpak (certbot/Let's Encrypt op de reverse-proxy-Pi) liggen al vast; zie `nginx/production-nginx.conf.example` / `nginx/production-nginx.conf.post-certbot.example` voor de voorbeeldconfiguratie (react-frontend-only, geen mail/iRedAdmin). **Voordat dit voor het eerst gebruikt wordt**, moet de Gitea-variable `DEPLOY_PATH_PRODUCTION` nog worden aangemaakt (zie `deployment-instructions.md`) — zonder deze faalt de upload. ## Verified Build Prerequisite Dit plan bouwt voort op de Build and Test-stage (`construction/build-and-test/build-and-test-summary.md`): `pnpm run build` produceert een statische `dist/`-bundel zonder server-side vereisten, geschikt om direct door nginx geserveerd te worden.