Step 1 of the Scribe -> Grimoire rename: every capitalised "Scribe" in prose
becomes "Grimoire" ("Fabled Scribe" -> "Fabled Grimoire") across the UI,
the PWA manifest and page title, the MCP instructions and tool docstrings,
hook and skill text, docs and README, with the tests that assert on that
prose moving with it. Old migrations keep their wording.
Identifiers are untouched here: the package, plugin name, MCP server key,
hook file names, env vars, the .scribe marker and FabledScribe repo/image
names move in steps 2 and 3, along with prose that quotes them.
The sweep matched "Scribe" only as a whole word, so describe/subscribe and
friends are untouched. The longer name took the MCP instructions one
character over their 1,600 budget; two phrases are shortened to fit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.7 KiB
Configuration
Grimoire reads its configuration from environment variables. Most settings people change day to day (registration, SMTP, retrieval thresholds, backups, forge connections) live in Settings in the web UI instead.
Any variable marked secret can also be read from a file: set <NAME>_FILE to the path, for example a Docker secret at /run/secrets/scribe_key.
Environment variables
Core
| Variable | Default | Description |
|---|---|---|
DATABASE_URL (secret) |
postgresql+asyncpg://scribe:scribe@localhost:5432/scribe |
PostgreSQL connection string, using the asyncpg driver |
SECRET_KEY (secret) |
dev-secret-change-me |
Signs sessions and seals stored credentials. Set it before first use and keep it (see below) |
BASE_URL |
http://localhost:5000 |
Public URL, used in email links and OIDC redirects |
SECURE_COOKIES |
false |
true when Grimoire is served over HTTPS |
TRUST_PROXY_HEADERS |
false |
true behind a reverse proxy, to read the client IP from X-Forwarded-For / X-Real-IP |
LOG_LEVEL |
INFO |
DEBUG, INFO, WARNING or ERROR |
LOG_RETENTION_DAYS |
90 |
Days of app logs to keep |
FASTEMBED_CACHE_DIR |
/data/fastembed-cache |
Where the embedding model is stored after its first download |
Sign-in
| Variable | Default | Description |
|---|---|---|
LOCAL_AUTH_ENABLED |
true |
false turns off username/password login, leaving SSO only |
OIDC_ISSUER |
— | OIDC issuer URL |
OIDC_CLIENT_ID |
— | OIDC client ID |
OIDC_CLIENT_SECRET (secret) |
— | OIDC client secret |
OIDC_SCOPES |
openid profile email |
Scopes to request |
SSO turns on when the issuer, client ID and secret are all set. See SSO / OAuth.
Admins can set SMTP in Settings; these are the defaults until they do.
| Variable | Default |
|---|---|
SMTP_HOST |
— |
SMTP_PORT |
587 |
SMTP_USERNAME |
— |
SMTP_PASSWORD (secret) |
— |
SMTP_FROM_ADDRESS |
— |
SMTP_FROM_NAME |
Fabled Grimoire |
SMTP_USE_TLS |
true |
Integrations
| Variable | Default | Description |
|---|---|---|
PLUGIN_MARKETPLACE_URL |
this repo's git URL | The git URL shown in the plugin install command under Settings → MCP Access. An admin can override it in Settings |
FORGE_KIND, FORGE_BASE_URL, FORGE_TOKEN (secret) |
— | A git forge connection for admins' projects, so a token can live in a Docker secret. Each user can add their own under Settings → Integrations; a stored connection for the same host wins |
FORGE_WEBHOOK_SECRET (secret) |
— | Verifies push webhooks from the forge |
SEARXNG_URL |
— | A SearXNG instance, listed as the web-search backend under Settings → Integrations |
Running it
Quick start
docker-compose.quickstart.yml runs the published image with its own database:
SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_hex(32))') \
docker compose -f docker-compose.quickstart.yml up -d
Open http://localhost:5000. The first account registered becomes the admin; after that, registration stays closed until an admin opens it in Settings or sends an invite.
From source
cp .env.example .env # then set SECRET_KEY
docker compose up --build
Docker Swarm
docker-compose.prod.yml is a stack file: the app and database on a private overlay network, with SECURE_COOKIES and TRUST_PROXY_HEADERS on. Provide DB_PASSWORD and SECRET_KEY in the environment:
DB_PASSWORD=... SECRET_KEY=... docker stack deploy -c docker-compose.prod.yml scribe
The shipped files leave out healthchecks and restart policies on purpose. The app waits for its database on startup, and the orchestrator's defaults restart it if it ever exits.
Volumes
- Database (
pgdata): everything Grimoire stores. - App data (
/data): the embedding model cache and diagnostics. Losing it costs a re-download, nothing else.
Back up the database with Settings → Data → Scheduled backups (Backups).
Behind a reverse proxy
Grimoire doesn't terminate TLS. Put it behind Nginx, Traefik or Caddy, forward to port 5000, and keep port 5000 off the internet. Set SECURE_COOKIES=true, TRUST_PROXY_HEADERS=true and BASE_URL.
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# MCP responses can stream.
proxy_buffering off;
proxy_read_timeout 600s;
}
With TRUST_PROXY_HEADERS=true, make sure the proxy replaces any X-Forwarded-For the client sends.
Security checklist
- Set a strong
SECRET_KEY, and keep it. Forge tokens and the backup destination's S3 secret are sealed under a key derived from it, so a copy of the database alone can't read them. If the key changes (say, a restore onto an instance with a different key), Settings marks those credentials and asks for them again; nothing else breaks. The app logs a warning at startup while the default key is in use, and refuses to start with it whenSECURE_COOKIES=true. SECURE_COOKIES=truewhenever Grimoire is served over HTTPS.- Registration is open only for the first account. Invite people, or open it briefly from Settings.
- Signing everyone else out: changing a password ends that user's other sessions; Settings → Account has a button for it too.
- API keys are per user, shown once, and can be read-only. Revoke any you no longer use under Settings → MCP Access.