# Handmatige deploy naar Unraid (1 container, poort 1202) Voor als de bestaande deploy stuk is en je de code met de hand kopieert (zip/scp/SMB) in plaats van via `git clone`. Eindresultaat: **één** container met de naam `geointel`, bereikbaar op `http://192.0.2.10:1202`. --- ## 1. Kopiëren Kopieer de **volledige** map `C:\Projects\geointel` naar `/mnt/user/appdata/geointel` op de server. Verder niets uitzoeken. `.dockerignore` regelt de rest: `node_modules/`, `.git/`, `docs/`, `artifacts/` en testoutput gaan niet mee de build-context in, ook al staan ze in de map. Eén waarschuwing bij het overschrijven: laat `storage/`, `postgres-data/`, `backups/` en `models/` op de server **staan**. Dat is je bestaande data, en die staat niet in je Windows-map. Kopieer dus overschrijvend, niet met een "mirror"/"purge"-optie die bestanden aan de doelzijde weggooit. ```powershell # Vanaf Windows, veilig: kopieert en overschrijft, verwijdert niets aan de doelkant. robocopy C:\Projects\geointel \\192.0.2.10\appdata\geointel /E ``` --- ## 2. Rechten en regeleindes goedzetten Na een kopie via Windows zijn de execute-bits weg. Op de Unraid-shell: ```bash cd /mnt/user/appdata/geointel find . -name '*.sh' -exec sed -i 's/\r$//' {} + sed -i 's/\r$//' deploy/unraid/gosu-setpriv chmod +x deploy/unraid/*.sh scripts/*.sh deploy/unraid/gosu-setpriv ``` --- ## 3. `.env` aanmaken ```bash cd /mnt/user/appdata/geointel cp deploy/unraid/geointel.env.example .env nano .env ``` Verplicht aan te passen: - `GEOINTEL_POSTGRES_PASSWORD` — de deploy **weigert** te starten met een lege of standaardwaarde (`geointel`, `postgres`, `changeme`, `change-me-before-shared-use`). Gebruik hier dezelfde waarde als je vorige installatie, anders kan de bestaande PostGIS-data niet worden geopend. Controleer dat deze op de bestaande data wijzen: ```env GEOINTEL_FRONTEND_PORT=1202 GEOINTEL_STORAGE_PATH=/mnt/user/appdata/geointel/storage GEOINTEL_POSTGIS_DATA_PATH=/mnt/user/appdata/geointel/postgres-data GEOINTEL_MODELS_PATH=/mnt/user/appdata/geointel/models GEOINTEL_BACKUPS_PATH=/mnt/user/appdata/geointel/backups GEOINTEL_CORS_ORIGINS=https://geointel.example.com,http://geointel.example.com,http://localhost:1202,http://127.0.0.1:1202,http://192.0.2.10:1202 ``` Staat Nginx Proxy Manager voor poort 1202 op `geointel.example.com`, dan moet die hostname in `GEOINTEL_CORS_ORIGINS` staan — anders blokkeert de browser de API-calls vanaf het publieke adres. De backend doet geen host-validatie, dus verder is er niets nodig aan applicatiekant. De productie-image bevat altijd de gepinde AI-runtime. Inferentie zelf kan uitblijven totdat een lokaal, gevalideerd model beschikbaar is: ```env GEOINTEL_INSTALL_AI=true YOLO_ENABLED=true YOLO_DEVICE=cuda:0 YOLO_REQUIRE_CUDA=true YOLO_MODEL_PATH=/app/models/.pt ``` Laat `YOLO_ENABLED=false` zolang er geen geschikt modelbestand is. Het release-deployscript weigert bewust een GIS-only productie-image. --- ## 4. Login instellen De app slaat geen plaintext wachtwoord op: `.env` bevat alleen een pbkdf2_sha256-hash. Dit script maakt die hash plus een sessiegeheim en zet ze in `.env`: ```bash cd /mnt/user/appdata/geointel bash scripts/configure_operator_login.sh --username ITWorx --guest-access true ``` `--guest-access true` is nodig om de demo-ingang te behouden; zonder die vlag zet het script `GEOINTEL_GUEST_ACCESS_ENABLED=false`. Het script vraagt het wachtwoord tweemaal (je typt het niet zichtbaar en het komt niet in je shell-history), en zet: ```env GEOINTEL_AUTH_ENABLED=true GEOINTEL_AUTH_USERNAME=ITWorx GEOINTEL_AUTH_PASSWORD_HASH=pbkdf2_sha256$600000$... GEOINTEL_AUTH_SESSION_SECRET=<48 willekeurige tekens> GEOINTEL_GUEST_ACCESS_ENABLED=false ``` Gastentoegang wordt bewust uitgezet — met auth aan zou anders de publieke demo-ingang "Als gast verkennen" op de loginpagina blijven staan. Wil je die wel: `--guest-access true`. Wachtwoord later wijzigen: draai hetzelfde commando opnieuw en deploy. Er wordt dan ook een nieuw sessiegeheim gemaakt, dus openstaande browsersessies worden ongeldig. > Het wachtwoord dat je me in de chat gaf staat nu in die chatgeschiedenis. > Draai het script met een nieuw wachtwoord zodra de deploy staat. --- ## 5. Deployen ```bash cd /mnt/user/appdata/geointel docker compose -f docker-compose.unraid.yml config >/dev/null # syntaxcheck bash deploy/unraid/deploy-release.sh ``` Het script: 1. bindt het exacte huidige image-ID aan een unieke backup-specifieke `rollback-predeploy-*`-tag; 2. bouwt of hergebruikt de AI-candidate terwijl de huidige release beschikbaar blijft, legt het exacte lokale image-ID vast en maakt daarop SBOM- en Trivy-evidence; 3. controleert vóór het pauzeren de vrije ruimte en maakt vervolgens een byte-complete, SHA-256-geverifieerde database-, storage- en modelsnapshot in `/mnt/user/appdata/geointel/backups`; ongewijzigde bestanden mogen alleen vanuit een oudere geverifieerde backup worden gehardlinkt; 4. ruimt een eventueel achtergebleven Compose-stack op (ook de oude 3-container dev-stack die óók poort 1202 pakt); 5. start één container `geointel` met `-p 1202:80` en `--gpus all`; 6. bewijst een rollbackdump eerst in een geïsoleerde tijdelijke database, bewaart de oude productiedatabase als herstelpad en start pas daarna automatisch het image-ID dat cryptografisch in die pre-deploybackup staat. De eerste build duurt lang (PostGIS + GDAL + npm build). Volgende deploys hergebruiken de Docker-layercache. --- ## 6. Controleren ```bash docker ps --filter name=geointel # exact 1 regel verwacht curl -fsS http://127.0.0.1:1202/health/live curl -fsS http://127.0.0.1:1202/health/ready curl -fsS http://127.0.0.1:1202/api/v1/system/capabilities ``` Browser: `http://192.0.2.10:1202` Bij problemen: ```bash docker logs --tail 200 geointel ``` --- ## 7. Geretireerde dubbele projectmap De vroegere geneste mirror `C:\Projects\geointel\geointel` is geretireerd. De immutable Git-herkomst, niet-getrackte recoverybestanden en verificatiegrens staan in de private release-evidence buiten Git. Behandel die evidence als herstelreferentie; deze handleiding vraagt geen extra kopieer- of opruimactie. --- ## 8. Terugrollen ```bash cd /mnt/user/appdata/geointel bash deploy/unraid/rollback-dockerman-container.sh \ --backup-dir /mnt/user/appdata/geointel/backups/ \ --confirm-production-database-restore ``` Rollback hergebruikt dezelfde storage-paden, bewijst de geverifieerde dump eerst geïsoleerd, wisselt daarna databases via no-clobber namen en draait nooit een Alembic-downgrade. De oude productiedatabase blijft staan totdat een operator haar na controle expliciet opruimt. --- ## Wat er is aangepast om dit mogelijk te maken | Bestand | Aanpassing | |---|---| | `.dockerignore` | Sluit root-`node_modules`, `.git`, `docs/`, `artifacts/` en testoutput uit de build-context | | `deploy/unraid/deploy-release.sh` | `git rev-parse HEAD` crashte op een kopie zonder `.git`. Valt nu terug op `GEOINTEL_BUILD_SHA`, een `RELEASE_SHA`-bestand of een content-hash van de broncode | | `deploy/unraid/deploy-release.sh` | Smoke-scripts worden op bestaan getest in plaats van op de execute-bit, die bij een Windows-kopie verloren gaat | | `deploy/unraid/run-dockerman-container.sh` | Ruimt expliciet zowel `docker-compose.yml` (3 containers) als `docker-compose.unraid.yml` op, zodat poort 1202 gegarandeerd vrij is | | `deploy/unraid/geointel.env.example` | `COMPOSE_FILE=docker-compose.unraid.yml`, zodat een kaal `docker compose up -d` nooit per ongeluk de 3-container dev-stack start | | `scripts/configure_operator_login.sh` | Nieuw. Zet de operator-login in `.env` met een correcte pbkdf2_sha256-hash (600.000 iteraties, identiek aan `AuthService.hash_password`) en een vers sessiegeheim |