-
Notifications
You must be signed in to change notification settings - Fork 30
mTLS
If the niks3 server sits behind a reverse proxy that verifies client certificates, the certificate is the credential — no bearer token required. This is a good fit for fleets of machines that already manage X.509 certs (internal CA, step-ca, vault PKI, SPIFFE).
Pass the cert and skip the auth flags entirely:
niks3 push --server-url https://niks3.example.com \
--client-cert /etc/niks3/client.pem \
--client-key /etc/niks3/client.key \
--ca-cert /etc/niks3/ca.pem \
./result--ca-cert is optional — without it the system CA pool is used to verify
the server. The niks3-hook serve daemon takes the same flags.
For Nix to read from the cache through a vhost that requires a client
cert (require = true below), set the cert in nix.conf:
ssl-cert-file = /etc/niks3/client.pem
ssl-key-file = /etc/niks3/client.keyniks3 itself doesn't terminate TLS — a reverse proxy does, verifies the
client cert, and signals the result via headers. niks3 trusts those headers
because --mtls-proxy-header opts in.
| Flag | Default | Description |
|---|---|---|
--mtls-proxy-header |
(off) | Header set to SUCCESS by the proxy after verifying the client cert |
--mtls-subject-header |
X-SSL-Client-Dn |
Header carrying the verified cert's subject DN |
--mtls-bound-subject |
(any) | Restrict to certs whose subject DN matches this glob; repeatable |
niks3-server \
--mtls-proxy-header X-SSL-Client-Verify \
--mtls-bound-subject 'CN=ci-runner-*' \
...Security:
--mtls-proxy-headermust only be enabled behind a proxy that overrides the header on every request — including requests where verification failed or no cert was presented. Otherwise any client can fakeX-SSL-Client-Verify: SUCCESSand bypass auth entirely.
services.niks3.nginx = {
enable = true;
domain = "niks3.example.com";
mtls = {
enable = true;
clientCAFile = "/etc/niks3/client-ca.pem";
boundSubjects = [ "CN=ci-runner-*" ];
# require = true; # `optional` (default) lets bearer-token auth coexist
};
};This configures nginx with ssl_verify_client, always sets
X-SSL-Client-Verify and X-SSL-Client-Dn on proxied requests (overriding
any inbound values), and passes the matching --mtls-* flags to the
server.
With require = false (the default, nginx ssl_verify_client optional),
clients without a cert can still authenticate with a bearer token.
With require = true, every TLS connection — including Nix substituter
reads — must present a cert.
- mTLS: long-lived machines with managed certs, no external identity provider needed, both sides verify each other.
- OIDC: short-lived CI jobs (GitHub Actions, GitLab CI), no certs to provision, identity comes from the CI platform.
- API token: simplest, but a shared secret. Good for bootstrapping or a single trusted operator.