-
Notifications
You must be signed in to change notification settings - Fork 2k
feat: add plain self-hosted Docker deploy template #976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
LIOsDev
wants to merge
2
commits into
rohitg00:main
Choose a base branch
from
LIOsDev:feat/generic-docker-deploy-template
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+372
−11
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| ARG III_VERSION=0.11.2 | ||
|
|
||
| FROM iiidev/iii:${III_VERSION} AS iii-image | ||
|
|
||
| FROM node:22-slim | ||
|
|
||
| ARG AGENTMEMORY_VERSION=0.9.12 | ||
| ARG III_VERSION=0.11.2 | ||
| ARG III_SDK_VERSION=0.11.2 | ||
|
|
||
| RUN apt-get update \ | ||
| && apt-get install -y --no-install-recommends openssl ca-certificates tini gosu curl \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| COPY --from=iii-image /app/iii /usr/local/bin/iii | ||
|
|
||
| # Install agentmemory into a dedicated prefix so the local package.json's | ||
| # `overrides` field pins iii-sdk down to match the engine (agentmemory's | ||
| # caret range `^0.11.2` otherwise resolves to 0.11.6, the version that | ||
| # requires the new sandbox-everything worker model the agentmemory CLI | ||
| # is not refactored for yet). `npm install -g` ignores overrides, hence | ||
| # the local prefix. | ||
| WORKDIR /opt/agentmemory | ||
| RUN printf '{"name":"agentmemory-deploy","version":"1.0.0","private":true,"overrides":{"iii-sdk":"%s"}}\n' "${III_SDK_VERSION}" > package.json \ | ||
| && npm install "@agentmemory/agentmemory@${AGENTMEMORY_VERSION}" --omit=optional --no-fund --no-audit \ | ||
| && ln -s /opt/agentmemory/node_modules/.bin/agentmemory /usr/local/bin/agentmemory | ||
|
|
||
| ENV AGENTMEMORY_III_VERSION=${III_VERSION} \ | ||
| TINI_SUBREAPER=1 | ||
|
|
||
| COPY --chmod=0755 entrypoint.sh /usr/local/bin/agentmemory-entrypoint.sh | ||
|
|
||
| EXPOSE 3111 3113 | ||
|
|
||
| HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \ | ||
| CMD curl -fsS http://127.0.0.1:3111/agentmemory/livez || exit 1 | ||
|
|
||
| ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/agentmemory-entrypoint.sh"] |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| # Deploy agentmemory on plain self-hosted Docker | ||
|
|
||
| For running agentmemory on infrastructure you already control and aren't | ||
| asking a PaaS to manage — a NAS, a homelab server, a Windows machine running | ||
| Docker Desktop, or any other Docker host with no built-in reverse proxy or | ||
| TLS termination. Same Dockerfile/entrypoint pattern as the | ||
| [Coolify template](../coolify/README.md), with the platform-specific bits | ||
| (`SERVICE_FQDN_*`, Coolify's managed Traefik/Caddy proxy) removed and replaced | ||
| with plain `ports:` publishing you control directly. | ||
|
|
||
| ## What you get | ||
|
|
||
| - A Docker Compose stack exposing the agentmemory REST/MCP API on port | ||
| `3111`, published directly to whatever network your Docker host is on (no | ||
| proxy required, but nothing stops you from putting one in front). | ||
| - A persistent named volume (`agentmemory-data`) backing `/data` — memories, | ||
| BM25 index, and stream backlog survive container recreation. | ||
| - An HMAC secret generated on first boot and persisted to the volume (see | ||
| below) — never baked into the image or a committed config file. | ||
| - The viewer (port `3113`) stays loopback-only inside the container by | ||
| default, matching the npm package's own safe default. Reaching it from | ||
| another machine is opt-in (see "Viewer access" below). | ||
|
|
||
| ## One-time setup | ||
|
|
||
| ```bash | ||
| git clone https://github.com/rohitg00/agentmemory | ||
| cd agentmemory/deploy/docker | ||
| docker compose up -d --build | ||
| ``` | ||
|
|
||
| Watch the first-boot logs for the generated secret: | ||
|
|
||
| ```bash | ||
| docker compose logs -f agentmemory | ||
| # look for a line: AGENTMEMORY_SECRET=<64 hex chars> | ||
| ``` | ||
|
|
||
| Copy it into your MCP client's environment (see the main repo README's | ||
| Claude Code / Cursor / etc. integration sections). It is not printed again on | ||
| subsequent boots — to rotate it, see "Rotate the HMAC secret" below. | ||
|
|
||
| ## Verify the deployment | ||
|
|
||
| ```bash | ||
| curl http://<your-host-ip>:3111/agentmemory/livez | ||
| # {"status":"ok"} | ||
| ``` | ||
|
|
||
| For an authenticated call, send `Authorization: Bearer <secret>`. | ||
|
|
||
| ## Viewer access (port 3113 stays internal by default) | ||
|
|
||
| Two options, in order of how much you trust the network this host is on: | ||
|
|
||
| **Option A — SSH/local tunnel (recommended for anything beyond a fully | ||
| trusted LAN).** | ||
|
|
||
| The viewer port must first be exposed on the Docker host before a tunnel can | ||
| reach it: uncomment the `3113:3113` line in `docker-compose.yml`'s `ports:` | ||
| block and run `docker compose up -d` to apply it (you can leave | ||
| `AGENTMEMORY_VIEWER_HOST`/`VIEWER_ALLOWED_HOSTS` unset for this option, since | ||
| the tunnel terminates on `127.0.0.1` itself). Then: | ||
|
|
||
| ```bash | ||
| ssh -L 3113:127.0.0.1:3113 <user>@<docker-host> | ||
| # then open http://localhost:3113 on your own machine | ||
| ``` | ||
|
|
||
| **Option B — expose it directly on your LAN.** Reasonable if this Docker | ||
| host already lives on a trusted home/office network (e.g. a NAS). Three | ||
| things have to change together — doing only one or two of them will not | ||
| work, and the failure modes are confusing enough that they're worth listing | ||
| explicitly: | ||
|
|
||
| 1. Uncomment the `3113:3113` line in `docker-compose.yml`'s `ports:` block. | ||
| 2. Uncomment and set `AGENTMEMORY_VIEWER_HOST` and `VIEWER_ALLOWED_HOSTS` in | ||
| the same file's `environment:` block. `VIEWER_ALLOWED_HOSTS` must be the | ||
| *exact* `host:port` your browser will send as the `Host` header (e.g. | ||
| `192.168.1.50:3113`) — the viewer rejects anything not on this allowlist | ||
| with a `403 forbidden host`, by design (it's a DNS-rebinding guard, not a | ||
| bug). | ||
| 3. **If you put your own reverse proxy in front of this** (nginx, Caddy, | ||
| Traefik, etc. — common on a NAS that already runs one for other | ||
| services): make sure it forwards the Host header with the port intact. | ||
| nginx's `$host` variable *strips the port* (it's meant for server-name | ||
| matching, not header passthrough) — use `proxy_set_header Host $http_host;` | ||
| instead of `$host`, or step 2's allowlist will never match and every | ||
| request 403s even though the configuration looks correct. This is the | ||
| single most confusing failure mode in this whole setup if you hit it | ||
| blind; it's called out here so you don't have to rediscover it. | ||
|
|
||
| Then `docker compose up -d` to apply, and confirm with: | ||
|
|
||
| ```bash | ||
| curl -H "Host: <your-host-ip>:3113" http://<your-host-ip>:3113/ | ||
| ``` | ||
|
|
||
| ## Rotate the HMAC secret | ||
|
|
||
| ```bash | ||
| docker compose exec agentmemory rm /data/.hmac | ||
| docker compose restart agentmemory | ||
| docker compose logs agentmemory | grep AGENTMEMORY_SECRET | ||
| ``` | ||
|
|
||
| ## Back up `/data` | ||
|
|
||
| ```bash | ||
| docker run --rm -v agentmemory-data:/data -v "$(pwd)":/backup alpine \ | ||
| tar czf /backup/agentmemory-backup.tar.gz -C /data . | ||
| ``` | ||
|
|
||
| This assumes a Linux/WSL2 shell (`$(pwd)` and `tar` both need one). On native | ||
| Windows PowerShell without WSL2, run it from a WSL2 shell instead, or | ||
| substitute `${PWD}` for `$(pwd)` — see "Windows / Docker Desktop notes" below. | ||
|
|
||
| Restore by extracting that tarball back into the same named volume. | ||
|
|
||
| ## Windows / Docker Desktop notes | ||
|
|
||
| This template builds and runs on Docker Desktop's WSL2 backend the same as | ||
| any Linux Docker host — there's nothing Windows-specific in the | ||
| Dockerfile/compose file itself. Two things that are easy to trip on: | ||
|
|
||
| - Run `docker compose` from a WSL2 shell or a terminal where Docker Desktop's | ||
| context is active, not a plain PowerShell session without Docker Desktop's | ||
| CLI integration enabled. | ||
| - If you bind-mount `/data` to a Windows path instead of using the named | ||
| volume this template defaults to, file ownership (`chown` in | ||
| `entrypoint.sh`) behaves differently across the Windows/WSL2 filesystem | ||
| boundary — stick with the named volume (`agentmemory-data:`) unless you | ||
| have a specific reason not to. | ||
|
|
||
| ## Known caveats | ||
|
|
||
| - The image builds locally on `docker compose up --build` — first build | ||
| pulls `node:22-slim` and `iiidev/iii`, subsequent builds are cache-fast | ||
| unless you bump `AGENTMEMORY_VERSION`/`III_VERSION` in the compose file's | ||
| `build.args`. | ||
| - No TLS termination is included — this template assumes either a fully | ||
| trusted local network or that you're fronting it with your own reverse | ||
| proxy (see the Host-header caution above if you do). | ||
| - arm64 hosts work — the `iiidev/iii` base image and the iii binary | ||
| selection both resolve per-architecture automatically. | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| services: | ||
| agentmemory: | ||
| build: | ||
| context: . | ||
| dockerfile: Dockerfile | ||
| args: | ||
| AGENTMEMORY_VERSION: "0.9.12" | ||
| III_VERSION: "0.11.2" | ||
| III_SDK_VERSION: "0.11.2" | ||
| restart: unless-stopped | ||
| # 3111 (REST/MCP) is published to the LAN by default — this template is | ||
| # for self-hosting on infrastructure you already control (a NAS, a | ||
| # homelab box, a Windows machine running Docker Desktop), not the open | ||
| # internet. Put your own reverse proxy / firewall in front if this host | ||
| # is internet-reachable. 3113 (viewer) is commented out: it stays | ||
| # loopback-only inside the container by default (safe), so it isn't | ||
| # reachable from another machine until you both uncomment the port below | ||
| # AND set AGENTMEMORY_VIEWER_HOST + VIEWER_ALLOWED_HOSTS (see README). | ||
| # If you terminate TLS with your own reverse proxy on this same host and | ||
| # don't want 3111 reachable from the LAN directly, bind it to loopback | ||
| # instead: "127.0.0.1:3111:3111". | ||
| ports: | ||
| - "3111:3111" | ||
| # - "3113:3113" | ||
| environment: | ||
| AGENTMEMORY_TEAM_ID: ${AGENTMEMORY_TEAM_ID:-} | ||
| AGENTMEMORY_USER_ID: ${AGENTMEMORY_USER_ID:-} | ||
| ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} | ||
| # Uncomment to expose the viewer beyond the container's own loopback — | ||
| # see the Dockerfile's EXPOSE list and the commented port above, and | ||
| # the README's reverse-proxy caution before doing this on a LAN with | ||
| # other machines on it. | ||
| # AGENTMEMORY_VIEWER_HOST: "0.0.0.0" | ||
| # VIEWER_ALLOWED_HOSTS: "<your-host-ip-or-name>:3113" | ||
| volumes: | ||
| - agentmemory-data:/data | ||
| healthcheck: | ||
| test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:3111/agentmemory/livez || exit 1"] | ||
| interval: 30s | ||
| timeout: 5s | ||
| start_period: 30s | ||
| retries: 3 | ||
| logging: | ||
| driver: json-file | ||
| options: | ||
| max-size: "10m" | ||
| max-file: "3" | ||
|
|
||
| volumes: | ||
| agentmemory-data: |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.