Configuration
Configuration lives in .env next to docker-compose.yml, with one exception: SMTP is set in the PocketBase admin UI, not in the file. The complete variable list with defaults is in Environment variables; this page covers the decisions rather than the table.
After any change:
docker compose up -d --buildAI
AI is off by default and the app is fully usable that way. Switch it on with KB_AI_PROVIDER:
| Provider | What it means |
|---|---|
none | No AI. Nothing ever leaves your server. This is the default. |
ollama | Your own local model. Install Ollama, ollama pull gpt-oss:20b, then set KB_AI_URL=http://IP:11434 and KB_AI_MODEL=gpt-oss:20b. Everything stays inside your network. Basic prompts; voice transcription is not included. |
api | A remote AI service compatible with the killBottleneck API — an address and token from your provider. No GPU of your own and no maintenance. |
custom | Your own endpoint honouring the same API contract. |
KB_AI_PROVIDER=ollama
KB_AI_URL=http://192.168.1.10:11434
KB_AI_MODEL=gpt-oss:20bWhich model to pick
gpt-oss:20b is the verified one — killBottleneck is tested against it. Plan for what it needs:
| Model size | ~14 GB |
| Sensible operation | a GPU with 16 GB of memory or more |
| Answer time | seconds to tens of seconds (~23 s measured for suggesting questions) |
We recommend only this one, because it is the only one we have tested. You are free to try another — Ollama offers plenty — but that is at your own risk. It is not about how "smart" the model is: killBottleneck needs a machine-readable answer (JSON), and smaller or so-called reasoning models sometimes return it truncated — the feature then silently does nothing.
Of the ones we measured, gemma3:12b (~8 GB) held up and is usable on a 12 GB card, just slower. Another model of the same size returned a broken answer on the harder task — which is why "at your own risk" is meant literally. The quickest way to check a new model is to try Suggest a plan from a goal: either a tree appears, or nothing happens.
Without a GPU the model runs on the CPU and answers take minutes; that is not enough to work with.
killBottleneck talks to Ollama directly (/api/chat) — nothing sits in between and nothing leaves your network.
Where your data goes
With any provider other than none, map data is sent to the endpoint you configured. With ollama pointing at a machine you own, that is still your network. With api or custom it is whatever you pointed it at. There is no third option hidden anywhere.
A separate model just for daily summaries
The one-line encouragement in My day is short formatted text — a smaller, faster model is plenty. KB_SUMMARY_PROVIDER / _URL / _MODEL / _TOKEN override the general AI config for that one job. Left empty, the general configuration is used.
The summary is generated in the morning at KB_SUMMARY_HOUR (default 6) only for accounts that signed in within KB_SUMMARY_ACTIVE_DAYS days (default 14, 0 = everyone); everyone else gets theirs when they open the app.
What the AI is not allowed to do
The AI never enumerates your task lists — those are computed from your data and clickable. Task names are sanitised before they enter the prompt. Turning AI off costs you exactly one line in My day; the panel itself keeps working.
Registration and the registration key
The first account to register becomes the administrator. After that, either people register themselves, or an administrator invites them from Administration.
Set KB_SETUP_CODE and every registration requires that key. Hand it to the people you want to let in. An invitation from an administrator does not need the key.
Reachable from the internet?
Set KB_SETUP_CODE before you expose the instance. Empty means open registration.
Sign in with Google
Optional — users then sign in with Google instead of e-mail and password.
- In the Google Cloud Console: APIs & Services → Credentials → Create credentials → OAuth client ID → Web application.
- Under Authorized redirect URIs add:
https://YOUR-DOMAIN/api/oauth2-redirect - Put the values in
.env:bashKB_GOOGLE_CLIENT_ID=…apps.googleusercontent.com KB_GOOGLE_CLIENT_SECRET=… docker compose up -d --build— the button appears by itself.
Empty variables = Google sign-in is off and the button is not shown.
E-mail (SMTP)
SMTP is configured in the PocketBase admin UI, not in .env:
http://SERVER-IP:8090/_/ → Settings → Mail settings
The superuser account is created on first start; the link is in docker compose logs.
What changes if you skip SMTP
E-mail is off by default and the instance is fully usable that way. Only these differ:
| With SMTP | Without SMTP | |
|---|---|---|
| Inviting a member | e-mailed with a link | the admin is shown a temporary password to hand over |
| "Forgot your password?" | self-service, link arrives by e-mail | not offered — the admin resets it (see below) |
| Reminders and daily digest | delivered per each person's preferences | in-app bell only |
The password-reset link is hidden on purpose without SMTP: the server would confirm the request, no message would arrive, and the person would wait for mail that does not exist.
Forgotten password without SMTP
For a team member, the admin resets it: Organisation settings → key icon next to the person → confirm. A new temporary password appears to hand over; the old password stops working immediately and the person is signed out everywhere. They are told in the bell that someone reset it.
For the admin, nobody can do this — there is no one above them (and the app does not offer resetting your own password either). Here the two versions differ:
- Hosted version (killbottleneck.com): e-mail always works, so the admin uses the normal "Forgot your password?" on the sign-in page. Nothing else to handle.
- Your own server without SMTP: the route goes through the PocketBase console, which you have access to as the operator:
http://SERVER-IP:8090/_/→ sign in as superuser- users collection → find your account → Change password
No superuser yet? Create one on the server (service name comes from docker-compose.yml):
docker compose exec killbottleneck /app/pocketbase superuser upsert you@example.com 'YourStrongPassword'Watch out
The console on :8090/_/ runs over plain HTTP — open it only from your local network or through an SSH tunnel, never over the internet. A password typed on the command line also stays in your shell history and is briefly visible to other users of the server; change it in the console afterwards and delete the history entry.
Recommendation
Create a second account with the admin role and keep its password in a password manager. The PocketBase route works, but it is extra work in the middle of a day when nobody can sign in.
Notification e-mails are off by default and controlled by each user's preferences. If e-mails were already reaching your users before an upgrade and you want to keep them, KB_NOTIFY_EMAIL_DEFAULT=1.
Time zone and recurring templates
TZ applies to the whole instance, not per user. It decides which zone "every Monday" and "at 5 in the morning" are counted in. A team spread across zones gets the server's zone.
If the server was powered off during KB_AUTO_HOUR, recurring projects are created at the next later hour the same day — they are not silently skipped.
Attachment limits
KB_FILES_MB caps uploaded files across the whole instance:
- empty — no limit; the self-hosting default, it is your disk
- a number — cap in MB (
5000= 5 GB) 0— uploading disabled; attachments can still be added as links, which take no space and always point at the current version of the file
Why 0 is the default on our hosted version
It is not about saving disk space, it is deliberate: we do not store other people's files. They never enter our backups, they do not turn into "we process customer documents" in a contract, and they stay where they already are. On your own server it is your disk and your call.
Automations
Only relevant if you drive goals from an automation. KB_PUBLIC_URL is the address the agent should call back on — see Environment variables → Automations for why leaving it empty can make a remote agent call itself, and why KB_ALLOW_PRIVATE_WEBHOOKS is off by default.
Instance mode
Leave KB_HOSTED empty on your own server. It exists for instances that run at a provider alongside other customers, where the instance administrator must not be able to point the AI service into a private network and probe the neighbours.

