Skip to content

Deployment

bacetiner edited this page Oct 3, 2026 · 1 revision

This page sets up one rapidtools-gui server that colleagues use from their browsers over HTTPS: the GUI runs in Docker behind the Caddy web server, which obtains the certificate by itself, while imagery, results and caches stay on the host disk.

The files live under deploy/ in the repository. The authoritative version of this page is Deploying a shared server in the docs; for the app itself see Graphical Interface.

What you need

  • A Linux machine with Docker and the Docker Compose plugin. For local models (Gemma 4, Qwen, Llama) and fast SAM 3 detection it needs an NVIDIA GPU with at least 16 GB of memory, the NVIDIA driver and the NVIDIA Container Toolkit. Without a GPU the cloud model backends (Gemini, Claude, OpenAI, Qwen and Muse Spark through their APIs) still work and SAM 3 runs slowly on the CPU.
  • A DNS name pointing at the machine (for example gui.example.edu) and ports 80 and 443 reachable by your colleagues. Port 8765 stays closed; Caddy is the only thing exposed.
  • Optionally an SMTP relay for email notifications.

The files in deploy/

File Role
Dockerfile Builds the GUI image on a PyTorch CUDA runtime base (or python:3.11-slim for CPU) and runs rapidtools-gui --host 0.0.0.0 --port 8765 --no-browser --data-root /data --output-dir /output.
docker-compose.yml The gui service plus Caddy; mounts DATA_DIR at /data, OUTPUT_DIR at /output and the rapidtools-cache volume at /cache.
docker-compose.gpu.yml Override that hands the host's NVIDIA GPU to the container.
Caddyfile Reverse proxy to gui:8765 with 10-minute read and write timeouts for long downloads and inference, automatic TLS, gzip.
.env.example Template for deploy/.env. Never commit the filled-in file.
idle-shutdown.sh Cron job that shuts a cloud VM down when the GUI has been idle.

One-time setup

  1. Get the code and prepare the folders that will hold imagery and results:

    git clone https://github.com/RAPID-Facility/rAPIdtools.git
    cd rAPIdtools
    sudo mkdir -p /srv/rapidtools/data /srv/rapidtools/output
    sudo chown -R $USER /srv/rapidtools
  2. Copy the environment template and fill it in:

    cp deploy/.env.example deploy/.env
    python -c "import secrets; print(secrets.token_urlsafe(18))"   # a token
    nano deploy/.env
    Variable Meaning
    RAPIDTOOLS_DOMAIN DNS name of the server; Caddy issues the certificate for it.
    RAPIDTOOLS_GUI_TOKEN Shared access token colleagues must present.
    DATA_DIR, OUTPUT_DIR Host folders mounted into the container (imagery colleagues may load; results).
    RAPIDTOOLS_SMTP_HOST, RAPIDTOOLS_SMTP_PORT, RAPIDTOOLS_SMTP_USER, RAPIDTOOLS_SMTP_PASSWORD, RAPIDTOOLS_SMTP_FROM, RAPIDTOOLS_SMTP_SSL Email notifications; leave empty to offer webhooks only.
    RAPIDTOOLS_IMAGE Image pulled by docker compose up -d; defaults to ghcr.io/rapid-facility/rapidtools-gui:latest.
    BASE_IMAGE, TORCH_INDEX Build arguments for a local CPU build; uncomment them on a machine without a GPU.

    The compose file sets RAPIDTOOLS_PUBLIC_URL to https://<domain>/ itself, so links in notifications point at the public address.

  3. Start it. With a GPU:

    docker compose -f deploy/docker-compose.yml -f deploy/docker-compose.gpu.yml \
        --env-file deploy/.env up -d

    Without one:

    docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d

    This pulls the ready-built image of the latest release from the GitHub Container Registry (several gigabytes for the CUDA image), or builds it locally when you add --build (required until the first image is published, see below). docker compose logs -f gui shows the server starting; the first request builds the RAPID route database from Mapillary in two to three minutes, after which it is cached in the rapidtools-cache volume.

  4. Open https://<domain>/?token=<your token> and check that the map loads. That link is what you send to colleagues; the token can also be typed on the sign-in page.

The published images

Every release tag publishes two images from deploy/Dockerfile to the GitHub Container Registry through .github/workflows/container.yml. The repository is public, so pulling them needs no account. The workflow ships with the release after 0.2.0; until that release is tagged no image exists on the registry yet, so build locally with the --build route described below.

Image Contents
ghcr.io/rapid-facility/rapidtools-gui:latest CUDA build on the PyTorch runtime base; also tagged with the version (0.2.0, 0.2).
ghcr.io/rapid-facility/rapidtools-gui:latest-cpu CPU-only build (0.2.0-cpu, 0.2-cpu).

Pin a version tag in RAPIDTOOLS_IMAGE to decide yourself when the server moves to a new release. The image runs on its own too, without Caddy, for a quick look on a workstation:

docker run --rm --gpus all -p 8765:8765 \
    -e RAPIDTOOLS_GUI_TOKEN=<token> \
    -v /path/to/imagery:/data -v /path/to/results:/output \
    ghcr.io/rapid-facility/rapidtools-gui:latest

To build the image from a checkout instead, add --build to the up -d command; the BASE_IMAGE and TORCH_INDEX lines in .env choose the CPU build.

Day to day

  • Everyone shares one workspace and one job queue. One detection or inference runs at a time; a second person's request is refused until it finishes. For a team that runs analyses at the same time, start a second gui service on another port with its own token and add it to the Caddyfile under a second path or name.
  • Imagery colleagues load must sit under DATA_DIR; the file browser cannot leave it. Results, crops and downloaded basemaps land under OUTPUT_DIR.
  • Model weights and the route database persist in the rapidtools-cache volume, so restarts do not download them again.
  • Notifications: with the SMTP lines filled in, users can ask for an email when a long run ends; webhooks (Slack, Teams) work without any setup. Browser alerts work because the site is served over HTTPS.
  • Updating: docker compose ... pull, then the same up -d command with the same -f and --env-file options. Restarting clears the loaded image and assets from memory but keeps every result file.
  • Rotating the token: change it in deploy/.env and restart the gui service.

A Windows machine in the lab

On a Windows workstation that colleagues reach over the local network, skip Docker and Caddy: install the package in a conda environment, run the console script with --host 0.0.0.0 --no-browser --data-root ... --output-dir ... and RAPIDTOOLS_GUI_TOKEN set, open TCP port 8765 in the Windows firewall for the Domain and Private profiles only, and keep it alive with a batch file registered in Task Scheduler (At startup, Restart the task if it fails, machine never sleeps). The window prints share links such as http://LAB-PC-07:8765/?token=.... Colleagues connect over plain HTTP on the intranet; the token still protects the app, but browser alerts need HTTPS, so users get email or webhook notifications instead. The step-by-step commands are in the docs.

Running without Docker

The container only wraps the console script. In a conda environment:

RAPIDTOOLS_GUI_TOKEN=<token> RAPIDTOOLS_SMTP_HOST=... rapidtools-gui \
    --host 127.0.0.1 --port 8765 --no-browser \
    --data-root /srv/rapidtools/data --output-dir /srv/rapidtools/output \
    --public-url https://gui.example.edu/

then point Caddy or nginx at 127.0.0.1:8765 for HTTPS. A systemd unit with Restart=always keeps it up across reboots.

On a cloud machine

  • Choose the machine for the models you will use. One 24 GB card (an L4 or A10G) runs the local Gemma 4 models in 4-bit and SAM 3 comfortably. A 2 to 4 vCPU machine without a GPU is enough when colleagues bring their own cloud model keys. Give it a static address.
  • Stop it when nobody uses it. Install deploy/idle-shutdown.sh as a cron job on the host (every 5 minutes, say). It polls /api/state with the X-Rapidtools-Token header, treats a running job or recent container log output as activity, and shuts the machine down after IDLE_MINUTES (30 by default) of silence. RAPIDTOOLS_URL and RAPIDTOOLS_GUI_TOKEN tell it where the GUI is and how to authenticate.
  • Disk: keep DATA_DIR, OUTPUT_DIR and the Docker volumes on a persistent disk that survives the instance, and snapshot it now and then.

Security notes

The token is the only protection and everyone shares it. Serve the site over HTTPS only (the compose setup does), keep port 8765 closed, rotate the token when someone leaves, and prefer the institution's network or a VPN for the address. API keys pasted into the page are sent to the server for the duration of a job and are not stored. Problems starting or reaching the server are covered in Troubleshooting and FAQ.

Clone this wiki locally