UI fixing
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-28 04:44:16 +02:00
parent c76a746cd7
commit 19cf2b5211
8 changed files with 503 additions and 10 deletions
+210
View File
@@ -0,0 +1,210 @@
# 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.168.10.150: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/`, de dubbele
`geointel/`-map, `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.168.10.150\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.itworx.tech,http://geointel.itworx.tech,http://localhost:1202,http://127.0.0.1:1202,http://192.168.10.150:1202
```
Staat Nginx Proxy Manager voor poort 1202 op `geointel.itworx.tech`, 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.
Voor GPU-inferentie (optioneel, kan ook later):
```env
GEOINTEL_INSTALL_AI=true
YOLO_ENABLED=true
YOLO_DEVICE=cuda:0
YOLO_REQUIRE_CUDA=true
YOLO_MODEL_PATH=/app/models/<jouw-model>.pt
```
Laat `GEOINTEL_INSTALL_AI=false` staan als je eerst gewoon wilt dat de app
draait — dat scheelt een paar GB aan PyTorch-lagen in de build.
---
## 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 jens@itworx.tech --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=jens@itworx.tech
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. ruimt een eventueel achtergebleven Compose-stack op (ook de oude
3-container dev-stack die óók poort 1202 pakt);
2. bewaart de huidige image als `geointel-all-in-one:previous`;
3. bouwt `deploy/unraid/Dockerfile.all-in-one`;
4. start één container `geointel` met `-p 1202:80` en `--gpus all`;
5. rolt automatisch terug naar `:previous` als de healthcheck of smoke faalt.
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.168.10.150:1202`
Bij problemen:
```bash
docker logs --tail 200 geointel
```
---
## 7. Belangrijk: dubbele projectmap lokaal
In `C:\Projects\geointel` staat een tweede, volledige kopie van het project
onder `C:\Projects\geointel\geointel\`. Die bevat dezelfde bestanden en
dezelfde datum, maar staat buiten git. Zolang die er staat:
- wordt de Docker build-context onnodig verdubbeld;
- weet je bij het bewerken van bijvoorbeeld `docker-compose.unraid.yml` niet
welke versie je te pakken hebt.
`.dockerignore` sluit hem nu uit, maar ruim hem op zodra je zeker weet dat er
niets unieks in staat. Vergelijk eerst:
```powershell
robocopy C:\Projects\geointel\geointel C:\Projects\geointel /L /E /NJH /NJS /NDL /XF *.pyc
```
Regels die als `New File` verschijnen bestaan alleen in de kopie.
---
## 8. Terugrollen
```bash
cd /mnt/user/appdata/geointel
bash deploy/unraid/rollback-dockerman-container.sh
```
Rollback hergebruikt dezelfde PostGIS- en storage-paden en draait nooit een
Alembic-downgrade.
---
## Wat er is aangepast om dit mogelijk te maken
| Bestand | Aanpassing |
|---|---|
| `.dockerignore` | Sluit root-`node_modules`, de dubbele `geointel/`-map, `.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 |
+54 -3
View File
@@ -32,7 +32,58 @@ if ! [[ "$GEOINTEL_APP_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]
echo "Invalid semantic version in VERSION: ${GEOINTEL_APP_VERSION}" >&2
exit 2
fi
GEOINTEL_BUILD_SHA="$(git rev-parse HEAD)"
resolve_build_sha() {
# 1. Explicit override wins.
if [ -n "${GEOINTEL_BUILD_SHA:-}" ]; then
printf '%s' "$GEOINTEL_BUILD_SHA"
return 0
fi
# 2. Real git checkout.
if command -v git >/dev/null 2>&1 && git rev-parse --git-dir >/dev/null 2>&1; then
git rev-parse HEAD
return 0
fi
# 3. Manually copied tree with a RELEASE_SHA marker file.
if [ -f RELEASE_SHA ]; then
tr -d '[:space:]' < RELEASE_SHA
return 0
fi
# 4. Manually copied tree without git: derive a stable content hash so
# an unchanged redeploy reuses the existing immutable image tag.
if command -v sha1sum >/dev/null 2>&1; then
local tree_hash
tree_hash="$(
find backend frontend deploy scripts fixtures VERSION \
-type f \
! -path '*/node_modules/*' \
! -path '*/__pycache__/*' \
! -path '*/.pytest_cache/*' \
! -name '*.pyc' \
-print0 2>/dev/null \
| sort -z \
| xargs -0 sha1sum 2>/dev/null \
| sha1sum \
| cut -c1-40
)" || tree_hash=""
if [ -n "$tree_hash" ]; then
printf '%s' "$tree_hash"
return 0
fi
fi
# 5. Last resort: unique per deploy.
printf 'manual%s' "$(date -u +%Y%m%d%H%M%S)"
}
GEOINTEL_BUILD_SHA="$(resolve_build_sha)"
if [ -z "$GEOINTEL_BUILD_SHA" ]; then
echo "Could not determine a build revision for this deployment." >&2
exit 2
fi
echo "Build revision: ${GEOINTEL_BUILD_SHA}"
GEOINTEL_BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
GEOINTEL_IMAGE_REPOSITORY="${GEOINTEL_IMAGE_REPOSITORY:-geointel-all-in-one}"
if [ "$GEOINTEL_INSTALL_AI" = "true" ]; then
@@ -138,14 +189,14 @@ if ! start_image "$GEOINTEL_RELEASE_IMAGE"; then
exit 1
fi
if [ -x scripts/live_migration_smoke.sh ]; then
if [ -f scripts/live_migration_smoke.sh ]; then
if ! LIVE_SMOKE_CONTAINER=geointel bash scripts/live_migration_smoke.sh; then
rollback_previous || true
exit 1
fi
fi
if [ -x scripts/verify_browser_runtime.sh ]; then
if [ -f scripts/verify_browser_runtime.sh ]; then
if ! bash scripts/verify_browser_runtime.sh "$FRONTEND_URL"; then
rollback_previous || true
exit 1
+9 -1
View File
@@ -1,6 +1,11 @@
# GeoIntel Unraid all-in-one environment template.
# Copy this file to /mnt/user/appdata/geointel/.env and edit values there.
# GeoIntel runs as ONE container. This makes a bare `docker compose ...` in this
# directory use the single-container file instead of the multi-container
# development stack in docker-compose.yml.
COMPOSE_FILE=docker-compose.unraid.yml
# Browser URL: http://<unraid-ip>:<GEOINTEL_FRONTEND_PORT>
GEOINTEL_FRONTEND_PORT=1202
@@ -24,7 +29,8 @@ GEOINTEL_POSTGRES_USER=geointel
GEOINTEL_POSTGRES_PASSWORD=change-me-before-shared-use
# Browser origins allowed when directly calling the backend API.
GEOINTEL_CORS_ORIGINS=http://localhost:1202,http://127.0.0.1:1202,http://192.168.10.150:1202
# Neem hier ook de publieke hostname op zodra Nginx Proxy Manager ervoor staat.
GEOINTEL_CORS_ORIGINS=https://geointel.itworx.tech,http://geointel.itworx.tech,http://localhost:1202,http://127.0.0.1:1202,http://192.168.10.150:1202
# Upload guard in MiB. The same 1-2048 limit is applied by nginx and FastAPI.
GEOINTEL_MAX_UPLOAD_MB=500
@@ -43,6 +49,8 @@ GEOINTEL_AUTH_SESSION_TTL_SECONDS=43200
# Guest access is enabled by default whenever operator authentication is active.
# It opens the seeded GeoIntel demo in a temporary, API-enforced restricted
# session. Set this to false on installations containing private project data.
# LET OP: scripts/configure_operator_login.sh zet dit op false tenzij je
# expliciet --guest-access true meegeeft.
GEOINTEL_GUEST_ACCESS_ENABLED=true
GEOINTEL_GUEST_DISPLAY_NAME=Gast
GEOINTEL_GUEST_SESSION_TTL_SECONDS=7200
+8 -1
View File
@@ -269,7 +269,14 @@ migrate_compose_volume_if_needed() {
validate_runtime_config
install_dockerman_metadata
docker compose down --remove-orphans || true
# GeoIntel runs as ONE container started by docker run below.
# Tear down any leftover Compose stack first, including the multi-container
# development stack (db + backend + frontend) that also claims port 1202.
for compose_file in docker-compose.yml docker-compose.unraid.yml; do
if [ -f "$compose_file" ]; then
docker compose -f "$compose_file" down --remove-orphans || true
fi
done
if docker ps -a --format '{{.Names}}' | grep -qx geointel; then
docker rm -f geointel >/dev/null 2>&1 || true