Environment variables
Everything is configured in .env next to docker-compose.yml. Copy the template and edit:
cp .env.example .envAfter any change, rebuild — a restart is not enough:
docker compose up -d --buildOld FLOWMAP_* names still work
The variables used to be called FLOWMAP_*. Both layers — Docker Compose and the server — understand the old names, so an .env from an earlier version keeps working. Fresh installs should use KB_*.
Basics
| Variable | Default | What it does |
|---|---|---|
KB_PORT | 8090 | Port the instance listens on: http://SERVER-IP:PORT. |
KB_NAME | killbottleneck | Container name. Set a different one to run a second instance next to the first on the same host. |
TZ | UTC | Instance time zone. Decides which zone "day" and "hour" mean for recurring templates, daily summaries, deadline notices and timed reminders (calendar events and deadline reminders fire at HH:MM in this zone — with the default UTC a "14:00" reminder arrives at 16:00 Prague summer time). Set e.g. Europe/Prague. Applies to the whole instance — a team spread across zones gets the server's zone, not each user's. |
KB_AUTO_HOUR | 5 | Hour (0–23, in TZ) from which recurring templates create that day's projects. If the server was off during that hour, they are created at the next later hour the same day. |
KB_DEADLINE_HOUR | 7 | Hour of the morning deadline digest (0–23, local). Also the hour at which the reminder of an all-day calendar event arrives. |
AI
| Variable | Default | What it does |
|---|---|---|
KB_AI_PROVIDER | none | none = no AI at all (everything else works). openai = any OpenAI-compatible API (OpenAI, OpenRouter, Groq, vLLM, LM Studio…). ollama = your own local model. api = a remote AI service compatible with the killBottleneck API (address + token). custom = your own endpoint honouring the same contract. |
KB_AI_URL | (empty) | Endpoint address. For ollama the Ollama address, e.g. http://192.168.1.10:11434. For openai the base address, usually ending in /v1 — a trailing /chat/completions or a missing /v1 is corrected automatically. |
KB_AI_TOKEN | (empty) | Token for api / custom; the API key for openai (sent as Authorization: Bearer). |
KB_AI_MODEL | (empty) | For ollama the model to use (ollama pull <model> first); for openai the exact model name your provider expects, e.g. gpt-4o-mini. |
KB_AI_OPENAI_EXTRA | (empty) | openai only — JSON with extra request fields sent with every call, e.g. {"reasoning_effort":"none"} to switch reasoning off where the provider allows it (same as KB_CHAT_OPENAI_EXTRA, but for the general AI functions). also applies to the assistant (unless KB_CHAT_OPENAI_EXTRA is set) and to summaries. |
KB_AI_TRANSCRIBE_URL | (empty) | Speech-to-text endpoint. Derived from KB_AI_URL when empty. With openai you can leave it empty — dictation then goes to the same service; when filled in, this address wins. |
KB_AI_TRANSCRIBE_MODEL | whisper-1 | openai only — the transcription model (Groq: whisper-large-v3). Can also be set in Administration. |
KB_AI_MAX_PER_HOUR | 60 | openai only — AI operations one person may run per hour. Every call spends your own credit. The AI assistant on the side has its own counter with the same cap, which applies with every provider. |
KB_AI_MAX_TRANSCRIBE_PER_HOUR | 20 | Same, just for dictation. |
Daily summary
The one-line encouragement in My day can use a separate, smaller model.
| Variable | Default | What it does |
|---|---|---|
KB_SUMMARY_HOUR | 6 | Hour of morning generation (local). |
KB_SUMMARY_ACTIVE_DAYS | 14 | Generate in the morning only for accounts that signed in within N days. 0 = everyone. Inactive users get theirs when they open the app. |
KB_SUMMARY_PROVIDER | (empty) | Overrides KB_AI_PROVIDER just for summaries. |
KB_SUMMARY_URL | (empty) | Overrides KB_AI_URL just for summaries. |
KB_SUMMARY_MODEL | (empty) | Overrides KB_AI_MODEL just for summaries. |
KB_SUMMARY_TOKEN | (empty) | Overrides KB_AI_TOKEN just for summaries. |
Assistant on the side
The AI assistant in the right-hand panel. The model is looked up in the order KB_CHAT_* → KB_SUMMARY_* → the general AI settings. The panel shows only with the ollama or openai provider and needs a model with tool calling, e.g. gemma4, qwen3, gpt-oss or gpt-4o-mini.
| Variable | Default | What it does |
|---|---|---|
KB_CHAT_PROVIDER | (empty) | ollama or openai — a dedicated model just for the assistant. Empty = KB_SUMMARY_* is used, then the general AI settings. |
KB_CHAT_URL | (empty) | Address of the assistant model (like KB_AI_URL). |
KB_CHAT_MODEL | (empty) | Name of the assistant model. |
KB_CHAT_TOKEN | (empty) | API key for the assistant model. |
KB_CHAT_THINK | (empty) | Model reasoning: empty = off (fastest), otherwise low, medium, high or true. |
KB_CHAT_NUM_CTX | (empty) | ollama only — context size (num_ctx) sent with every call. Ollama otherwise defaults to 4096 tokens and would silently cut the assistant's longer prompt. |
KB_CHAT_OPENAI_EXTRA | (empty) | openai only — JSON with extra request fields, e.g. {"reasoning_effort":"none"}. Reasoning models with a low token limit can otherwise spend it all on thinking and return an error the provider still bills. |
KB_CHAT_TOOLS | (empty) | Which tool schemas the assistant model receives. Empty = only the groups the conversation needs (saves tokens; a tool the model asks for anyway is added and the call repeated). all = every tool on every call — for A/B measurements only. |
KB_AI_KVOTA_TYDEN | (empty) | Weekly cap of AI credits for the organization (the AI credits section in Organization settings). The value set in the app can only lower it, never raise it. Empty = no operator cap. |
Images in the assistant
An image is first transcribed by a model that can see images; the assistant then works with the text only. The original is not stored. Without KB_VISION_PROVIDER, KB_VISION_URL and KB_VISION_MODEL the assistant refuses images.
| Variable | Default | What it does |
|---|---|---|
KB_VISION_PROVIDER | (empty) | ollama or openai — the model that reads images (e.g. gemma4 / gemma3 via Ollama, or an OpenAI-compatible API with image input). |
KB_VISION_URL | (empty) | Address of the image model. |
KB_VISION_MODEL | (empty) | Name of the image model. |
KB_VISION_TOKEN | (empty) | API key for the image model. |
KB_VISION_NUM_CTX | 8192 | ollama only — context size for the image transcription. |
KB_VISION_OPENAI_EXTRA | (empty) | openai only — JSON with extra fields; for reasoning models {"reasoning_effort":"none"}. |
KB_VISION_ZALOHA_PROVIDER / _URL / _MODEL / _TOKEN / _NUM_CTX / _OPENAI_EXTRA | (empty) | Optional fallback model used when the first one fails or times out. |
KB_VISION_TIMEOUT | 45 | Seconds per transcription attempt. Keep the total well under your reverse proxy timeout (Cloudflare around 100 s). |
KB_VISION_POKUSY | 0 | Extra retries on the first model before the fallback is tried. |
KB_CHAT_MAX_IMG_MB | 1.2 | Largest accepted image in MB. The browser shrinks screenshots to about 250 kB on its own. |
KB_CHAT_NAHLEDU | 3 | How many small image thumbnails one conversation keeps; older images keep only the transcript. |
KB_AI_IMG_VAHA | 3 | How many turns of the hourly cap (KB_AI_MAX_PER_HOUR) one image turn uses. |
KB_AI_PDF_VAHA | 2 | How many turns of the hourly cap one turn with an attached PDF uses (the assistant only receives the page text; merging and splitting PDFs run in the browser and cost nothing). |
Access and sign-in
| Variable | Default | What it does |
|---|---|---|
KB_SETUP_CODE | (empty) | Instance registration key. When set, every registration requires it. Empty = anyone who knows the address can register. The first account registered is always the administrator. |
KB_GOOGLE_CLIENT_ID | (empty) | Google OAuth client ID. Empty = the "Sign in with Google" button is not shown. |
KB_GOOGLE_CLIENT_SECRET | (empty) | Google OAuth client secret. |
KB_GOOGLE_PICKER_API_KEY | (empty) | Enables picking attachments straight from Google Drive. Needs the OAuth client above plus the "Google Picker API" enabled in the same Google Cloud project. Files picked this way are stored as links — they never leave Drive. |
Set a registration key before you expose the instance
On a machine reachable from the internet, an empty KB_SETUP_CODE means anyone who finds the address can create an account.
E-mail (SMTP) is not configured here — it lives in the PocketBase admin UI, see Configuration → E-mail.
Automations
Only needed if you actually use automations on goals.
| Variable | Default | What it does |
|---|---|---|
KB_PUBLIC_URL | (empty) | Public address of this instance, sent to the agent as callback_url so it can report back. Any address the agent can reach works — on a self-host a LAN address is fine. When unset, the "Application URL" from the PocketBase admin UI is used, which after installation is http://localhost:8090 — an agent on another machine would then call itself. The agent registry in the app shows the effective address and warns about localhost. |
KB_AGENT_TIMEOUT_MIN | 90 | How many minutes an automation may run before the watchdog marks it failed. |
KB_ALLOW_PRIVATE_WEBHOOKS | (empty) | 1 allows agent webhooks to target private networks (10.x, 192.168.x, localhost). Disabled by default. |
Why private webhooks are off by default
Without that guard, the server can be pointed at your internal network and used to scan it. Turn it on only when the automation target (n8n, for instance) genuinely runs on the same LAN.
Limits and instance mode
| Variable | Default | What it does |
|---|---|---|
KB_FILES_MB | (empty) | Cap in MB for uploaded attachments across the whole instance. Empty = no limit (the self-hosting default — it is your disk). 0 = uploading disabled, attachments can only be added as links. |
KB_HOSTED | (empty) | 1 marks an instance that runs at a provider alongside other customers. The instance administrator then may not point the AI service into a private network. On your own server leave this empty — a local Ollama on the LAN is the normal setup there. |
KB_SHARE_INVITE_DAILY_CAP | 20 | How many shared-project invitations (to addresses without an account) one user may send per day. An address gets at most one per project. |
KB_SHARE_INVITE_INSTANCE_CAP | 50 | Daily cap of these invitations for the whole instance — protects the mail quota. |
KB_NOTIFY_EMAIL_DEFAULT | (empty) | Notification e-mails are off by default and driven by per-user preferences. Set to 1 to keep the old "e-mail on until the user turns it off" behaviour after an upgrade. |
KB_REPORT_TO | (empty) | Address that bug reports and ideas from the app are sent to. Empty means the feature does not exist on this instance: the menu item is not shown and the route returns 404, so nothing ever leaves. Set your own address to collect reports from your users — the reporter's address goes into Reply-To, so you can answer straight from your inbox. Requires working SMTP. |
Notifications
The defaults are sane. Change them if notices are too noisy, or if an automation of yours legitimately produces more than the cap.
There is no "unlimited"
0 is not a magic value here — it means the cap is reached immediately. Raise the number instead of zeroing it.
| Variable | Default | What it does |
|---|---|---|
KB_NOTIFY_DIGEST_HOUR | 8 | Hour of the daily e-mail digest (0–23, local TZ). |
KB_REMINDER_CATCHUP_H | 48 | Catch-up window for timed reminders (hours, 0–720). After an outage, reminders whose time is older than this are only logged, not sent — so restoring an old backup does not flood the bell with meetings that already happened. Younger missed reminders are sent right after start. |
KB_NOTIFY_DAILY_CAP | 50 | Maximum in-app notices per recipient per day. Above the cap the individual rows are replaced by one growing summary ("+N more") — nothing is silently lost. |
KB_NOTIFY_EMAIL_DAILY_CAP | 10 | Maximum notification e-mails per recipient per day. Above the cap e-mails are dropped (the in-app notice still appears). |
KB_NOTIFY_COALESCE_MIN | 10 | Notices for the same recipient arriving within this many minutes are merged into one message. |
KB_UVODNI_MAPA | 1 | Create the two starter projects (tour + trial project) for every new user. 0 = new accounts start empty. |
KB_PURPOSE_ASK | 1 | Ask the first admin what the instance is for (company / family / solo) on first login. 0 = never ask (defaults to company). Off automatically when KB_UVODNI_MAPA=0. |
Updates and versioning
| Variable | Default | What it does |
|---|---|---|
KB_UPDATE_CHECK | 1 | The signed-in user's browser asks the GitHub API whether a newer release exists; the About dialog then offers a link. The instance itself sends nothing anywhere. 0 turns the check off. |
KB_UPDATE_REPO | (empty) | Where releases are read from. Empty = the official repository. Set it only for your own fork. |
KB_VERSION | dev | Build argument, not an .env variable — pass it on the command line: KB_VERSION=$(git describe --tags --dirty) docker compose up -d --build. Left at dev, the update check is not offered. |
No telemetry
The update check runs in the user's browser against GitHub. The instance never phones home, so nothing about your installation reaches us.

