Add Docker and Docker Compose support#7
Merged
Conversation
Signed-off-by: Veslydev <vesly@vesly.dev>
Signed-off-by: Veslydev <vesly@vesly.dev>
Signed-off-by: Veslydev <vesly@vesly.dev>
Signed-off-by: Veslydev <vesly@vesly.dev>
Bind-mount a config directory (not a single file) so the binary's atomic PUT /config write can rename within it; verified GET + PUT persist to the host file. Seed with: cp tsheadroom.config.example.json config/config.json Signed-off-by: Veslydev <vesly@vesly.dev>
lkosewsk
requested changes
Jun 12, 2026
lkosewsk
left a comment
Collaborator
There was a problem hiding this comment.
I love it, thank you! I'm going to ask for one thing - can you take the PR description, condense it, and put it in the README (above or below the Run it as a service section - take your pick)? That gives new users the ability to get started fast without trying to figure out how to set up docker.
Condensed the deployment notes into a 'Run it with Docker' section under Run, so new users can get started with docker compose up -d --build without reverse-engineering the compose file. Signed-off-by: Veslydev <vesly@vesly.dev>
lkosewsk
approved these changes
Jun 12, 2026
lkosewsk
left a comment
Collaborator
There was a problem hiding this comment.
A+, thank you! Clear to merge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Docker and Docker Compose support so deploying and updating tsheadroom no longer requires manual Go toolchain setup, venv management, or systemd unit editing on the host.
Dockerfile— multi-stage build (Go 1.26 compiler →python:3.13-slimruntime). AHEADROOM_VARIANTbuild arg selects betweenheadroom-ai(base, tool outputs only, low memory) andheadroom-ai[ml](full text + tool compression, ~600 MB ML model per worker). Python 3.13 is pinned because headroom-ai ships prebuilt wheels for it — no Rust toolchain needed.docker-compose.yml— single service backed by two named volumes and one bind mount:tsheadroom-state(named) — tailnet device identity; persists across restarts so the node never re-authenticates.tsheadroom-hf-cache(named) — HuggingFace model cache, shared by all workers in the container; survivesdown/upso the ~600 MB model is never re-downloaded../config→/etc/tsheadroom(bind) — the live compression config (config.json). A directory, not a single file, so the binary's atomicPUT /configwrite can rename within it (a single-file bind mount fails this withEBUSY). Editconfig/config.jsonon the host and restart, or change it live viaPUT /config; both paths are verified to persist.TS_AUTHKEY,TS_HOSTNAME,HEADROOM_VARIANT,POOL_SIZE) live in.env..env.example— copy to.envand fill in to get started.tsheadroom.config.example.json— committed default compression config (mirrors the binary's built-in defaults). Copy it toconfig/config.jsonbefore first start, the same way you copy.env.example..dockerignore— excludesbuild/,.git/,tests/,docs/,.envfrom the build context.Deploy
Update
git pull && docker compose up -d --build--buildrecompiles the Go binary and reinstalls Python deps if anything changed. The tailnet identity and model cache are preserved in volumes.Migrate from systemd
Testing
base(630 MB) andml(CUDA stack pulled in by torch).mlimage: verifiedheadroom+ ML deps import inside the image.-local-addr: a short chat returns{"action":"allow"}../configbind mount round-trips:GET /configreads it andPUT /configpersists changes back to the host file.