No description
  • Shell 83%
  • Dockerfile 17%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jriyuu 1b315eb188
All checks were successful
Build and push Docker image / resolve (push) Successful in 3s
Build and push Docker image / build-amd64 (push) Successful in 12s
Build and push Docker image / build-arm64 (push) Successful in 12s
Build and push Docker image / merge-manifest (push) Successful in 13s
Merge pull request 'Upload files to "/"' (#5) from jriyuu-patch-2 into main
Reviewed-on: #5
2026-10-03 16:33:25 +10:00
.forgejo/workflows Upload files to ".forgejo/workflows" 2026-10-03 16:09:01 +10:00
.env.example Upload files to "/" 2026-10-03 15:14:18 +10:00
10-gbrain.sh Upload files to "/" 2026-10-03 15:14:18 +10:00
docker-compose.yml Upload files to "/" 2026-10-03 15:14:18 +10:00
Dockerfile Upload files to "/" 2026-10-03 15:14:18 +10:00
entrypoint.sh Upload files to "/" 2026-10-03 16:32:37 +10:00
README.md Upload files to "/" 2026-10-03 15:14:18 +10:00

gbrain-docker

Unofficial container image for gbrain (MIT), packaged to give OpenClaw and other MCP agents a persistent memory server.

  • Runs gbrain serve --http: MCP at /mcp (bearer/OAuth tokens), health at /health, dashboard at /admin/
  • Auto-initialises on first start from DATABASE_URL + your embedding settings, and applies schema migrations on every start
  • Indexes a folder of markdown (/import) on a schedule, and can export the brain back to .md (/export)
  • Multi-arch: linux/amd64 and linux/arm64
  • Image: nidavellir.jriyuu.io/jriyuu-labs/gbrain, tags latest, <gbrain version> (e.g. 0.60.32.0) and <upstream commit> (12 chars), each multi-arch; -amd64 / -arm64 variants also exist

Not affiliated with gbrain's author. Bugs in the packaging belong here; bugs in gbrain itself belong upstream.

Requirements

  • Postgres with pgvector. gbrain's HTTP server doesn't support its embedded PGLite engine.
  • An embedding model gbrain supports (e.g. any model behind a LiteLLM proxy, or Voyage). The model and its dimension are fixed at first init: changing them later means re-embedding everything.

Quick start: Docker Compose (bundled Postgres)

cd compose
cp .env.example .env      # fill in passwords + embedding settings
docker compose up -d
docker compose logs -f gbrain

The bundled Postgres runs initdb/10-gbrain.sh on first start, which creates gbrain's role and database with every privilege its migrations need. Wait for [gbrain-docker] Brain ready. in the log.

Unraid

Use unraid/gbrain.xml (copy it to /boot/config/plugins/dockerMan/templates-user/, then Add Container and pick gbrain). Bring your own pgvector Postgres and prep it as below.

Bring your own Postgres: database prep

gbrain's migrations need a few things only a superuser can do. Run sql/gbrain-db-prep.sql as a superuser, following the comments in the file (find/replace the names, run part A, then part B connected to gbrain's database). In short:

Requirement Why
role has BYPASSRLS gbrain enables row-level security on its tables (migration v24)
role owns the database Postgres 15+ only lets the owner create tables in public
CREATE EXTENSION vector superuser-only
pre-created auto_rls_on_create_table event trigger superuser-only (migration v35)
role owns auto_enable_rls() gbrain alters that function later (migration v120)

Connect OpenClaw

  1. Create a token (shown once; copy it):
    docker exec -it gbrain gbrain auth create "openclaw"
    
  2. Add gbrain as an HTTP MCP server in your OpenClaw config:
    {
      "mcp": {
        "servers": {
          "gbrain": {
            "url": "http://gbrain:3131/mcp",
            "headers": { "Authorization": "Bearer gbrain_xxx" }
          }
        }
      }
    }
    
    Use the container name if both share a Docker network, otherwise http://<host-ip>:3131/mcp. Key names can differ between OpenClaw versions: openclaw mcp add shows the form yours expects.
  3. Smoke test from the gbrain console:
    gbrain remember "OpenClaw is connected" --provenance "smoke test" --entity people/me
    gbrain recall people/me
    

One brain per agent instance is the intended layout: every agent connected to a brain can read its world memories.

Configuration

Variable Default Purpose
DATABASE_URL (required) postgresql://user:pass@host:5432/db. URL-encode special characters in the password
GBRAIN_EMBEDDING_MODEL (required for auto-init) provider:model, e.g. litellm:my-embed. Also read by gbrain at runtime
GBRAIN_EMBEDDING_DIMENSIONS (required for auto-init) Vector size the model outputs
LITELLM_BASE_URL / LITELLM_API_KEY For litellm: models
VOYAGE_API_KEY, OPENAI_API_KEY For those providers. An OpenAI or Anthropic key also enables automatic fact extraction
IMPORT_DIRS /import Space-separated container paths to index each cycle
SYNC_INTERVAL 900 Seconds between imports
EXPORT_DIR /export if mounted Where the brain is exported as .md. Export-only: never import it
EXPORT_INTERVAL 3600 Seconds between exports (only changed files are rewritten)
SYNC_CMD (built from IMPORT_DIRS) Override the whole sync command
GBRAIN_PUBLIC_URL Public URL when reverse-proxied (OAuth issuer must match)
GBRAIN_HTTP_TRUST_PROXY Reverse proxy IP/CIDR, so rate limits see real client IPs
GBRAIN_ADMIN_BOOTSTRAP_TOKEN Fixed admin token for the /admin/ dashboard
GBRAIN_HTTP_CORS_ORIGIN Only for browser-based clients on other origins (e.g. https://claude.ai)
GBRAIN_PUBLISH_SKILLS true lets agents list gbrain's skills (larger tool context)
GBRAIN_AUTO_INIT true Set false to always init manually
GBRAIN_INIT_EXTRA_ARGS Extra flags for the auto-init gbrain init
GBRAIN_SKIP_READY_CHECK false Skip the startup readiness probe (escape hatch)
GBRAIN_PORT 3131 Listen port

Empty variables are treated as unset, so blank template fields are harmless.

How the container behaves

  1. Readiness. It asks the database (not the environment) whether a brain with an embedding model exists. If not, and the embedding variables are set, it runs gbrain init (never with --force, so an existing brain can't be wiped), retrying every 30s while Postgres is unreachable or unprepared.
  2. Migrations. gbrain apply-migrations --yes on every start, so pulling a new image upgrades the schema.
  3. Sync loop. Imports each IMPORT_DIRS folder, embeds anything stale, and exports on its own interval. (gbrain's sync_brain and file_upload are local-only over HTTP, which is why the container does this itself.)
  4. Serve. gbrain serve --http --bind 0.0.0.0. Binding all interfaces is required in a container; /mcp still needs a token.

Don't run gbrain self-upgrade inside the container: it's lost when the container is recreated. Pull a newer image instead.

Troubleshooting

Error Fix
permission denied to create extension "vector" Superuser: CREATE EXTENSION vector; in gbrain's database
role ... does not have BYPASSRLS privilege ALTER ROLE <user> BYPASSRLS;
may not CREATE EVENT TRIGGER (v35) Pre-create the trigger with sql/gbrain-db-prep.sql part B
must be owner of function public.auto_enable_rls (v120) ALTER FUNCTION public.auto_enable_rls() OWNER TO <user>;
getaddrinfo ENOTFOUND <name> on embedding The embedding URL uses a hostname gbrain's network can't resolve; use an IP
Embedding model "unconfigured" in the server log Set GBRAIN_EMBEDDING_MODEL / _DIMENSIONS in the container env
MINIONS HALF-INSTALLED in doctor Harmless here: autopilot wants a host service manager; the sync loop replaces it
remember prints only Usage: --provenance is required

After fixing a privilege problem, restart the container. Migrations resume where they stopped.

Building

.forgejo/workflows/build.yml resolves gbrain's latest-stable to an exact commit once, builds natively on ubuntu-latest (amd64) and a linux-arm64 runner, then merges both into multi-arch tags. Pull requests build without pushing. Scheduled runs skip when that upstream commit is already published, so latest only changes when there's something new.

Needs a ci-bot user with package write access and its token in the CI_BOT_TOKEN Actions secret.

License

Packaging: MIT (see LICENSE). gbrain: MIT, © Garry Tan and contributors.