246 lines
9.6 KiB
Markdown
246 lines
9.6 KiB
Markdown
# GeoIntel Unraid all-in-one container
|
|
|
|
GeoIntel can run on Unraid as one DockerMan-native container.
|
|
|
|
Inside that single container:
|
|
|
|
- embedded PostGIS stores the application database
|
|
- Alembic migrations run at startup
|
|
- FastAPI runs on internal `127.0.0.1:8000`
|
|
- nginx serves the React/MapLibre frontend on container port `80`
|
|
- nginx proxies `/api` and `/health` to the internal backend
|
|
|
|
The browser entrypoint is:
|
|
|
|
```text
|
|
http://<unraid-ip>:${GEOINTEL_FRONTEND_PORT}
|
|
```
|
|
|
|
The app icons are served from the same container:
|
|
|
|
```text
|
|
http://<unraid-ip>:${GEOINTEL_FRONTEND_PORT}/geointel-icon.svg
|
|
http://<unraid-ip>:${GEOINTEL_FRONTEND_PORT}/geointel-icon.png
|
|
```
|
|
|
|
## Files
|
|
|
|
- `docker-compose.unraid.yml`: config validation reference for the all-in-one image.
|
|
- `deploy/unraid/Dockerfile.all-in-one`: builds the single container.
|
|
- `deploy/unraid/all-in-one-start.sh`: starts embedded PostGIS, backend and nginx.
|
|
- `deploy/unraid/run-dockerman-container.sh`: starts/replaces the running container with DockerMan labels and editable Unraid metadata.
|
|
- `deploy/unraid/nginx-all-in-one.conf`: frontend and API proxy config for one container.
|
|
- `deploy/unraid/geointel.env.example`: copy to `.env` and edit ports/paths.
|
|
- `deploy/unraid/geointel-unraid-template.xml`: Unraid/DockerMan metadata for editable fields.
|
|
- `deploy/unraid/geointel-icon.svg`: frontend favicon source.
|
|
- `deploy/unraid/geointel-icon.png`: DockerMan/Unraid icon source.
|
|
- `frontend/public/geointel-icon.svg`: frontend-served SVG icon.
|
|
- `frontend/public/geointel-icon.png`: frontend-served PNG icon.
|
|
|
|
The Tower deploy scripts also copy the editable DockerMan template to:
|
|
|
|
```text
|
|
/boot/config/plugins/dockerMan/templates-user/my-geointel.xml
|
|
```
|
|
|
|
and copy the PNG icon to:
|
|
|
|
```text
|
|
/boot/config/plugins/dockerMan/images/geointel-icon.png
|
|
```
|
|
|
|
The template name is `geointel` so it matches the running all-in-one container name. If the Unraid Docker page was already open, refresh it after deploy so DockerMan reloads the template/icon metadata.
|
|
|
|
`docker-compose.unraid.yml` also applies DockerMan labels to the running container:
|
|
|
|
```text
|
|
net.unraid.docker.managed=dockerman
|
|
net.unraid.docker.webui=http://[IP]:[PORT:80]/
|
|
net.unraid.docker.icon=/boot/config/plugins/dockerMan/images/geointel-icon.png
|
|
```
|
|
|
|
These labels are required because a plain Compose container can run correctly while still missing the normal Unraid edit/icon controls.
|
|
|
|
## First setup from the repo
|
|
|
|
From the Unraid shell:
|
|
|
|
```bash
|
|
cd /mnt/user/appdata
|
|
git clone gitea-widefrog:NuklearRabbit/geointel.git geointel
|
|
cd /mnt/user/appdata/geointel
|
|
cp deploy/unraid/geointel.env.example .env
|
|
nano .env
|
|
docker compose -f docker-compose.unraid.yml config
|
|
docker build --build-arg GEOINTEL_INSTALL_AI=${GEOINTEL_INSTALL_AI:-false} -f deploy/unraid/Dockerfile.all-in-one -t geointel-all-in-one:latest .
|
|
bash deploy/unraid/run-dockerman-container.sh
|
|
```
|
|
|
|
The repository deploy scripts run the same flow automatically. They validate the Compose reference, build the image with the `GEOINTEL_INSTALL_AI` build arg, install the DockerMan template/icon, remove any old Compose-owned `geointel` container, preserve/migrate the PostGIS data path and start the final container with DockerMan labels.
|
|
|
|
`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.
|
|
|
|
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
|
|
`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
|
|
libraries needed for Ultralytics imports; it still never downloads model weights.
|
|
The documented CPU runtime installs pinned `torch==2.13.0` and
|
|
`torchvision==0.28.0` from `https://download.pytorch.org/whl/cpu`, avoiding the
|
|
unused CUDA runtime wheels included by the general Linux package index. The
|
|
Dockerfile copies dependency metadata before backend source, so normal code-only
|
|
redeploys can reuse the expensive dependency layer.
|
|
`YOLO_CONFIG_DIR` defaults to `/app/storage/ultralytics`, a writable persistent
|
|
path, so Ultralytics settings do not fall back to root user config directories.
|
|
|
|
To safely configure an existing local YOLO model on Tower, place one supported
|
|
model file (`.pt`, `.onnx` or `.engine`) under:
|
|
|
|
```text
|
|
/mnt/user/appdata/geointel/models
|
|
```
|
|
|
|
Then run a dry-run first:
|
|
|
|
```bash
|
|
cd /mnt/user/appdata/geointel
|
|
python scripts/configure_yolo_model.py \
|
|
--models-dir /mnt/user/appdata/geointel/models \
|
|
--env-file .env
|
|
```
|
|
|
|
Apply only after the selected host and container paths are correct:
|
|
|
|
```bash
|
|
python scripts/configure_yolo_model.py \
|
|
--models-dir /mnt/user/appdata/geointel/models \
|
|
--env-file .env \
|
|
--apply
|
|
bash deploy/unraid/run-dockerman-container.sh
|
|
```
|
|
|
|
If multiple model files are present, add `--model-file /mnt/user/appdata/geointel/models/<name>.pt`.
|
|
The helper does not download weights, does not load a model and does not run
|
|
inference; it only updates the env file for the mounted local model.
|
|
|
|
Validate liveness, dependency readiness and the canonical API:
|
|
|
|
```bash
|
|
curl -fsS "http://192.168.10.150:${GEOINTEL_FRONTEND_PORT:-1202}/health/live"
|
|
curl -fsS "http://192.168.10.150:${GEOINTEL_FRONTEND_PORT:-1202}/health/ready"
|
|
curl -fsS "http://192.168.10.150:${GEOINTEL_FRONTEND_PORT:-1202}/api/v1/system/capabilities"
|
|
curl -fsS "http://192.168.10.150:${GEOINTEL_FRONTEND_PORT:-1202}/api/v1/projects"
|
|
curl -I "http://192.168.10.150:${GEOINTEL_FRONTEND_PORT:-1202}/geointel-icon.svg"
|
|
curl -I "http://192.168.10.150:${GEOINTEL_FRONTEND_PORT:-1202}/geointel-icon.png"
|
|
```
|
|
|
|
The live migration smoke also checks PostgreSQL database collation metadata.
|
|
When reusing a PostGIS volume created by an older Debian/glibc runtime, it may
|
|
print `COLLATION_VERSION_MISMATCH`. This is a maintenance warning, not an app
|
|
startup failure. Review backups first, then acknowledge the new runtime
|
|
collation version inside the running container:
|
|
|
|
```bash
|
|
docker exec -it geointel psql -U "${GEOINTEL_POSTGRES_USER:-geointel}" -d "${GEOINTEL_POSTGRES_DB:-geointel}"
|
|
ALTER DATABASE "geointel" REFRESH COLLATION VERSION;
|
|
```
|
|
|
|
If you rely on text indexes with locale-specific ordering, plan a maintenance
|
|
window and rebuild the affected indexes before acknowledging the version. The
|
|
current GeoIntel V1 spatial workflows primarily use UUIDs, JSON metadata and
|
|
PostGIS geometry indexes, but the warning should still be tracked explicitly.
|
|
|
|
## Change the browser port
|
|
|
|
Edit `.env`:
|
|
|
|
```env
|
|
GEOINTEL_FRONTEND_PORT=1203
|
|
GEOINTEL_CORS_ORIGINS=http://localhost:1203,http://127.0.0.1:1203,http://192.168.10.150:1203
|
|
```
|
|
|
|
Apply:
|
|
|
|
```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 .
|
|
bash deploy/unraid/run-dockerman-container.sh
|
|
```
|
|
|
|
## Persistent paths
|
|
|
|
Recommended Unraid paths:
|
|
|
|
```env
|
|
GEOINTEL_STORAGE_PATH=/mnt/user/appdata/geointel/storage
|
|
GEOINTEL_POSTGIS_DATA_PATH=/mnt/user/appdata/geointel/postgres-data
|
|
```
|
|
|
|
`GEOINTEL_STORAGE_PATH` contains uploads, tiles, masks, reports and exports.
|
|
|
|
`GEOINTEL_POSTGIS_DATA_PATH` contains the embedded PostGIS database files.
|
|
|
|
## Local Ollama assistant
|
|
|
|
The repository Compose file, DockerMan template and automatic deployment all
|
|
map `host.docker.internal` to the Unraid host and enable the source-grounded
|
|
assistant by default. Ollama must already listen on host port `11434`;
|
|
GeoIntel does not install or expose Ollama itself.
|
|
|
|
```env
|
|
OLLAMA_ENABLED=true
|
|
OLLAMA_BASE_URL=http://host.docker.internal:11434
|
|
OLLAMA_DEFAULT_MODEL=qwen3.5:9b
|
|
OLLAMA_TIMEOUT_SECONDS=120
|
|
OLLAMA_MAX_OUTPUT_TOKENS=1200
|
|
OLLAMA_CONTEXT_TOKENS=16384
|
|
```
|
|
|
|
`/health/live` proves only that FastAPI is serving. `/health/ready` returns
|
|
HTTP 503 when PostgreSQL, PostGIS, the migration head or persistent storage is
|
|
not ready, and is the container healthcheck. The all-in-one startup also marks
|
|
work left in `running` by a previous process as failed with
|
|
`PROCESS_INTERRUPTED`; synchronous work cannot survive a container restart.
|
|
|
|
The model dropdown comes from Ollama `/api/tags`, so changing the installed
|
|
models requires no frontend rebuild. Verify after deployment with:
|
|
|
|
```bash
|
|
curl http://127.0.0.1:1202/api/v1/assistant/status
|
|
curl http://127.0.0.1:1202/api/v1/assistant/models
|
|
```
|
|
|
|
## Update from Gitea
|
|
|
|
```bash
|
|
cd /mnt/user/appdata/geointel
|
|
git fetch origin main
|
|
git reset --hard origin/main
|
|
docker build --build-arg GEOINTEL_INSTALL_AI=${GEOINTEL_INSTALL_AI:-false} -f deploy/unraid/Dockerfile.all-in-one -t geointel-all-in-one:latest .
|
|
bash deploy/unraid/run-dockerman-container.sh
|
|
```
|
|
|
|
## Safe cleanup
|
|
|
|
Safe cache cleanup if Docker build cache fills the Unraid Docker image:
|
|
|
|
```bash
|
|
docker builder prune -af
|
|
```
|
|
|
|
Avoid broad volume pruning unless you explicitly intend to remove persisted PostGIS data or GeoIntel artifacts.
|
|
|
|
## Multi-container development stack
|
|
|
|
The root `docker-compose.yml` remains available for development and CI-like validation with separate `db`, `backend` and `frontend` services. For Unraid app-style operation, prefer `docker-compose.unraid.yml`.
|