15 KiB
Productie uitrollen op de Synology (S6)
De buildworkflow bouwt, test en publiceert automatisch. Productie verandert
alleen via Actions → Deploy production → Run workflow of Rollback
production. Start beide vanaf main; de workflows verschijnen na de merge.
Tot S16 is geïmplementeerd kan iedere deployment, retry, rollback of automatisch herstel alle applicatiegegevens wissen. Informeer de launching partner vooraf. Een onderbroken berekening moet opnieuw worden gestart. Een herstelde applicatieversie herstelt geen verloren gegevens.
Eenmalige DSM-inrichting
Gebruik je bestaande beheeraccount voor deze stappen:
- Maak onder Configuratiescherm → Gebruiker en groep → Gebruiker → Maken
het account
agiledancers-deploymet een uniek sterk wachtwoord. Voeg het toe aan administrators: DSM vereist deze groep voor SSH. Het is daardoor een beheerder, geen beperkt bestandsaccount. - Bij Gedeelde mapmachtigingen:
dockerop Lezen/Schrijven,homesongewijzigd, overige mappen op Geen toegang.gitis niet nodig: deployment gebruikt de Gitea-API en registry. Blokkeerhomesniet, omdat dit ook de eigen thuismap kan blokkeren. - De toepassingen onder Toegangsmachtigingen toewijzen zijn niet nodig en mogen op Weigeren. Gebruik je eigen beheeraccount voor DSM. Deployment gebruikt SSH-shellopdrachten, geen SFTP, rsync of bestandsdeling.
- Schakel onder Gebruiker en groep → Geavanceerd de gebruikersbasismapservice in als deze uitstaat.
- Schakel Terminal en SNMP → Terminal → SSH-service inschakelen in. De maintainer heeft SSH-poort 22 bevestigd. Beperk toegang tot mini-pc/LAN/VPN; configureer geen internet-portforwarding.
- Controleer dat Container Manager/Docker draait, dat Docker Compose v2,
curl,timeoutmet-kenshbeschikbaar zijn. Op de NAS is geen Java, Python of Git nodig. Controleer het Docker-pad, doorgaans/usr/local/bin/docker.
Map- en toepassingsrechten vormen geen beveiligde isolatie voor een account met beheerder-/Dockerrechten. De runner voert ook vertrouwde repositorycode uit. Geef alleen vertrouwde beheerders schrijftoegang tot workflows en credentials.
Bronnen: SSH op DSM, sleutelaanmelding en basismappen, maprechten.
SSH-sleutel en hostkey
Maak op de mini-pc een aparte sleutel buiten de repository. De lege passphrase maakt niet-interactieve uitvoering mogelijk; behandel de private sleutel als secret.
ssh-keygen -t ed25519 -f "$HOME/.config/agiledancers-runner/s6-deploy-key" -N '' -C agiledancers-production
ssh-copy-id -i "$HOME/.config/agiledancers-runner/s6-deploy-key.pub" -p 22 agiledancers-deploy@192.168.2.28
Genereer niet opnieuw als de sleutel al bestaat. De implementatiesessie heeft deze dedicated sleutel op de mini-pc aangemaakt. De gebruiker installeert de publieke sleutel via een eigen interactieve terminal; deel geen wachtwoorden.
Controleer de serverfingerprint via een reeds vertrouwde beheerverbinding, tegen
/etc/ssh/ssh_host_ed25519_key.pub. Een keyscan alleen bewijst de serveridentiteit
niet. Bewaar de geverifieerde known_hosts-regel; bij een andere poort gebruikt
die [host]:poort. De helper vereist StrictHostKeyChecking=yes, gebruikt alleen
de dedicated sleutel en negeert SSH-agent en lokale SSH-configuratie.
Op de NAS: eigen ~/.ssh mode 700, authorized_keys mode 600, juiste eigenaar,
thuismap niet schrijfbaar voor andere gebruikers. De public-keyregel kan worden
beperkt met de werkelijke vaste mini-pc-IP en zonder forwarding/TTY:
from="<mini-pc-LAN-IP>",no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-pty ssh-ed25519 <public-key> agiledancers-production
Als de sleutel na ssh-copy-id nog wordt geweigerd door ruime DSM-basismaprechten,
voer dan eenmaal met wachtwoordauthenticatie uit als dit account:
chmod go-w "$HOME"
chmod 700 "$HOME/.ssh"
chmod 600 "$HOME/.ssh/authorized_keys"
Productiemap en Dockerrechten
Controleer het volume: /volume1/docker/agiledancers-production is een voorbeeld,
geen vastgestelde locatie. Maak de map als deploymentaccount, mode 700, met
dat account als eigenaar. Houd deze stack gescheiden van Gitea en andere projecten.
Kopieer deploy/production.env.example naar <productiemap>/production.env, mode
600. Stel de private NAS-IP, vrije frontendpoort (voorbeeld 8088), absolute
Docker-locatie en DOCKER_CONFIG in. Gebruik een eigen docker-auth-submap.
Alleen de frontend bindt aan de private IPv4; de backend krijgt geen hostpoort.
De Docker-projectnaam is vast agiledancers-production.
Als Docker sudo vereist, laat een beheerder met visudo een afzonderlijke
sudoers-regel installeren en valideren, met het gecontroleerde Docker-pad:
agiledancers-deploy ALL=(root) NOPASSWD: /usr/local/bin/docker
Dit staat alleen dat executable toe, maar Dockerbeheer geeft in de praktijk
rootmogelijkheden. Gebruik geen NOPASSWD: ALL, wereldschrijfbare Docker-socket
of wachtwoord in de workflow. De helper gebruikt sudo -n. Als Docker al direct
toegankelijk is voor het account, stel DOCKER_SUDO=0 in.
Provision apart een pull-only Gitea-packagecredential. Log als deploymentaccount op de NAS in, via de interactieve wachtwoordprompt:
mkdir -p /volume1/docker/agiledancers-production/docker-auth
chmod 700 /volume1/docker/agiledancers-production/docker-auth
sudo -n /usr/local/bin/docker --config /volume1/docker/agiledancers-production/docker-auth login 127.0.0.1:3000 --username <pull-account>
sudo -n /usr/local/bin/docker compose version
sudo -n /usr/local/bin/docker info --format '{{.OSType}}/{{.Architecture}}'
Als DSM geen visudo bevat, is deploy/enable-docker.sh het eenmalige alternatief.
Kopieer het naar de eigen NAS-thuismap en voer het daar met sudo uit. Het maakt
uitsluitend de bovengenoemde regel, controleert die door als deploymentaccount
Docker te starten en verwijdert een nieuwe regel als die controle faalt. Een
afwijkende bestaande regel wordt niet overschreven. De implementatiesessie heeft
deze stap op de NAS uitgevoerd; Docker rapporteert linux/x86_64.
Pas paden aan voor de echte configuratie. De bevestigde NAS-Dockerdaemon staat
HTTP-registryverkeer alleen op loopback toe. Gebruik daarom vanaf die NAS
127.0.0.1:3000: dezelfde Gitea-registry en gepubliceerde SHA-images, zonder een
daemonherstart die Gitea en Kimai zou onderbreken. De mini-pc blijft naar
192.168.2.28:3000 publiceren. Deploymentrecords bevatten de op de NAS bruikbare
loopback-digestreferenties. Authenticatie-/netwerkfouten zijn deploymentfouten.
Gitea-configuratie
Stel onder repository Settings → Actions in:
| Soort | Naam | Inhoud |
|---|---|---|
| Variabele | DEPLOY_HOST |
Private NAS-IP/hostnaam, passend bij known_hosts |
| Variabele | DEPLOY_USER |
agiledancers-deploy |
| Variabele | DEPLOY_SSH_PORT |
22 |
| Variabele | DEPLOY_DIRECTORY |
Absolute productiemap |
| Variabele | DEPLOY_REGISTRY |
127.0.0.1:3000, de NAS-lokale alias van dezelfde registry |
| Secret | DEPLOY_SSH_KEY |
Volledige private sleutel, inclusief begin/eindregels |
| Secret | DEPLOY_KNOWN_HOSTS |
Onafhankelijk geverifieerde NAS-hostkey-regel |
| Secret | RELEASE_TOKEN |
Apart Gitea-token voor Actions lezen en Git-tags maken |
Het releaseaccount heeft repositorylees-/schrijfrechten en Actions-metadatatoegang
nodig (write:repository op deze Gitea). Het NAS-registrycredential is apart en
heeft alleen de noodzakelijke package-leestoegang. Hergebruik de publicatie-PAT
niet voor deployment. Bewaar secrets buiten Git en logs.
De setuphelper kan deze configuratie en de productiemap zonder containerstart
inrichten. Bewaar admin-token, s6-release-token, s6-pull-token en de private
s6-deploy-key als owner-only bestanden (mode 600) in
~/.config/agiledancers-runner/. Gebruik de eerder vertrouwde NAS-hostkey in
~/.ssh/known_hosts en voer uit:
java ci/Ci.java configure-deployment
Defaults zijn de bevestigde NAS/account/SSH-poort, repository
wanjakrah/agiledancers, productiemap /volume1/docker/agiledancers-production,
NAS-IP-binding 192.168.2.28 en frontendpoort 8088. De helper controleert een
geslaagde main-build, weigert een bezette poort bij eerste inrichting, bewaart
bestaande productieconfiguratie en controleert de aparte registry-login voordat
Gitea-secrets/variabelen worden gezet. Er wordt geen release/tag gemaakt en geen
container vervangen. Variabelen met de namen uit bovenstaande tabel en
DEPLOY_BIND_IP, DEPLOY_FRONTEND_PORT, PULL_USER en de credential-*_FILE-
paden kunnen de defaults expliciet vervangen.
Bescherm release-tags v* in Gitea en beperk tagcreatie tot de releasebeheerder.
De helper maakt alleen nieuwe tags; hij verplaatst of verwijdert ze nooit. Laat
registry-cleanup de images van huidig/vorig niet verwijderen. Gebruik geen
algemene Docker-image/volume-prune als onderhoud van deze stack.
Nieuwe release, retry en rollback
- Merge naar
mainen wacht op een geslaagde Build, test and publish voor die SHA, inclusief imagepublicatie. - Open Deploy production → Run workflow, branch
main, modenew, keuzepatch,minorofmajor. Laat het versieveld leeg. De eerste release isv1.0.0; daarna telt de hoogste bestaande release-tag, inclusief mislukte deployments. Minor/major zetten de lagere componenten op nul. - De workflow toont versie/SHA. De immutable annotated Git-tag wordt na imagevoorbereiding, vóór vervanging gemaakt en blijft bij falen bestaan. Een tag bewijst geen succesvolle productiedeployment.
- Gebruik mode
retrymet een bestaande tag om dezelfde SHA/versie opnieuw uit te rollen. De incrementkeuze wordt genegeerd: Gitea toont alle velden, ook wanneer ze voor de gekozen mode niet relevant zijn. Een retry mag afwijken van huidig main, maar geen nieuwere succesvolle release verdringen. - Rollback production → Run workflow → main herstelt de vorige succesvolle release zonder versie/tag. Na succes wisselen huidig/vorig om; nogmaals rollback kan dus terugschakelen. De hoogste succesvolle versie blijft bewaard.
De NAS-lock omvat alle modes en versieallocatie. Een gelijktijdige run faalt
zichtbaar. Gitea 1.25 negeert workflow-concurrency; de serverlock is leidend.
Main wordt direct vóór vervanging opnieuw gecontroleerd. Zodra vervanging start,
wordt de gepinde versie afgemaakt of hersteld. Branchbuilds rollen niets uit.
Checks en operationele state
De helper haalt beide SHA-images terug, controleert revisie/platform en legt
registry-digests vast. Compose gebruikt die digests, nooit de bewegende main-tag.
De recovery-images worden eveneens vooraf gecontroleerd. Binnen vijf minuten
moeten backend-readiness, frontendpagina, GET /api/dance-schools via de
gepubliceerde frontendpoort en containeridentiteit slagen. Deze checks schrijven
geen gebruikersdata. De frontend herstart ook om de nieuwe backend-IP te resolven.
De productiemap bevat:
state.json: atomisch geschreven huidig/vorig en hoogste succesvolle versie. Redeployment van dezelfde versie behoudt de afzonderlijke rollbackversie.releases/<attempt>/: behouden Compose- en digest-/versieconfiguratie.pending.json: kandidaat en vorige state, vóór iedere vervanging geschreven.deploy.lock/owner: unieke run/poging;operation/markeert een actieve vervanging op de NAS.history/: pogingjournalen en uitkomsten; niet opruimen tijdens een release.
Een ongezonde kandidaat herstelt automatisch de vorige succesvolle release en blijft een mislukte workflow. Bij de eerste release zonder voorganger, mislukt herstel, runner/SSH-onderbreking of onduidelijke statecommit blijven journal en lock staan. Nieuwe runs weigeren dan wijzigingen. Remote opdrachten hebben ook op de NAS een timeout; herstel overlapt geen nog actieve vervanging. Geen eindeloze herstelpogingen.
Download artifact deployment-<run>-<attempt> of rollback-<run>-<attempt> voor
log, uitkomst, versie/SHA/digests en beschikbare foutdiagnostiek. Retentie is
veertien dagen; serverinstellingen mogen dit niet inkorten. Log geen environment,
Docker-authconfig of volledige container-inspect met eventuele secrets.
Handmatig herstel
Gebruik een vertrouwde beheerverbinding. Verwijder nooit alleen de lock om een nieuwe release door te drukken.
-
Annuleer de betrokken Gitea-run. Controleer op de NAS dat geen SSH-deployment, timeout, Compose-vervanging of herstel van deze poging meer actief is. Onderzoek
deploy.lock/operation; wacht op de timeout of beëindig alleen de geverifieerde vastgelopen deploymentprocessen. -
Bewaar state, pending journal, history en containerlogs. Vergelijk de kandidaat, de
before-state en werkelijke images. De statecommit kan al zijn uitgevoerd terwijl de runner geen antwoord ontving. -
Behoud een aantoonbaar gezonde kandidaat met overeenkomende state. Anders: herstel
before.currentuit het journal met de behouden Compose-/env-bestanden, dezelfde projectnaam en digest-images. Start geen tweede stack. -
Voer dezelfde checks uit. Vanaf de checkout op de mini-pc kun je het echte controlescript uitvoeren met bestaande lockowner en gekozen release-directory:
ssh -i <private-key-path> -p <ssh-port> <deploy-user>@<nas> \ 'timeout -k 5 300 sh -s -- apply <production-directory> <lock-owner> <release-directory-id>' < deploy/remote.shGebruik de eerder gepinde hostkey en gecontroleerde waarden uit het journal. Verwijder een achtergebleven lege
operation/alleen als stap 1 heeft bewezen dat de oude operatie gestopt is. -
Bij herstel van de oude release: herstel ook de volledige
before-state atomisch, inclusief high-watermark en rollbackdoel. Bij een mislukte eerste release: stop de defecte stack en behoud de lege succesvolle state. Verwijder geen volumes of release-tags. -
Noteer het herstel in history, archiveer het opgeloste journal en verwijder daarna pas de lockowner en lege lockdirectory. Start vervolgens een retry. Laat de blokkade staan als gezondheid of state onduidelijk is.
Na S16 en lokale verificatie
S16 blokkeert S6 niet. Zodra S16 is ingevoerd, moeten database/volumes buiten de vervangbare containers blijven en saved data zowel deployment als rollback overleven. De gewone procedure vereist dan databasecompatibiliteit met de vorige applicatieversie. Plan incompatibele migraties apart: imageherstel maakt geen migratie ongedaan. Backup/restore blijven S17-werk.
java ci/Ci.java test
java ci/Ci.java release-test
sh -n deploy/remote.sh
mvn -N -Dformat.mode=check exec:exec@format
De buildworkflow voert beide Java-testsuites uit vóór publicatie. Release-tests
wijzigen geen productie, registry of tags. Leg echte NAS-/Gitea-bewijzen vast in
docs/s6-validation.md; configuratie en lokale tests alleen voltooien S6 niet.