Skip to content

Configuration

All the environment variables the kubelatch binary reads, with their default value, format, and what they do. There is no config file or server flags.

At startup, kubelatch validates all the variables and, if there are errors, shows them all together and does not start. The CLI subcommands read the same variables with the same rules: they also need DATABASE_URL, KUBELATCH_BASE_URL and KUBELATCH_ENCRYPTION_KEY.

Each variable has an anchor with its name in lowercase: configuration.md#kubelatch_base_url, configuration.md#database_url, configuration.md#github_app_id.

Common formats

Format What it accepts
Duration A number of days <n>d (no leading zeros, up to 3650d) or a Go duration greater than zero (720h, 90m), up to 10 years.
List Comma-separated values; spaces around them and empty items are ignored.
Boolean Exactly true or false. Any other value is an error.
URL Absolute, http or https, with no user, query (?) or fragment (#).

Server

Variable Required Default Format What it does
KUBELATCH_LISTEN No :8080 host:port Listen address and port. The manifests in deploy/k8s/base use :8443.
KUBELATCH_BASE_URL Yes URL Public URL kubelatch is reached at. It is normalized: no trailing slash, scheme and host lowercased, no default port. Decides the Secure attribute of cookies (if https), the only trusted origin for cross-origin request protection, the URL of invitation links (<base>/cuenta#kli_…), the server of the kubeconfigs (<base>/clusters/<id>), the audience (aud) GitHub Actions tokens must carry, and the GitHub App callback (<base>/api/auth/github/callback).
KUBELATCH_ENCRYPTION_KEY Yes Standard Base64, exactly 32 bytes Master key. From it, with distinct labels, kubelatch derives the key that signs session cookies, the one that signs GitHub login state cookies, and the AES-256-GCM key that encrypts each cluster's ServiceAccount tokens. Rotating it closes every session and requires re-pasting each cluster's tokens.
KUBELATCH_INSTANCE_ID No default Kubernetes label value: alphanumeric, -, _, ., up to 63 characters Value of the kubelatch.io/instance label on the objects kubelatch creates in the clusters. That instance's cleanup and garbage collector only touch their own objects, which lets you move a cluster to another instance. Cleanup does restore the shared kubelatch-proxy ClusterRole to the uids-only rule. It is not meant for two instances to share a cluster at the same time.
KUBELATCH_TRUSTED_PROXIES No empty List of CIDRs (10.0.0.1/32 for a single host) Networks from which X-Forwarded-For is trusted, read right to left up to the first untrusted hop. Affects the source IP recorded in the audit log and the control plane, and the per-IP limits on login, the CI exchange and proxy failures. A bare IP is an error, and so is a prefix wider than /8 (IPv4) or /16 (IPv6). Empty behind an L4 LoadBalancer; mandatory behind an Ingress.

To generate KUBELATCH_ENCRYPTION_KEY:

head -c32 /dev/urandom | base64

Database

Variable Required Default Format What it does
DATABASE_URL Yes Postgres connection string (postgres://user:password@host:5432/kubelatch?sslmode=require) Database holding all state. kubelatch applies its migrations at startup, and so does every CLI subcommand.

TLS

Variable Required Default Format What it does
KUBELATCH_TLS_CERT With KUBELATCH_TLS_KEY empty Path to a PEM file Server certificate. With both variables, kubelatch serves HTTPS (TLS 1.2 or higher, HTTP/2 and HTTP/1.1). Reloads the pair when it changes on disk (checks at most every 10 s); an invalid pair is ignored and logged. An invalid pair at startup prevents startup. Every hour it warns if fewer than 30 days of validity remain. Without them, kubelatch serves plain HTTP.
KUBELATCH_TLS_KEY With KUBELATCH_TLS_CERT empty Path to a PEM file Certificate's private key. The two variables go together: one without the other is an error.
KUBELATCH_KUBECONFIG_CA No empty Path to a regular PEM file, CERTIFICATE blocks only, up to 1 MiB CA embedded as certificate-authority-data in every kubeconfig it issues. Only needed with a private CA. A block that is not a certificate (a key pasted by mistake) prevents startup.

Permissions

Variable Required Default Format What it does
KUBELATCH_PROTECTED_NAMESPACES No empty List of namespace names Namespaces that admit no permission of any tier, in addition to kube-system, kube-public, kube-node-lease and kubelatch-system, which are always protected.
KUBELATCH_REQUIRE_PSA No true Boolean With false, developer, debugger and admin stop requiring the namespace to carry pod-security.kubernetes.io/enforce=baseline or restricted. Permisos (Permissions) warns about it. See Tiers before changing it.

Limits and TTLs

Variable Required Default Format What it does
KUBELATCH_MAX_TTL_USER No 30d Duration Maximum lifetime of a person's credential.
KUBELATCH_MAX_TTL_BOT No 90d Duration Maximum lifetime of a bot's credential, including CI ones.

Audit

Variable Required Default Format What it does
KUBELATCH_AUDIT_RETENTION No 90d Duration of at least 1 day, or 0 / 0d How long audit_events and control_events are kept. A periodic job on each replica deletes hourly (the first pass, one minute after startup), in batches of 5,000 rows. 0 or 0d disables deletion. The same job deletes CI jtis one hour after their token expires, regardless of this value.

CI

Variable Required Default Format What it does
KUBELATCH_CI_TOKEN_TTL No 1h Duration, no greater than KUBELATCH_MAX_TTL_BOT Lifetime of the credentials a GitHub Actions workflow gets when it exchanges its OIDC token.
KUBELATCH_GITHUB_ACTIONS_ISSUER No https://token.actions.githubusercontent.com URL; http only on a loopback host Issuer (iss) of GitHub Actions OIDC tokens. Its keys are read from <issuer>/.well-known/jwks. For GitHub Enterprise Server: https://<host>/_services/token.

Identity and GitHub

These variables configure login with your organization's GitHub App (see GitHub login). Without any of them, kubelatch works with local passwords only.

The five core variables (GITHUB_APP_ID, GITHUB_APP_CLIENT_ID, GITHUB_APP_CLIENT_SECRET, GITHUB_APP_PRIVATE_KEY, GITHUB_ORG) go together. With any of them present, or with GITHUB_WEBHOOK_SECRET, all five are required and kubelatch does not start if any is missing. GITHUB_REQUIRE_ORG_2FA, GITHUB_URL and GITHUB_API_URL alone activate nothing. All of them have surrounding spaces stripped.

Variable Required Default Format What it does
GITHUB_APP_ID With GitHub Positive integer App ID of the GitHub App. Signs the JWT kubelatch uses to get installation tokens.
GITHUB_APP_CLIENT_ID With GitHub Text (Iv1.…, Iv23…) App's Client ID, for OAuth login.
GITHUB_APP_CLIENT_SECRET With GitHub Text App's client secret, to exchange the login code server-side.
GITHUB_APP_PRIVATE_KEY With GitHub Full RSA PEM (PKCS#1 RSA PRIVATE KEY or PKCS#8 PRIVATE KEY), 2048 to 8192 bits; accepted on one line with literal \n App's private key. It is the file's content, not a path.
GITHUB_ORG With GitHub GitHub organization login (acme-corp) Only active members of this organization can sign in. The hourly member sync walks it.
GITHUB_WEBHOOK_SECRET No empty Text Activates POST /v1/github/webhook (HMAC-SHA256 signature in X-Hub-Signature-256), which instantly disables anyone who leaves the organization. Its presence turns on GitHub mode.
GITHUB_REQUIRE_ORG_2FA No true Boolean Rejects GitHub logins while kubelatch knows the organization does not require two-factor. It can only know this if the App has Organization → Administration: read; otherwise it lets people in and warns on every sync.
GITHUB_URL No https://github.com URL; http only on a loopback host Only for GitHub Enterprise Server: https://<host>. Base for the OAuth authorization routes.
GITHUB_API_URL No https://api.github.com URL; http only on a loopback host Only for GitHub Enterprise Server: https://<host>/api/v3.

Member sync runs every hour; that interval is not configurable.

What goes in a Secret

In Kubernetes, DATABASE_URL, KUBELATCH_ENCRYPTION_KEY and the sensitive GITHUB_* variables go in the kubelatch-secrets Secret, which the Deployment loads whole. Everything else goes in deploy/k8s/base/config.env, which becomes the kubelatch-config ConfigMap.