chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
ARG III_VERSION=0.11.2
|
||||
|
||||
FROM iiidev/iii:${III_VERSION} AS iii-image
|
||||
|
||||
FROM node:22-slim
|
||||
|
||||
ARG AGENTMEMORY_VERSION=0.9.27
|
||||
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
|
||||
|
||||
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/agentmemory-entrypoint.sh"]
|
||||
@@ -0,0 +1,113 @@
|
||||
# Deploy agentmemory on Render
|
||||
|
||||
This template runs agentmemory on a single Render Web Service with a
|
||||
persistent disk mounted at `/data`. The HMAC secret is generated on
|
||||
first boot and persisted to the disk — you capture it from the deploy
|
||||
logs exactly once.
|
||||
|
||||
## What you get
|
||||
|
||||
- A public HTTPS endpoint serving the agentmemory REST API on port 3111
|
||||
(Render injects `PORT` defaulting to 10000; we override it to 3111
|
||||
via `envVars` so the published port matches the container's bind)
|
||||
- A 1 GB persistent disk at `/data` for memories, BM25 index, and
|
||||
stream backlog
|
||||
- Render healthcheck against `/agentmemory/livez`
|
||||
- The HMAC bearer secret is generated on first boot inside the
|
||||
container and persisted to `/data/.hmac` (chmod 600); the operator
|
||||
copies it from the deploy logs once.
|
||||
|
||||
## Deploy via Render Blueprint
|
||||
|
||||
Render's one-click deploy button only auto-detects `render.yaml` at the
|
||||
repository root, which the agentmemory repo keeps clean. Use the
|
||||
dashboard's manual Blueprint flow instead:
|
||||
|
||||
1. Push the `deploy/render/` directory to a Git provider Render can
|
||||
reach (a fork of `rohitg00/agentmemory` works).
|
||||
2. In the Render dashboard, click **New +** → **Blueprint**.
|
||||
3. Point Render at the repo and the path `deploy/render/render.yaml`.
|
||||
4. Render reads the Blueprint, provisions the disk, builds the
|
||||
Dockerfile, and starts the service. The whole flow takes 3–5
|
||||
minutes on the first run.
|
||||
|
||||
## Deploy via Render Deploy Hook (one-click)
|
||||
|
||||
Once the Blueprint exists in your account, generate a Deploy Hook URL
|
||||
in the service settings. Future deploys are a single curl call:
|
||||
|
||||
```bash
|
||||
curl "https://api.render.com/deploy/srv-XXYYZZ?key=AABBCC"
|
||||
```
|
||||
|
||||
To pin a specific `@agentmemory/agentmemory` release, set the
|
||||
`AGENTMEMORY_VERSION` build arg in the service's *Environment* tab
|
||||
before the next deploy. Same for `III_VERSION`.
|
||||
|
||||
## Capture the HMAC secret
|
||||
|
||||
After the first deploy succeeds, open the service's **Logs** tab and
|
||||
search for `AGENTMEMORY_SECRET=`. You will see exactly one line of the
|
||||
form `AGENTMEMORY_SECRET=<64 hex chars>`. Copy it into your client
|
||||
environment. The secret is never printed again on subsequent boots.
|
||||
|
||||
## Verify the deployment
|
||||
|
||||
```bash
|
||||
curl https://agentmemory.onrender.com/agentmemory/livez
|
||||
# {"status":"ok"}
|
||||
```
|
||||
|
||||
For an authenticated call, your client must send `Authorization: Bearer <secret>`.
|
||||
|
||||
## Viewer access (port 3113 stays internal)
|
||||
|
||||
Render only exposes one public port per service, and we use it for
|
||||
3111. The viewer port stays bound to localhost inside the container.
|
||||
Reach it via Render's SSH:
|
||||
|
||||
```bash
|
||||
# Settings → SSH → enable for your service, copy the connection command
|
||||
ssh srv-XXYYZZ@ssh.<region>.render.com -L 3113:localhost:3113
|
||||
# now http://localhost:3113 in your browser hits the in-container viewer
|
||||
```
|
||||
|
||||
## Rotate the HMAC secret
|
||||
|
||||
```bash
|
||||
ssh srv-XXYYZZ@ssh.<region>.render.com
|
||||
rm /data/.hmac
|
||||
exit
|
||||
# trigger a redeploy from the Render dashboard or via the Deploy Hook
|
||||
```
|
||||
|
||||
After the redeploy, grab the new secret from the logs and update every
|
||||
client. Old tokens stop working immediately.
|
||||
|
||||
## Back up `/data`
|
||||
|
||||
```bash
|
||||
ssh srv-XXYYZZ@ssh.<region>.render.com "tar czf - /data" > agentmemory-$(date +%Y%m%d).tar.gz
|
||||
```
|
||||
|
||||
Render also takes daily snapshots of persistent disks automatically on
|
||||
paid plans — the SSH tarball is a belt-and-braces option you can ship
|
||||
off-platform.
|
||||
|
||||
## Cost floor and egress
|
||||
|
||||
- Starter plan web service: $7/month (0.5 CPU, 512 MB RAM).
|
||||
- 1 GB persistent disk: $0.25/GB/month, so $0.25/month for the default.
|
||||
- Bandwidth: 100 GB outbound included, then $0.10/GB.
|
||||
|
||||
See <https://render.com/pricing> for the current rate card.
|
||||
|
||||
## Known caveats
|
||||
|
||||
- Render Free tier does not support persistent disks. The Starter plan
|
||||
($7/month) is the minimum.
|
||||
- Render restarts the service on every deploy. The HMAC secret survives
|
||||
because it lives on the disk, but expect a 10–30 s gap of 502s
|
||||
during rollouts.
|
||||
- Render runs amd64 only for web services. The Dockerfile selects the
|
||||
matching iii binary automatically via `uname -m`.
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/bin/sh
|
||||
# agentmemory first-boot entrypoint.
|
||||
#
|
||||
# Runs as root so it can:
|
||||
# 1. Overwrite the npm-bundled iii-config.yaml (which binds 127.0.0.1
|
||||
# and uses relative ./data paths) with a deploy-tuned version that
|
||||
# binds 0.0.0.0 and uses absolute /data paths.
|
||||
# 2. chown the platform-mounted /data volume to the runtime user
|
||||
# (managed platforms mount volumes root-owned 755 by default).
|
||||
# 3. Generate the HMAC secret on first boot and persist it to
|
||||
# /data/.hmac (chmod 600) so the secret survives restarts.
|
||||
#
|
||||
# Then it execs the agentmemory CLI under gosu as the unprivileged
|
||||
# `node` user.
|
||||
|
||||
set -eu
|
||||
|
||||
DATA_DIR="${AGENTMEMORY_DATA_DIR:-/data}"
|
||||
HMAC_FILE="${AGENTMEMORY_HMAC_FILE:-/data/.hmac}"
|
||||
RUN_AS="node:node"
|
||||
III_CONFIG="/opt/agentmemory/node_modules/@agentmemory/agentmemory/dist/iii-config.yaml"
|
||||
|
||||
mkdir -p "$DATA_DIR"
|
||||
chown -R "$RUN_AS" "$DATA_DIR"
|
||||
|
||||
cat > "$III_CONFIG" <<'EOF'
|
||||
workers:
|
||||
- name: iii-http
|
||||
config:
|
||||
port: 3111
|
||||
host: 0.0.0.0
|
||||
default_timeout: 180000
|
||||
cors:
|
||||
allowed_origins:
|
||||
- "http://localhost:3111"
|
||||
- "http://localhost:3113"
|
||||
- "http://127.0.0.1:3111"
|
||||
- "http://127.0.0.1:3113"
|
||||
allowed_methods: [GET, POST, PUT, DELETE, OPTIONS]
|
||||
- name: iii-state
|
||||
config:
|
||||
adapter:
|
||||
name: kv
|
||||
config:
|
||||
store_method: file_based
|
||||
file_path: /data/state_store.db
|
||||
- name: iii-queue
|
||||
config:
|
||||
adapter:
|
||||
name: builtin
|
||||
- name: iii-pubsub
|
||||
config:
|
||||
adapter:
|
||||
name: local
|
||||
- name: iii-cron
|
||||
config:
|
||||
adapter:
|
||||
name: kv
|
||||
- name: iii-stream
|
||||
config:
|
||||
port: 3112
|
||||
host: 0.0.0.0
|
||||
adapter:
|
||||
name: kv
|
||||
config:
|
||||
store_method: file_based
|
||||
file_path: /data/stream_store
|
||||
- name: iii-observability
|
||||
config:
|
||||
enabled: true
|
||||
service_name: agentmemory
|
||||
exporter: memory
|
||||
sampling_ratio: 1.0
|
||||
metrics_enabled: true
|
||||
logs_enabled: true
|
||||
logs_console_output: true
|
||||
EOF
|
||||
chown "$RUN_AS" "$III_CONFIG"
|
||||
|
||||
if [ ! -s "$HMAC_FILE" ]; then
|
||||
SECRET="$(openssl rand -hex 32)"
|
||||
umask 077
|
||||
printf '%s\n' "$SECRET" > "$HMAC_FILE"
|
||||
chmod 600 "$HMAC_FILE"
|
||||
chown "$RUN_AS" "$HMAC_FILE"
|
||||
echo "================================================================"
|
||||
echo "agentmemory: generated HMAC secret on first boot"
|
||||
echo "AGENTMEMORY_SECRET=$SECRET"
|
||||
echo "Copy this value now. It will not be printed again."
|
||||
echo "Stored at: $HMAC_FILE (chmod 600)"
|
||||
echo "To rotate: delete $HMAC_FILE on the persistent volume and restart."
|
||||
echo "================================================================"
|
||||
fi
|
||||
|
||||
AGENTMEMORY_SECRET="$(cat "$HMAC_FILE")"
|
||||
export AGENTMEMORY_SECRET
|
||||
|
||||
exec gosu "$RUN_AS" agentmemory "$@"
|
||||
@@ -0,0 +1,22 @@
|
||||
services:
|
||||
- type: web
|
||||
name: agentmemory
|
||||
runtime: docker
|
||||
plan: starter
|
||||
dockerfilePath: ./deploy/render/Dockerfile
|
||||
dockerContext: ./deploy/render
|
||||
healthCheckPath: /agentmemory/livez
|
||||
autoDeploy: false
|
||||
disk:
|
||||
name: data
|
||||
mountPath: /data
|
||||
sizeGB: 1
|
||||
envVars:
|
||||
- key: PORT
|
||||
value: "3111"
|
||||
- key: AGENTMEMORY_VERSION
|
||||
value: "0.9.27"
|
||||
- key: III_VERSION
|
||||
value: "0.11.2"
|
||||
- key: III_SDK_VERSION
|
||||
value: "0.11.2"
|
||||
Reference in New Issue
Block a user