# Docker The image is Node 24 Alpine. It runs `node index.ts` with `PORT=4040` and listens on `0.0.0.0`. CI publishes `ghcr.io/kody-bot/home-mcp-starter` to GitHub Container Registry. Tags are `latest` and `sha-`. ## Compose From the repo root: ```bash cp .env.example .env ``` Set at least: ```bash HOME_MCP_PUBLIC_BASE_URL=https://home.example.com PORT=4040 ``` Then: ```bash docker compose up --build -d ``` `docker-compose.yml` maps host `4040` to the container, loads `.env`, and bind mounts `${HOME}/.kody/home-mcp` to `/data` with `HOME_MCP_DATA_PATH=/data`. OAuth rows and notes survive container recreation. Bridge networking is enough for HTTP tools. If you later add LAN multicast discovery, switch the service to host networking so those packets reach the process. ## Volumes Default data lives at `~/.kody/home-mcp` on the host: - `home-mcp.sqlite` — hashed OAuth codes and tokens - `notes.json` — household notes Override `HOME_MCP_DB_PATH` or `HOME_MCP_NOTES_PATH` if you want those files somewhere else inside `/data`. ## NAS / Container Manager The same image runs in a NAS container UI: 1. Pull `ghcr.io/kody-bot/home-mcp-starter:latest`. 2. Publish container port `4040`. 3. Bind a persistent folder to `/data`. 4. Set `HOME_MCP_DATA_PATH=/data`. 5. Set `HOME_MCP_PUBLIC_BASE_URL` to the HTTPS hostname in front of the NAS (the Tunnel hostname, not an RFC 1918 address). 6. Restart policy: unless stopped. Create the host data folder before the first start so the mount is not owned by root unexpectedly. The process does not need extra packages inside the image. ## Environment See [Getting started](./getting-started.md) for the full table. In Docker, `APP_COMMIT_SHA` is a build-arg and an image env var. ## Updating the image ```bash docker compose pull docker compose up -d ``` Or, when you build locally: ```bash docker compose up --build -d ``` The data mount stays in place. After an update, `/health` should still report the same `mcpUrl` and `serverId`.