Self-host Charyl on your own Linux server
Docker Engine and Compose on a Linux box you already own — the same runtime the appliance runs, on hardware that's yours.
Run the full Charyl stack on a Linux server you keep on — the same Docker runtime the appliance runs, just on hardware that’s yours. This is the self-host path: free, real today, and pulling the same published images the appliance ships with.
What you need
- A Linux box you keep on — a home server, a mini-PC, or a VM.
amd64/x86-64today;arm64images are still a work in progress. - Docker Engine and Compose v2 (
docker compose versionreports v2 or later) — Engine on Linux, not Docker Desktop. - A local model runtime for AI and embeddings (Step 3 below). Without it, semantic search stays dark; everything else still works.
- A couple of GB of RAM headroom, and disk space for the database and uploads.
The stack binds four ports on the host: 8080 (the web app), 5142 (the API and realtime hub), 1883 (MQTT, for sensor nodes), and 8123 only if you turn on the bundled Home Assistant. The database, Charyl, and the updater are never exposed to your network — by design.
-
Get the files
During the testing period we send you the compose bundle —
docker-compose.yml,.env.example, and the helper scripts — together with registry access when your early-access request is approved. Unpack it into the directory you’ll run from, then:cp .env.example .envYou don't need the source to run the stack
It pulls prebuilt images — the bundle is just the compose file and its helper scripts. At release, both the bundle and the images are public.
-
Configure .env
Open
.envand set the handful of knobs that matter for a self-host box. Most already have working defaults:Variable Set it to Why SINGER_VERSION/CHARYL_VERSIONthe release you’re running Pins the image versions — the two numbers drift apart on purpose. SINGER_PROJECT_DIRthe absolute path of this directory (e.g. /opt/singer)Required for the auto-updater to apply releases correctly. GHCR_USERNAME/GHCR_READ_TOKENyour GitHub username and a read:packagestokenOnly during the private-testing period — Step 4 below. Goes away once images are public. SIH_ANTHROPIC_KEYyour AI provider key (optional) Enables Charyl’s chat and product research. Not needed just to onboard. TAVILY_API_KEYa web-search provider key (optional) Used only if web search is enabled. TZyour timezone Maintenance-window and log timestamps. Leave
SINGER_REGISTRYunset — the default is correct. Do not put a database password or signing key in.env; the stack generates those itself, per box, the first time it boots.Leave
ADMIN_PASSWORDblank and the app generates a random one, printed once in the log — you’ll grab it in Step 6. SetADMIN_EMAILto the address you want to log in with. -
Install a local model runtime
The stack expects a local model runtime reachable at
http://host.docker.internal:11434. Install it on the host, then pull the models Charyl uses:curl -fsSL https://ollama.com/install.sh | sh # host-native install ollama pull <chat-model> # value of OLLAMA_MODEL in .env ollama pull <embedding-model> # the model Charyl embeds withCheck the exact model names against your release — the chat model must be tool-capable. Semantic search stays dark until the embedding model is present; everything else runs without it.
-
Log in to the image registry
While the images are private, authenticate Docker with a GitHub token scoped to
read:packages— nothing more:docker login ghcr.io -u "$GHCR_USERNAME" --password-stdin <<< "$GHCR_READ_TOKEN"Testing period only
Once the images are published publicly, this step is unnecessary — a plain
docker compose uppulls anonymously. -
Bring it up
docker compose up -d # pulls published images; NO --build docker compose ps # watch until services are healthyOn first boot, a one-shot container mints this box’s own database password, signing key, API key, and updater secret into a private volume — nothing hardcoded, nothing in
.env, different on every box.Two volumes share one fate
The
secretsandpostgres_datavolumes are a matched pair.docker compose down -vwipes both together — safe, and how you get a clean box. Wiping only one of them causes a password mismatch. -
Onboard
docker compose logs singer-hkg-api | grep -i "GENERATED SEED ADMIN PASSWORD"Open
http://localhost:8080(orhttp://<box-lan-ip>:8080from another device on your network), log in withADMIN_EMAILand that generated password, and follow the first-run wizard — including, if you want it, connecting to Charyl Cloud.That’s it — the stack is running, and, if you pair it to Charyl Cloud, keeps itself updated.
Updates and day-to-day
- Updates. With a Charyl Cloud subscription the updater applies releases automatically in a maintenance window — pull by digest, recreate, health-gate, roll back if unhealthy. Without one, update by hand:
docker compose pull && docker compose up -d. Either waySINGER_PROJECT_DIRmust be set for the updater. - Logs.
docker compose logs -f <service>— for examplesinger-hkg-apiorsinger-charyl. - Stop and start.
docker compose stopanddocker compose up -d. Your data lives in named volumes and survives restarts and updates. - Optional Home Assistant. Add
COMPOSE_PROFILES=homeassistantto.envto run the bundled, version-pinned Home Assistant on port8123— see Connect Home Assistant. Households running their own leave this unset.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| A service won’t pull | Registry auth (Step 4) — confirm docker login ghcr.io succeeded and your token has read:packages. Unneeded after public release. |
| Postgres never goes healthy after resetting only one volume | The secrets/postgres_data shared-fate rule (Step 5) — run docker compose down -v to come back up clean. |
| Semantic search returns nothing | Confirm the local model runtime is running on the host and the embedding model is pulled; check docker compose logs singer-charyl for the embed call. |
| Can’t log in, or lost the admin password | Set ADMIN_PASSWORD and ADMIN_RESET_PASSWORD=true in .env for one boot, then unset it. |
Next
Once the stack is up, the first-run wizard covers naming your home, connecting Home Assistant, and pairing a phone.