Docker Compose
Run the prebuilt image behind a reverse proxy, pin a version, and upgrade.
Excaliself ships as a prebuilt multi-arch (amd64, arm64) image:
ghcr.io/maciekzygmunt/excaliself
| Tag | Tracks |
|---|---|
latest |
Newest release |
1.2.3 |
That exact release |
1.2 |
Newest 1.2.x patch |
main |
Tip of main (unreleased, may break) |
The app needs PostgreSQL. docker-compose.yaml starts both. The app runs
database migrations on startup, so upgrading is pulling a newer image and
restarting. GET /api/health returns 200 when the app is serving and Postgres
is reachable; the image uses it as its container healthcheck.
See the Quick start for the install commands and Environment variables for every setting.
Reverse proxy
Postgres is not published on the host; only the app port is
(EXCALISELF_PORT, default 3000). On a public server, put a reverse proxy
with TLS (Caddy, Traefik, nginx) in front of it and set BASE_URL to the
public https:// URL. Auth rejects sign-ins from any other origin. Set
EXCALISELF_PORT=127.0.0.1:3000 to keep the app port local to the proxy.
Live collaboration and all Team drawings use WebSockets on the app port, under
/ws/, so the proxy must pass them through. Caddy and Traefik do this by default:
draw.example.com {
reverse_proxy 127.0.0.1:3000
}
nginx needs the upgrade headers. Its default 1 MB body limit is also too small for images:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 32m;
}
Upgrade or pin a version
# optional: pin in .env, e.g. EXCALISELF_VERSION=1.2.3
docker compose pull
docker compose up -d
Drawings live in the pgdata volume, which survives upgrades and
docker compose down. docker compose down -v deletes it.
Take a backup before each upgrade. There are no down migrations, so restoring it is the safe way back to the older version.
Build from source
To build the image on the server instead of pulling it (needs ~4 GB RAM), clone the repo and run:
docker compose -f docker-compose.yaml -f docker-compose.build.yaml up -d --build
docker-compose.build.yaml alone publishes no port; docker-compose.yaml adds
it.