Files
2026-07-13 13:12:33 +08:00

9.8 KiB

Docker Deployment

Run the OpenSquilla gateway as a container on a machine that stays on — a home server, a NAS, or a small VPS. This page uses Debian 12 as the worked example, but any host with Docker Engine works the same way, on both amd64 and arm64.

Docker is the right install path when:

  • the host has no Python 3.12+ toolchain (or you do not want one),
  • you want the gateway to survive reboots and upgrade by pulling a new image,
  • you deploy on a NAS or headless server and use the Web UI from another device.

For a desktop machine, the quickstart installs are simpler.

Prerequisites

Install Docker Engine with the Compose plugin. On Debian 12, follow the official Docker instructions, then verify:

docker --version
docker compose version

Nothing else is required on the host for the prebuilt-image path — no Python, no Git, no build tools.

Quick Start with the Prebuilt Image

Prebuilt multi-arch images are published to ghcr.io/opensquilla/opensquilla for each release tag. The immutable v0.5.0rc3 tag identifies Preview 3, while latest follows the most recently pushed release tag, including previews and backports. If a backport moves latest, the newest release workflow is rerun to restore the intended ordering. If the release you want predates image publishing, use Build the Image Yourself instead. A pull that fails with denied or manifest unknown means the image for that tag has not been published (or the package is not public yet) — check the package page for available tags, or build from source.

Create a directory for the deployment and write this compose.yaml:

services:
  gateway:
    # Pin v0.5.0rc3 for reproducibility; latest follows the most recent tag push.
    image: ghcr.io/opensquilla/opensquilla:latest
    environment:
      # In-container bind. Keep it 0.0.0.0 — what the network can reach is
      # decided by `ports` below, not by this value.
      OPENSQUILLA_LISTEN: "0.0.0.0"
      # Token auth is required to administer a containerized gateway through
      # the Web UI, even from the same host. Generate a token with:
      #   openssl rand -hex 32
      OPENSQUILLA_AUTH_MODE: token
      OPENSQUILLA_AUTH_TOKEN: ${OPENSQUILLA_AUTH_TOKEN:?generate one with openssl rand -hex 32}
      OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-}
      TZ: ${TZ:-UTC}
    volumes:
      # All state — config, session DBs, memory, logs, workspace — lives under
      # /var/lib/opensquilla. The named volume makes it survive recreates.
      - opensquilla-state:/var/lib/opensquilla
    ports:
      # Loopback-only: reachable from this host, invisible to the network.
      # For NAS/LAN access see "Reach the Web UI from Your LAN" below.
      - "127.0.0.1:18791:18791"
    restart: unless-stopped

volumes:
  opensquilla-state:

Put the two secrets in a .env file next to compose.yaml (Compose reads it automatically; keep it out of version control and private: chmod 600 .env):

OPENSQUILLA_AUTH_TOKEN=<output of: openssl rand -hex 32>
OPENROUTER_API_KEY=<your provider key>

Start it:

docker compose up -d
docker compose logs -f gateway

Then open the Web UI with the token in the URL:

http://127.0.0.1:18791/control/?token=<your OPENSQUILLA_AUTH_TOKEN>

The token is consumed once and stored for the browser session. The first request also writes the token into the gateway access log, so treat docker compose logs output as sensitive — or open /control/ without the query parameter and paste the token into the connection panel instead. From there, finish provider onboarding and configuration in the Web UI — provider changes apply immediately and persist in the state volume.

Why token auth is not optional here: the container binds a wildcard address, so the gateway treats every browser — including one on the same host — as a remote operator. Remote operators without a token can chat but cannot administer configuration or onboarding (only a small allowlist of safe runtime toggles stays writable). With OPENSQUILLA_AUTH_MODE=token the token grants the operator scopes that Web UI administration needs. Use token mode specifically; password and trusted-proxy modes do not support the Web UI connection.

Reach the Web UI from Your LAN

On a headless NAS you will use the Web UI from another device. Two rules:

  1. Publish the port on all interfaces by changing the ports entry — do not change OPENSQUILLA_LISTEN:

    ports:
      - "18791:18791"
    
  2. Keep token auth configured (already true if you followed the quick start). The gateway warns, but does not refuse, when it is network-reachable — exposure is your call, auth is not.

Recreate the container (docker compose up -d) and open http://<server-address>:18791/control/?token=<token> from your device. If the host runs a firewall, allow inbound TCP 18791 from your LAN only. LAN traffic to the gateway is plain HTTP, so the token is visible to anyone who can observe that network — if your LAN is not fully trusted, put the gateway behind a TLS reverse proxy or use the VPN option below.

Do not forward the gateway port to the internet. For remote access away from home, use a VPN (WireGuard, Tailscale) or a reverse proxy with TLS and its own authentication in front. See the safety defaults in gateway.md.

Keep State on Your Own Storage (Bind Mount)

The named volume is the safest default. If you prefer a directory you manage (RAID storage, backup tooling), bind-mount it — but the container runs as non-root UID 10001, so give it ownership first or the gateway fails at boot:

sudo mkdir -p /srv/opensquilla
sudo chown -R 10001:10001 /srv/opensquilla
volumes:
  - /srv/opensquilla:/var/lib/opensquilla

Everything worth backing up is under that one directory: config.toml, state/ (session and scheduler databases), logs/, workspace/, media/, and an optional .env.

Configure Providers and Secrets

Three ways, in order of preference:

  1. Web UI — provider onboarding and most config changes at /control/ hot-apply and persist to config.toml in the state volume. Channel, memory-embedding, and sandbox-posture changes need a restart — the Web UI marks these, and docker compose restart gateway applies them.
  2. Compose environment — pass provider keys by env-var name, as in the quick start. Environment values always win over .env files.
  3. A .env inside the state volume — the gateway loads /var/lib/opensquilla/.env at startup, so keys survive image upgrades without appearing in compose.yaml. On a bind mount, keep it owned by the container user and private: chown 10001:10001 .env && chmod 600 .env. Caveat: a key listed under environment: in compose.yaml shadows the state-volume .env even when the host variable is unset (Compose passes an empty value through) — remove it from environment: if you manage it in the state volume.

One precedence caveat for auth: values saved to config.toml — for example by the Web UI — take precedence over environment variables at boot. If the OPENSQUILLA_AUTH_* variables stop taking effect after configuring through the Web UI, config.toml now owns the [auth] settings; rotate the token there (or in the Web UI) and restart.

Hand-edits to /var/lib/opensquilla/config.toml are read at boot only — restart to apply them:

docker compose restart gateway

Change the Published Port

Change the host side of the mapping and keep the container side at 18791:

ports:
  - "127.0.0.1:8080:18791"

Setting OPENSQUILLA_GATEWAY_PORT does not change the listen port of the container entrypoint — the port lives in the mapping above.

Health and CLI Access

/healthz answers liveness without auth, and /readyz returns 503 until the gateway is fully ready. The image ships a healthcheck; inspect it with:

docker inspect --format '{{.State.Health.Status}}' $(docker compose ps -q gateway)

The full CLI is available inside the container:

docker compose exec gateway opensquilla doctor
docker compose exec gateway opensquilla gateway status

Upgrade and Roll Back

State lives in the volume, so containers are disposable:

docker compose pull
docker compose up -d

To roll back, pin the previous release tag in image: and docker compose up -d again. Pinned tags plus a state backup make both directions routine.

Build the Image Yourself

The source checkout ships the same Dockerfile and a compose.yaml that defaults to a self-built opensquilla:local image (override with OPENSQUILLA_GATEWAY_IMAGE to use the GHCR image instead). Building needs git, git-lfs, and the Git LFS router assets:

sudo apt install -y git git-lfs
git clone https://github.com/opensquilla/opensquilla.git
cd opensquilla
git lfs pull --include="src/opensquilla/squilla_router/models/**"
docker build -t opensquilla:local .
docker compose up -d

On a low-power or arm64 NAS this build is slow; prefer the prebuilt image and keep source builds for development machines.

If Something Fails

  • docker compose logs gateway shows boot errors, including an unwritable state directory (fix ownership as above).
  • docker compose exec gateway opensquilla doctor reports readiness and recovery steps.
  • The Docker sections in troubleshooting.md cover the common failures: unreachable Web UI, rejected configuration changes, bind-mount permissions, and LFS-related build errors.

Docs index · Product guide · Improve this page · Report a docs issue