Docs / API integration
API keys, access control, and keeping secrets out of your config
apiKeys authentication has no per-key rate limits or user permissions; use env macros for secrets.
Requiring a key
By default llama-swap is unauthenticated. Add apiKeys and every request needs
one:
apiKeys:
- "sk-hunter2"
Clients may present it as Authorization: Bearer <key>, x-api-key: <key>, or
HTTP Basic. The web UI and everything under /api/ are covered too.
A handful of static files stay reachable without a key regardless:
/favicon.ico, /ui/site.webmanifest, and the two icons it references
(/ui/web-app-manifest-192x192.png, /ui/web-app-manifest-512x512.png).
Browsers fetch all of these themselves — the favicon for the tab, the
manifest and its icons to decide whether to offer installing llama-swap as a
PWA — and have no way to attach your API key to those requests.
Generate a real one:
$ printf "sk-%s\n" "$(head -c 48 /dev/urandom | base64)"
Multiple keys are allowed, which is how you rotate without downtime: add the new key, move clients over, remove the old one.
All keys are equivalent. llama-swap has no per-key rate limiting, user accounts, roles, or per-key permissions. Put a reverse proxy or API gateway in front of llama-swap when you need those controls.
apiKeys is not a substitute for a firewall. llama-swap starts processes
on your machine. Do not expose it to the internet on the strength of a bearer
token alone.
Keep the keys out of the file
Use env macros so the config itself is safe to commit:
apiKeys:
- "${env.LLAMA_SWAP_KEY}"
- "${env.LLAMA_SWAP_KEY_ROTATE}"
${env.VAR} is substituted before anything else. If the variable is not set,
config loading fails with an error — which is what you want. A typo becomes a
startup failure rather than an instance running with an empty key list.
The same applies anywhere a secret appears:
peers:
openrouter:
proxy: https://openrouter.ai/api
apiKey: ${env.OPENROUTER_API_KEY}
models: [z-ai/glm-4.7, moonshotai/kimi-k2-0905]
models:
hf-model:
env:
- "HF_TOKEN=${env.HF_TOKEN}"
cmd: llama-server --port ${PORT} -hf some/repo
How peer keys are used
peers.*.apiKey is injected into outgoing requests to that peer, as both
Authorization: Bearer <key> and x-api-key: <key>. Leave it blank and no key
is added. It accepts a macro, so use ${env.*}.
This is the key llama-swap presents to the peer. It is unrelated to the
apiKeys clients present to llama-swap.
What ends up in your config file
Worth being aware of, because config files get pasted into issues and chats:
apiKeys— literal keys, unless you used env macrospeers.*.apiKey— literal peer keys, samemodels.*.env— literalNAME=valuepairsmodels.*.cmd/cmdStop— full command lines, which often carry--api-keyflags and absolute pathsmacros— after env substitution has already run
That last one is the non-obvious one: a macro like
llama: "llama-server --api-key ${env.KEY}" holds the resolved secret once the
config is loaded.
Before sharing a config, strip those. Redact rather than delete so the shape of the problem survives.
Related
reference/config/apiKeys,reference/config/peersguides/configuration/macros— how env macros resolve