Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions deploy/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# One-click deploy templates
# Deploy templates

Stand up agentmemory on managed infrastructure without rolling your own
Docker host. Each template ships a self-contained Dockerfile that pulls
Stand up agentmemory on managed infrastructure (fly.io, Railway, Render,
Coolify) or on a Docker host you already run yourself (NAS, homelab, plain
`docker compose`). Each template ships a self-contained Dockerfile that pulls
`@agentmemory/agentmemory` from npm at build time and copies the iii
engine binary in from the official `iiidev/iii` image — no pre-built
agentmemory image required. Storage mounts at `/data`; an HMAC secret
Expand All @@ -17,6 +18,7 @@ exec'ing the agentmemory CLI.
| [Railway](./railway/README.md) | Push from GitHub, volume in the dashboard. Easiest managed dashboard flow. | $5/month (Hobby plan flat fee) |
| [Render](./render/README.md) | Blueprint-driven; persistent disk attaches automatically. Most "set it and forget it." | $7.25/month (Starter web + 1 GB disk) |
| [Coolify](./coolify/README.md) | Self-hosted on your own VPS. Same Docker Compose stack, you own the host and the data. | VPS cost only (Hetzner CX22 ~€3.79/month) |
| [Plain Docker](./docker/README.md) | No PaaS control plane at all — a NAS, a homelab box, a Windows machine with Docker Desktop, anything that runs `docker compose`. You own the host, the proxy (if any), and the data. | Whatever hardware you already have |

## What every template guarantees

Expand All @@ -30,13 +32,16 @@ exec'ing the agentmemory CLI.
- **Only port 3111 is exposed publicly.** The viewer on port 3113
stays bound to the container's localhost. Reach it via SSH tunnel
(see each platform's README).
- **TLS upstream of the container.** Every managed platform terminates
TLS at its edge proxy; the templates publish a single internal port
(`3111`) to that proxy, never to the host. Integration plugins
configured with `AGENTMEMORY_REQUIRE_HTTPS=1` will refuse to send the
bearer over plaintext HTTP to a non-loopback host, so a
misconfigured TLS layer fails loud instead of silently leaking the
secret.
- **TLS upstream of the container (managed platforms).** fly.io,
Railway, Render, and Coolify all terminate TLS at their edge proxy;
those templates publish a single internal port (`3111`) to that
proxy, never to the host. Integration plugins configured with
`AGENTMEMORY_REQUIRE_HTTPS=1` will refuse to send the bearer over
plaintext HTTP to a non-loopback host, so a misconfigured TLS layer
fails loud instead of silently leaking the secret. **Plain Docker is
the exception** — it publishes `3111` directly to the host network
by design (see its README), so TLS termination there is on you if
you need it.

## Pick a platform

Expand All @@ -49,8 +54,12 @@ exec'ing the agentmemory CLI.
- Pick **Coolify** if you already run a VPS and want a self-hosted
control plane — same Docker Compose stack, no third-party host has
your memories.
- Pick **Plain Docker** if you already have a Docker host running
somewhere (NAS, homelab, a Windows box with Docker Desktop) and don't
want a control plane at all — you manage the proxy and TLS, if any,
yourself.

All four give you the same agentmemory API at the same port (3111)
All five give you the same agentmemory API at the same port (3111)
with the same auth model. Migrating between them later is a `tar` of
`/data` and a re-import — see each platform's README for the exact
commands.
Expand Down
38 changes: 38 additions & 0 deletions deploy/docker/Dockerfile
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"]
145 changes: 145 additions & 0 deletions deploy/docker/README.md
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
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

**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.
50 changes: 50 additions & 0 deletions deploy/docker/docker-compose.yml
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:
Loading