fix(release): make deployment backup and rollback immutable

This commit is contained in:
Jens
2026-08-30 06:00:43 +02:00
parent a0884d64c9
commit c272220277
47 changed files with 3035 additions and 430 deletions
+30 -22
View File
@@ -106,27 +106,25 @@ customer or operational data. Deploy a separate demo container and storage
root for public or recruiter-facing access.
The repository deploy scripts run the same flow automatically. They validate
the Compose reference, preserve the current image as
`geointel-all-in-one:previous`, build an immutable `<commit-sha>-ai` or
`<commit-sha>-gis` tag plus `latest`, install the DockerMan metadata and start
the immutable image. An existing matching tag is reused, never rebuilt. A
failed start, live migration smoke or browser/API smoke automatically attempts
the previous image without changing the configured PostGIS or storage paths.
the Compose reference, preserve the current image under a unique
backup-specific `rollback-predeploy-*` tag, build the immutable production
`<commit-sha>-ai` tag plus `latest`, attest its exact local image ID, generate
an SBOM and enforce the Trivy policy before starting that same ID. An existing
matching tag is reused, never rebuilt. A failed start, live migration smoke or
browser/API smoke automatically attempts the previous image without changing
the configured PostGIS or storage paths.
`scripts/deploy_tower.sh` and `scripts/deploy_tower.ps1` source the remote
`.env` before building the image. That means `GEOINTEL_INSTALL_AI=true` in
`/mnt/user/appdata/geointel/.env` is enough for the automatic deploy to build
the AI-enabled image. Set `GEOINTEL_INSTALL_AI` in the local shell or pass
`-InstallAi true/false` to the PowerShell wrapper only when you intentionally
want to override the remote `.env` for that deploy.
`.env` before building the image. Production deployment requires
`GEOINTEL_INSTALL_AI=true`; an explicit false value fails closed before the
image or running container is replaced.
Database credentials are runtime configuration, not image metadata. The
all-in-one image does not bake `GEOINTEL_POSTGRES_PASSWORD` into the Dockerfile;
set it through `.env`, the Unraid template or `docker run -e`.
AI dependencies are opt-in. Leave `GEOINTEL_INSTALL_AI=false` for the default
GIS-only image. Set `GEOINTEL_INSTALL_AI=true`, mount models through
`GEOINTEL_MODELS_PATH` and configure `YOLO_ENABLED=true` plus
Production images always include the pinned AI dependencies. Mount models
through `GEOINTEL_MODELS_PATH` and configure `YOLO_ENABLED=true` plus
`YOLO_MODELS_DIR=/app/models` and `YOLO_MODEL_PATH=/app/models/<model>.pt` only
when you have a local model file.
The AI-enabled image installs PyTorch/Ultralytics plus the native OpenCV runtime
@@ -264,7 +262,8 @@ git reset --hard origin/main
bash deploy/unraid/deploy-release.sh
```
The equivalent low-level build remains available for debugging:
The equivalent low-level GIS-only build remains available only for local
debugging; it is not a production deployment path:
```bash
docker build --build-arg GEOINTEL_INSTALL_AI=${GEOINTEL_INSTALL_AI:-false} -f deploy/unraid/Dockerfile.all-in-one -t geointel-all-in-one:latest .
@@ -305,20 +304,27 @@ bash scripts/verify_release_upgrade_smoke.sh \
Return to the image that was active immediately before the latest deployment:
```bash
bash deploy/unraid/rollback-dockerman-container.sh
bash deploy/unraid/rollback-dockerman-container.sh \
--backup-dir /mnt/user/appdata/geointel/backups/<predeploy-release-id> \
--confirm-production-database-restore
```
For an older retained commit, select its immutable tag explicitly:
```bash
GEOINTEL_ROLLBACK_IMAGE=geointel-all-in-one:<commit-sha>-ai \
bash deploy/unraid/rollback-dockerman-container.sh
bash deploy/unraid/rollback-dockerman-container.sh \
--backup-dir /mnt/user/appdata/geointel/backups/<matching-predeploy-release-id> \
--confirm-production-database-restore
```
Rollback reuses the configured PostGIS and storage mounts and never runs an
Alembic downgrade. If a future release has a backward-incompatible migration,
restore its verified pre-release backup instead of forcing an older app
against a newer schema.
Rollback restores and verifies the selected dump in an isolated proof database
before any production replacement. It then swaps database names, retains the
pre-restore production database for operator recovery, reuses the configured
storage mount and never runs an Alembic downgrade or an older app against an
unknown newer schema. Remove the retained recovery database and old backup
directories only in a separately reviewed operator retention step; deployment
never deletes them automatically.
The configured upload limit is shared by FastAPI and the generated nginx
runtime configuration. Values outside `1..2048` MiB are rejected before the
@@ -339,7 +345,9 @@ docker exec geointel python /app/scripts/cleanup_storage_artifacts.py
```
The full backup, confirmation, candidate-limit and apply sequence is in
`docs/DATA_OPERATIONS_RUNBOOK.md`. GeoIntel installs no automatic cleanup
`docs/DATA_OPERATIONS_RUNBOOK.md`. Apply moves bytes to protected,
checksum-bound quarantine rather than deleting them; a separate confirmed
restore command reverses the move. GeoIntel installs no automatic cleanup
schedule.
## Safe cleanup