Deploy ADHD Hub on a homelab (Proxmox + Tailscale)¶
This guide covers the Proxmox/LXC + Tailscale layout: one persistent Docker Hub instance in the lab, with coding clients connecting over MCP.
For generic container installation, upgrades, and first login, use Install ADHD Progress Hub. For configuration keys, use Environment variables.
Before you start¶
You need:
- a Proxmox LXC or existing Docker host;
- Docker + Compose;
- Tailscale on the Hub host and any private clients;
- a strong
ADHD_HUB_AUTH_TOKEN; - persistent
/datastorage; - an HTTPS tunnel only if a cloud agent cannot reach the tailnet.
1. Create or pick an LXC¶
- Create a new CT or reuse a Docker host (for example beside OpenClaw).
- Install Docker + Compose.
- Join Tailscale (
tailscale up). Note the Tailscale IPv4/MagicDNS name you want clients to use.
2. Deploy the Hub¶
For a normal long-lived install, use the published-image Compose example from the installation guide on the LXC.
If you are developing ADHD Hub itself and intentionally deploy the current checkout, the repository also has sync/build tooling. From your Windows/dev machine, after Tailscale SSH auth works:
# Linux/macOS or Git Bash / WSL:
./scripts/sync-and-deploy.sh root@<tailscale-host-or-ip> /opt/adhd-hub
Or manually on the Docker host:
git clone <your-repo> /opt/adhd-hub # or rsync the tree
cd /opt/adhd-hub
cp .env.example .env
# Edit at minimum:
# ADHD_HUB_AUTH_TOKEN=<long random>
# Optional when OpenClaw is on the same/private network:
# ADHD_HUB_OPENCLAW_WEBHOOK_URL=http://<openclaw-host>:18789/hooks/wake
# ADHD_HUB_OPENCLAW_TOKEN=<openclaw hooks token>
docker compose up -d --build
curl -fsS http://127.0.0.1:8787/api/health
Ensure container port 8787 is reachable on the Tailscale interface. With the standard Compose mapping, clients use http://<tailscale-host-or-ip>:8787 while the process still listens on 0.0.0.0:8787 inside the container.
Reverse proxy / HTTPS cookies¶
If you terminate TLS in front of the Hub (Caddy, nginx, Tailscale Serve):
- Set
ADHD_HUB_PUBLIC_URLto the https URL browsers and agents use. - Set
ADHD_HUB_TRUST_PROXY_HEADERS=trueso login cookies can derive the Secure flag fromX-Forwarded-Proto: https. - Optionally force Secure cookies with
ADHD_HUB_COOKIE_SECURE=true. - Only trust those headers from your proxy — do not expose the Hub directly to the public internet with proxy trust enabled.
Installable PWA: open /ui/ over HTTPS (or localhost), then use “Install app” / Add to Home Screen. The service worker caches the UI shell only — never /api or MCP. When a newer shell is waiting, Hub shows a calm Refresh toast; updates are not forced mid-task.
Note: First Tailscale SSH from a new machine may require opening a Tailscale authentication URL in the browser.
3. OpenClaw¶
On the OpenClaw gateway, enable hooks with a bearer token, or use Hub pairing from Settings → Phone alerts. Point manual Hub configuration at /hooks/wake (and optionally /hooks/agent). Stale digests use ADHD_HUB_STALE_NUDGE_CRON (default 0 9 * * *).
You can also have OpenClaw poll:
4. Clients¶
Prefer adhd-hub connect / the generated one-liner instead of hand-editing each client; see Connect.
| Client | Typical route |
|---|---|
| Cursor Windows | MCP URL http://<tailscale-host-or-ip>:8787/mcp or HTTPS public URL |
| Cursor Cloud | Same MCP URL if the cloud agent can reach that private route; otherwise use a controlled HTTPS tunnel or the forge mailbox fallback |
| Dev LXC | Same MCP URL from that host |
| Codex / Claude | Connect CLI or their documented MCP configuration |
For MCP clients that support Auth/Authenticate, a correctly configured ADHD_HUB_PUBLIC_URL allows Hub OAuth discovery. Static Bearer auth remains supported. When Tailscale is unreachable from Cursor Cloud, see Remote MCP access before opening anything publicly.
5. Local indexer (Windows)¶
Transcripts normally live on the PC while the Hub lives in the lab. Run the indexer where those transcripts exist rather than mounting personal transcript directories into the server container:
Schedule it with Task Scheduler if you want nightly capture. See Indexer schedule.
6. Back up the lab instance¶
Before upgrades or migrations, use /ui → Settings → Your data → Download backup or the CLI export. Keep the Compose /data volume persistent; removing that volume removes the local Hub state (including project tags and ai.json AI settings). Never use docker compose down -v for a normal upgrade. Confirm ADHD_HUB_DATA_DIR=/data matches the volume mount — see Installation → What lives under /data.
For regular container upgrades using a published image:
7. Move an existing local Hub to this LXC¶
Two complementary paths are available.
A. Full instance migrate (SQLite threads + wiki + forge prefs)¶
On the old machine (UI or CLI):
/ui→ Settings → Your data → Download backup, oruv run adhd-hub export -o adhd-hub-backup.zip.- Optional encryption:
uv run adhd-hub export -o adhd-hub-backup.zip.enc --passphrase '…' - Copy the backup to the LXC (scp / Tailscale).
- Stop the target Hub while restoring so SQLite is not open.
If you run the CLI on the host against a bind-mounted data directory, import directly there. With a named Docker volume, restore through the supported UI/import path or a temporary container/CLI environment that points ADHD_HUB_DATA_DIR at that volume; do not assume a named volume exists at ./data on the host.
Encrypted files are a versioned envelope around the zip (magic ADHDHUB1), not a password-zip. New exports derive the Fernet key with scrypt using a random salt stored in the header. Older v1 encrypted backups still restore with the same passphrase. The HTTP restore path rejects archives over 80 MiB.
Keep the same ADHD_HUB_AUTH_TOKEN if you want existing static-Bearer clients to keep working, or reconnect/update those clients. Set ADHD_HUB_PUBLIC_URL to the final URL clients should use.
Legacy forge wiki paths¶
If an older Hub used wiki_path = "adhd-hub/wiki", migrate local config to repo-root projects/:
uv run adhd-hub forge-wiki-paths # dry-run
uv run adhd-hub forge-wiki-paths --apply # write forge.json / project overrides
Move remote files under the forge repo separately (adhd-hub/wiki/projects/ → projects/).
B. Forge-first (wiki already on Gitea/GitHub)¶
If the memory repo already has projects/*/PROGRESS.md:
- Deploy a fresh Hub on the LXC.
- Configure the same forge in
/uiSettings (orADHD_HUB_FORGE_*). - Save issue sync / Scan for projects — the UI lists remote projects missing from this Hub.
- Import registers projects and pulls progress files.
Forge import does not recreate SQLite threads/reminders; use Export/Import (A) when you need full local history.
8. Smoke test¶
First confirm health:
Then run adhd-hub doctor --hub http://<tailscale-host-or-ip>:8787 --project /path/to/project from a client machine. If you want an API-level write test, use a CLI session or temporary Bearer token and create a disposable thread, then confirm session_digest / check_overlap can see it.