Every KRAKEN_* environment variable the Panel reads, with its default and what it does — generated from internal/panel/config/config.go so it cannot drift from the code.
The Panel is configured entirely from the environment, read once at startup. Its
defaults make it runnable out of the box for local development, which is not the
same thing as runnable in production. Installing the
Panel covers the handful that matter on a real deploy.
Where the variables go depends on how you run it: deploy/.env (compose),
/etc/kraken/panel.env (systemd), or the process environment.
core
variable
what it does
KRAKEN_ENVdefault dev
Env is the deployment environment: "dev", "staging", or "prod".
KRAKEN_HTTP_ADDRdefault :8080
HTTPAddr is the listen address for the HTTP API, e.g. ":8080".
KRAKEN_DATABASE_URLdefault unset
DatabaseURL is the Postgres DSN. Empty selects the in-memory store (dev only).
KRAKEN_CONFIG_FILEdefault <stateDir>/panel.json
ConfigFile is the path to the JSON file holding UI-entered settings that must live outside the database (currently just the database_url).
KRAKEN_SESSION_TTLdefault 24h
SessionTTL is how long an authenticated session remains valid.
bootstrap admin
variable
what it does
KRAKEN_BOOTSTRAP_ADMIN_USERdefault admin
Bootstrap admin — created on first start if no users exist. If the password is left empty a strong random one is generated and logged once at startup, so there is no weak default credential.
KRAKEN_BOOTSTRAP_ADMIN_PASSWORDdefault unset
Bootstrap admin — created on first start if no users exist. If the password is left empty a strong random one is generated and logged once at startup, so there is no weak default credential.
browser origins
variable
what it does
KRAKEN_ALLOWED_ORIGINSdefault unset
AllowedOrigins is the WebSocket Origin allowlist (host[:port] patterns, "*" wildcards allowed). Empty falls back to localhost dev origins. Same-origin requests are always permitted regardless of this list.
first-run setup
variable
what it does
KRAKEN_SETUP_ALLOWED_CIDRSdefault unset
SetupAllowedCIDRs restricts the /setup/* API surface (first-run wizard, datastore configuration, local enrollment) to requests whose real TCP peer falls inside one of these CIDRs (single IPs allowed too). Defaults to loopback + private ranges (RFC 1918, link-local, IPv6 ULA) so setup is never drivable from the public internet, even with valid credentials.
content security policy
variable
what it does
KRAKEN_CSPdefault enforce
CSPMode selects how the Content-Security-Policy header is emitted: "enforce" (default), "report-only" for a dry run that reports violations without blocking, or "off" for the escape hatch when a reverse proxy already sets its own policy (two CSP headers intersect, which is usually stricter than either author intended).
KRAKEN_CSP_SCRIPT_SRCdefault unset
CSPScriptSrc and CSPConnectSrc are extra sources appended to those directives. The shipped policy is same-origin only; a Panel fronted by a CDN that injects a script (Cloudflare Web Analytics, for one) needs its host allowed here rather than in the default everyone else inherits.
KRAKEN_CSP_CONNECT_SRCdefault unset
CSPScriptSrc and CSPConnectSrc are extra sources appended to those directives. The shipped policy is same-origin only; a Panel fronted by a CDN that injects a script (Cloudflare Web Analytics, for one) needs its host allowed here rather than in the default everyone else inherits.
panel → agent mTLS
variable
what it does
KRAKEN_TLS_CERTdefault unset
Mutual-TLS for Panel→Agent gRPC. When all three are set the Panel dials Agents over mTLS; otherwise it falls back to an insecure connection (dev).
KRAKEN_TLS_KEYdefault unset
Mutual-TLS for Panel→Agent gRPC. When all three are set the Panel dials Agents over mTLS; otherwise it falls back to an insecure connection (dev).
KRAKEN_TLS_CAdefault unset
Mutual-TLS for Panel→Agent gRPC. When all three are set the Panel dials Agents over mTLS; otherwise it falls back to an insecure connection (dev).
certificate authority
variable
what it does
KRAKEN_CA_CERTdefault unset
CA signing material. When set, the Panel acts as the certificate authority for Agent enrollment: it issues short-lived Agent certs in response to a one-time bootstrap token. Usually CACert == TLSCA.
KRAKEN_CA_KEYdefault unset
CA signing material. When set, the Panel acts as the certificate authority for Agent enrollment: it issues short-lived Agent certs in response to a one-time bootstrap token. Usually CACert == TLSCA.
quickstart (single host)
variable
what it does
KRAKEN_LOCAL_AGENT_ADDRdefault 127.0.0.1:9090
LocalAgentAddr is the gRPC address of the co-located Agent used by quickstart.
KRAKEN_QUICKSTARTdefault true in dev, false otherwise
Quickstart defaults on in dev; override explicitly with KRAKEN_QUICKSTART.
state on disk
variable
what it does
KRAKEN_STATE_DIRdefault data
KRAKEN_STATE_DIR groups all Panel-owned state (config file, secrets key, generated CA) under one directory so a systemd unit or a container just needs to point at /var/lib/kraken. Legacy default is "data" (cwd-relative) so existing dev setups keep working unchanged.
secrets at rest
variable
what it does
KRAKEN_SECRETS_KEYdefault unset
ResolveSecretsKey returns the 32-byte master key used to encrypt at-rest DB secrets. Precedence: KRAKEN_SECRETS_KEY (base64) → the config file → a freshly generated key persisted to the config file. fromEnv reports the first case.
reverse tunnel
variable
what it does
KRAKEN_TUNNEL_ADDRdefault :9443
TunnelAddr is the listen address for the reverse-tunnel listener that tunnel-mode Agents dial into (mTLS only; see docs/design/reverse-connections.md). Default ":9443"; set KRAKEN_TUNNEL_ADDR=off to disable the listener entirely. The listener also requires CA signing material — with no CA there is nothing to authenticate agents against, so it stays off.
sftp proxy (tunnel nodes)
variable
what it does
KRAKEN_SFTP_PROXYdefault on
SFTPProxyHost is the host part of the Panel-side SFTP proxy endpoints for tunnel-mode nodes. Each tunneled node gets its own port (raw SSH carries no routing header a pass-through proxy could read), allocated upward from SFTPProxyBasePort and persisted on the node record. Default base 2222 — :2022 collides with a co-located Agent's own SFTP server. Set KRAKEN_SFTP_PROXY=off to disable the proxy.
KRAKEN_SFTP_PROXY_BASE_PORTdefault 2222
SFTPProxyHost is the host part of the Panel-side SFTP proxy endpoints for tunnel-mode nodes. Each tunneled node gets its own port (raw SSH carries no routing header a pass-through proxy could read), allocated upward from SFTPProxyBasePort and persisted on the node record. Default base 2222 — :2022 collides with a co-located Agent's own SFTP server. Set KRAKEN_SFTP_PROXY=off to disable the proxy.
behind a reverse proxy
variable
what it does
KRAKEN_TRUSTED_PROXIESdefault unset
TrustedProxies lists the CIDRs (bare IPs allowed) of reverse proxies whose forwarding headers the Panel may believe. EMPTY BY DEFAULT: with no trusted set, X-Forwarded-For is attacker-supplied and the Panel uses the real TCP peer for everything. Set it when the Panel sits behind Caddy/nginx/Traefik or a Cloudflare Tunnel — otherwise every request looks like it came from the proxy, which collapses the per-IP rate limiters into one shared bucket and files every audit row under the proxy's address. See clientIP in internal/panel/api.
rate limits
variable
what it does
KRAKEN_RATE_LIMITSdefault all
RateLimits selects which limiters run: "all" (the default; "on" is the historical alias), "login" for the login-side limiters only, "downloads" for the token-redemption limiter only, or "off" for neither — each logged loudly at startup when it is not "all". The switch is split because the two surfaces fail differently: behind a NAT that erases the client address the per-IP login bucket is shared by the whole internet and an operator may want it out of the way, while the redemption limiter is still worth having. An unrecognized value is a startup error.
KRAKEN_RATE_LIMIT_IP_SKIPdefault unset
RateLimitIPSkip lists the CIDRs (bare IPs allowed) whose resolved client address is EXEMPT from the per-IP limiters. It exists for one situation: a NAT that rewrites every source address to one gateway — Docker Desktop's 192.168.65.1 is the case that prompted it — where the per-IP bucket is not a limit on anybody in particular and locks the whole internet out together. Exempting that address leaves the per-username login limiter, which needs no IP at all, doing the real work. Empty by default, and not a substitute for naming a real proxy in KRAKEN_TRUSTED_PROXIES.
logging
variable
what it does
KRAKEN_LOG_LEVELdefault info
LogLevel is the Panel's slog level: debug, info (default), warn, error. Several diagnostics — a rejected download token, for one — are Debug on purpose, because they are writable by an unauthenticated caller; this is how an operator turns them on when actually diagnosing something.
audit log
variable
what it does
KRAKEN_AUDIT_RETENTION_DAYSdefault 90
AuditRetentionDays is how many days of audit log the Panel keeps. A daily job deletes entries older than the window in batches, shortly after startup and every 24 hours after that, and the console reads this number rather than promising a window nothing enforced. Set it to 0 to keep every entry forever — the right answer when an external log shipper or a compliance rule owns the retention instead. Must be a whole, non-negative number of days; anything else stops the Panel at startup rather than quietly pruning on a schedule nobody chose.
Reading the defaults
An unset default means empty, and the description says what empty selects.
Sometimes that is not "nothing": an empty KRAKEN_DATABASE_URL selects the
in-memory store, and an empty KRAKEN_TRUSTED_PROXIES means no forwarding
header is believed.
A list is comma-separated, trimmed, with empty entries dropped.
A duration takes either a Go duration (24h) or a plain number of
seconds.
Booleans take anything Go's strconv.ParseBool accepts: true, 1,
false, 0. An unparseable value falls back to the default rather than
failing.
Two variables refuse to be quietly wrong, and which way each list fails is the
reason they differ. An unparseable entry in KRAKEN_TRUSTED_PROXIES is a
startup error, because a typo that silently emptied that list would leave
the Panel running and wrong. KRAKEN_SETUP_ALLOWED_CIDRS keeps skip-and-warn,
since that list fails closed: a dropped entry denies access rather than granting
it.
The ones worth knowing
KRAKEN_SECRETS_KEY: base64 of 32 bytes. It seals every at-rest secret,
and losing it makes every stored secret unrecoverable. See installing the
Panel.
KRAKEN_TRUSTED_PROXIES: empty unless a proxy really fronts the Panel,
and correct when one does. It decides what the audit log records and whether
the rate limiters protect anybody. See behind a reverse
proxy.
KRAKEN_TUNNEL_ADDR: the :9443 listener a tunnel-mode node dials. Bind
it to loopback and the fleet goes offline. See ports and
firewall.
The Agent carries its own configuration, with a file, flags and environment
variables of its own: Agent configuration.
A few settings live in the database and are edited in the UI instead of the
environment: the datastore DSN entered in the first-run wizard, the session TTL,
the WebSocket origins. Where an environment variable exists for one of those,
the environment wins and the UI shows the field as locked, so a host driven
by compose or systemd cannot be changed out from under its unit file by somebody
clicking around.