- Shell 83%
- Dockerfile 17%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .forgejo/workflows | ||
| .env.example | ||
| 10-gbrain.sh | ||
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| README.md | ||
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/amd64andlinux/arm64 - Image:
nidavellir.jriyuu.io/jriyuu-labs/gbrain, tagslatest,<gbrain version>(e.g.0.60.32.0) and<upstream commit>(12 chars), each multi-arch;-amd64/-arm64variants 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
- Create a token (shown once; copy it):
docker exec -it gbrain gbrain auth create "openclaw" - Add gbrain as an HTTP MCP server in your OpenClaw config:
Use the container name if both share a Docker network, otherwise{ "mcp": { "servers": { "gbrain": { "url": "http://gbrain:3131/mcp", "headers": { "Authorization": "Bearer gbrain_xxx" } } } } }http://<host-ip>:3131/mcp. Key names can differ between OpenClaw versions:openclaw mcp addshows the form yours expects. - 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
- 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. - Migrations.
gbrain apply-migrations --yeson every start, so pulling a new image upgrades the schema. - Sync loop. Imports each
IMPORT_DIRSfolder, embeds anything stale, and exports on its own interval. (gbrain'ssync_brainandfile_uploadare local-only over HTTP, which is why the container does this itself.) - Serve.
gbrain serve --http --bind 0.0.0.0. Binding all interfaces is required in a container;/mcpstill 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.