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:
-
Publish the port on all interfaces by changing the
portsentry — do not changeOPENSQUILLA_LISTEN:ports: - "18791:18791" -
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:
- Web UI — provider onboarding and most config changes at
/control/hot-apply and persist toconfig.tomlin the state volume. Channel, memory-embedding, and sandbox-posture changes need a restart — the Web UI marks these, anddocker compose restart gatewayapplies them. - Compose
environment— pass provider keys by env-var name, as in the quick start. Environment values always win over.envfiles. - A
.envinside the state volume — the gateway loads/var/lib/opensquilla/.envat startup, so keys survive image upgrades without appearing incompose.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 underenvironment:incompose.yamlshadows the state-volume.enveven when the host variable is unset (Compose passes an empty value through) — remove it fromenvironment: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 gatewayshows boot errors, including an unwritable state directory (fix ownership as above).docker compose exec gateway opensquilla doctorreports readiness and recovery steps.- The Docker sections in
troubleshooting.mdcover 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