Environment variables
Important: Poindexter runs virtually ALL configuration out of theThis document enumerates the environment variables consumed by the stockapp_settingsPostgres table, not environment variables. Env vars and~/.poindexter/bootstrap.tomlexist only to bootstrap the stack (enough config to connect to the database and start Docker). Once the worker connects, everything — model thresholds, prompt templates, QA weights, auto-publish rules, algorithm windows, SEO pinging endpoints — is changed with SQL againstapp_settings(hundreds of keys — seedocs/reference/app-settings.mdfor the full, nightly-regenerated catalog), no redeploy needed. Preferred path: runpoindexter setuponce on first install. It writes~/.poindexter/bootstrap.tomlwith 5 bootstrap values (database URL + 4 generated passwords). Thenbash scripts/start-stack.shreads bootstrap.toml and exports them for Docker. No.envfile needed. See reference/app-settings.md for the full list of DB-backed settings.
docker-compose.local.yml deployment. If you’re running a
custom configuration, start from this list.
Required
These variables are generated bypoindexter setup and stored in
~/.poindexter/bootstrap.toml. The scripts/start-stack.sh wrapper
exports them automatically for Docker. Missing any causes the stack
to fail fast with a clear error — no silent fallbacks.
| Variable | Purpose | Example |
|---|---|---|
LOCAL_POSTGRES_PASSWORD | Password for the local Postgres superuser | random 32-char hex |
GRAFANA_PASSWORD | Grafana admin password | random 32-char hex |
PGADMIN_PASSWORD | pgAdmin admin password | random 32-char hex |
poindexter setup on
first run and written to ~/.poindexter/bootstrap.toml (safe
permissions, outside the repo). No .env file is needed.
Worker authentication uses OAuth 2.1 client credentials (Phase 3
finalised in Glad-Labs/poindexter#249). poindexter setup provisions
an initial CLI client and stores the credentials encrypted in
app_settings.cli_oauth_client_id / cli_oauth_client_secret. There
is no API_TOKEN env var.
Optional (with sensible defaults)
| Variable | Default | Purpose |
|---|---|---|
API_BASE_URL | http://localhost:8002 | Base URL clients use to reach the worker |
COMPANY_NAME | Glad Labs | Publisher name used in generated content’s <author> tag |
DEFAULT_OLLAMA_MODEL | auto | Ollama model the router picks when no override |
DEVELOPMENT_MODE | true | Enables dev bypasses (token, CORS). Never set in prod. |
ENVIRONMENT | production | Log tag — also tagged on GlitchTip events. Sentry SDK is back via self-hosted GlitchTip; main.py initialises it when app_settings.sentry_dsn is set (provisioned 2026-05-09). |
GRAFANA_USER | admin | Grafana admin username |
LOCAL_POSTGRES_USER | poindexter | Local Postgres user |
LOCAL_POSTGRES_DB | poindexter_brain | Local Postgres database name |
OLLAMA_BASE_URL | http://host.docker.internal:11434 | Where OllamaClient reaches Ollama (pipeline generation) |
OLLAMA_URL | http://host.docker.internal:11434 | Where MemoryClient / auto-embed.py reaches Ollama (embeddings). Must be set to the same value as OLLAMA_BASE_URL. |
PORT | 8002 | Worker HTTP port |
SITE_DOMAIN | gladlabs.io | The operator’s public site domain |
SITE_NAME | Glad Labs | Site name in feeds + metadata |
SITE_URL | https://www.gladlabs.io | Canonical site URL |
Optional (no default — feature off unless set)
| Variable | Feature gated on it |
|---|---|
PEXELS_API_KEY | Fallback stock-photo search when image-gen is unavailable |
TELEGRAM_BOT_TOKEN | Brain daemon alerts via Telegram |
TELEGRAM_CHAT_ID | Destination chat for Telegram alerts |
OPENCLAW_GATEWAY_URL | Discord + Telegram bridge via OpenClaw |
OPENCLAW_GATEWAY_TOKEN | Bearer token for OpenClaw Tools Invoke API |
POINDEXTER_MCP_HTTP_TOOL_ALLOWLIST | Comma-separated tool names exposed by the remote MCP HTTP transport. Unset = expose all 25+ tools. Set to the recommended voice/mobile read-only list when registering a Custom Connector to a phone (see below) |
Local Ollama only in the core stack. Paid-API providers (OpenAI,
Anthropic, Google) live in community plugins, never the core. If you
install one of those plugins, it reads its own keys from app_settings
at runtime via the settings API — not from env vars.
.env.local template
A fully-populated .env.local for a standard local install looks
like this (the bootstrap script writes something equivalent):
MCP HTTP tool allowlist (POINDEXTER_MCP_HTTP_TOOL_ALLOWLIST)
The remote MCP HTTP server (mcp-server/http_server.py) exposes the
same tool registry as the stdio transport — by default that’s all 25+
tools, including write-capable ones like publish_post,
approve_post, reject_post, set_setting, and create_post.
When you register the HTTP server as a Custom Connector for the mobile
or voice Claude app, write tools become a real risk: a misheard query
plus an LLM that “follows through” can publish or reject content from
the road, exactly when you’re least able to course-correct quickly.
Set POINDEXTER_MCP_HTTP_TOOL_ALLOWLIST to the comma-separated list
below to expose only the 13 read-only tools — covers “what’s the
system state?”, “what did I decide about X?”, and “what’s in the
queue?” without giving voice mode the keys to the publishing button:
DEFAULT_VOICE_MOBILE_ALLOWLIST constant
in mcp-server/http_server.py for in-code reference.
Behaviour notes:
- Unset ⇒ all registered tools exposed (pre-#239 default).
- Empty string (
"") ⇒ explicit “expose nothing” — useful if you want the route mounted but locked down without unmounting it. - Whitespace-tolerant —
a, b ,cparses as{a, b, c}. - Unknown names silently ignored — copying the recommended list verbatim never crashes startup, even after a tool is renamed upstream.
- Stdio transport unaffected — running
python mcp-server/server.pyalways exposes the full registry, since the stdio path doesn’t go throughhttp_server.build_app.
streamable_http_app(),
so both tools/list and tools/call reflect the trimmed registry —
unlisted tools surface as Unknown tool: <name> to the client.
How the worker actually reads these
The worker resolves configuration in this order:- Environment variable — for bootstrap-only values (DATABASE_URL,
passwords). Read once at startup. Worker API auth uses OAuth JWTs
(no env var); see
poindexter auth migrate-cli. app_settingstable — for runtime-mutable values (model thresholds, prompt overrides, cost guards, feature flags). Consulted on every call viasite_config.get(key, default).- Hardcoded fallback — the
_DEFAULTSdict inservices/site_config.py. Used only when the DB value is absent AND no env var provides a value.
_DEFAULTS to change runtime behavior — that requires a
rebuild. Use the settings API or SQL against app_settings instead.
Where to go next
- Full settings catalog: reference/app-settings.md
- Local dev setup: local-development-setup.md
- Troubleshooting: troubleshooting.md