Getting started

Server quickstart

greatmemory's server mode is the same single binary (or a single ~158 MB container) with a few environment variables. This page takes you from the local-first defaults to a server other machines and agents can reach.

What changes in server mode

The defaults are local-first: loopback bind, SQLite, no auth. Three things change for a server:

GM_HOST=0.0.0.0                          # bind beyond loopback (default 127.0.0.1)
GM_API_KEYS=gm_long_random_key           # REQUIRED before exposing the port
GM_CORS_ORIGINS=https://app.example.com  # replaces the permissive localhost default

API keys

By default there is no auth — fine on 127.0.0.1, not fine anywhere else. Before binding 0.0.0.0 or putting greatmemory behind a proxy, set GM_API_KEYS to one or more long random values:

GM_API_KEYS="$(openssl rand -hex 32)" GM_HOST=0.0.0.0 gmem serve

Every /v1 route except /v1/healthz (left open for load-balancer probes) — and the /mcp endpoint — then requires Authorization: Bearer <key>. Keys are compared in constant time. In v0.1 they are held in server memory in plaintext; treat them like any other secret in your env or secret manager.

Clients pass the key via GM_API_KEY:

GM_URL=https://memory.example.com GM_API_KEY=gm_... gmem status

CORS

With GM_CORS_ORIGINS unset, the server allows any localhost origin — which makes local web-app development work out of the box. Setting it to an explicit comma-separated list replaces that policy entirely: only the listed origins are allowed, and the permissive localhost behavior is disabled. That is how you "turn off" the development default in production. An origin that fails to parse is a startup error, not a silent drop.

SQLite or Postgres?

SQLite (default)Postgres + pgvector
Setupnothing — the whole store is one file in GM_DATA_DIRset GM_DB=postgres://... (pgvector extension required)
Best forsingle instance, simple ops, easy backupsmanaged databases, ephemeral containers, multi-instance
Backupcopy one file (or SQLite online backup)pg_dump and your existing tooling
Persistenceneeds a durable /data volumethe database is the durable state

Either way, GM_DATA_DIR still holds the embedding model cache — it re-downloads on demand, so it never needs backing up.

Docker Compose

SQLite variant

The docker-compose.yml in the source tree builds the image and persists data (SQLite database + model cache) in a named volume:

services:
  greatmemory:
    build: .
    ports:
      - "7437:7437"
    volumes:
      - gm-data:/data
    environment:
      GM_API_KEYS: gm_change_me

volumes:
  gm-data:
docker compose up -d
curl -s http://127.0.0.1:7437/v1/healthz

The image binds 0.0.0.0:7437 inside the container (GM_HOST=0.0.0.0, GM_DATA_DIR=/data) and runs as a non-root user.

Postgres variant

For multi-instance servers or managed databases, use docker-compose.postgres.yml, which starts a pgvector/pgvector:pg17 database and points greatmemory at it via GM_DB:

services:
  greatmemory:
    build: .
    ports:
      - "7437:7437"
    volumes:
      - gm-data:/data          # still mounted: holds the embedding model cache
    environment:
      GM_DB: postgres://greatmemory:change_me@db:5432/greatmemory
      GM_API_KEYS: gm_change_me
    depends_on:
      - db

  db:
    image: pgvector/pgvector:pg17
    environment:
      POSTGRES_USER: greatmemory
      POSTGRES_PASSWORD: change_me
      POSTGRES_DB: greatmemory
    volumes:
      - pg-data:/var/lib/postgresql/data

volumes:
  gm-data:
  pg-data:
docker compose -f docker-compose.postgres.yml up -d

Change the default credentials before exposing anything.

TLS

gmem serves plain HTTP; terminate TLS in front of it — a cloud load balancer, Caddy, or nginx. Keep GM_HOST=127.0.0.1 (or a private network) and let the proxy be the only public listener:

server {
    listen 443 ssl;
    server_name memory.example.com;
    # ssl_certificate / ssl_certificate_key ...

    location / {
        proxy_pass http://127.0.0.1:7437;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Note: the streamable-HTTP MCP endpoint (/mcp) validates a loopback Host in v0.1, so it won't work through a public hostname — proxy only the /v1 API and use stdio MCP locally.

Production checklist

  • GM_API_KEYS set to long random values
  • GM_CORS_ORIGINS set to your real origins (disables the localhost-any default)
  • TLS terminated by a proxy or load balancer; greatmemory bound to loopback or a private network
  • Data dir (or Postgres) on persistent storage with backups scheduled
  • /v1/healthz wired into health checks; /v1/stats into monitoring — rss_bytes is the number to watch, and it should stay flat

Next steps

Cloud-specific walkthroughs: AWS · Azure · Google Cloud