263 lines
9.8 KiB
Markdown
263 lines
9.8 KiB
Markdown
# 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](quickstart.md) installs are simpler.
|
|
|
|
## Prerequisites
|
|
|
|
Install Docker Engine with the Compose plugin. On Debian 12, follow the
|
|
[official Docker instructions](https://docs.docker.com/engine/install/debian/),
|
|
then verify:
|
|
|
|
```sh
|
|
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`](https://github.com/opensquilla/opensquilla/pkgs/container/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](#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`:
|
|
|
|
```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`):
|
|
|
|
```sh
|
|
OPENSQUILLA_AUTH_TOKEN=<output of: openssl rand -hex 32>
|
|
OPENROUTER_API_KEY=<your provider key>
|
|
```
|
|
|
|
Start it:
|
|
|
|
```sh
|
|
docker compose up -d
|
|
docker compose logs -f gateway
|
|
```
|
|
|
|
Then open the Web UI with the token in the URL:
|
|
|
|
```text
|
|
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`:
|
|
|
|
```yaml
|
|
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`](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:
|
|
|
|
```sh
|
|
sudo mkdir -p /srv/opensquilla
|
|
sudo chown -R 10001:10001 /srv/opensquilla
|
|
```
|
|
|
|
```yaml
|
|
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:
|
|
|
|
```sh
|
|
docker compose restart gateway
|
|
```
|
|
|
|
## Change the Published Port
|
|
|
|
Change the host side of the mapping and keep the container side at 18791:
|
|
|
|
```yaml
|
|
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:
|
|
|
|
```sh
|
|
docker inspect --format '{{.State.Health.Status}}' $(docker compose ps -q gateway)
|
|
```
|
|
|
|
The full CLI is available inside the container:
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
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`](troubleshooting.md) cover the
|
|
common failures: unreachable Web UI, rejected configuration changes,
|
|
bind-mount permissions, and LFS-related build errors.
|
|
|
|
---
|
|
|
|
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
|