TLS Setup¶
The SentriKat API ships with HTTP enabled by default for ease of first install, but production deployments must serve all API traffic over HTTPS. Agents transmit license keys, system inventories, and CVE intelligence over the wire — anything less than TLS leaks credentials and asset data to anyone with network visibility.
This page walks through the three TLS topologies SentriKat supports out of the box and the cert-acquisition flow for each.
Why TLS is required¶
- API keys travel as bearer tokens. Every agent → SaaS / on-prem call carries the license key in the
Authorizationheader. Without TLS the key is recoverable from a single packet capture and grants full control of the deployment until it's rotated. - Inventory data is sensitive. Agents post software inventories (versions, paths, container images, dependency manifests). For a regulated organisation this is a map of every exploitable surface in the estate — exactly the data an attacker needs to plan lateral movement.
- GDPR Art. 32 requires "appropriate technical measures" for self-hosted deployments that process personal data tied to operator identities (admin emails, audit log actor IDs). TLS is the minimum bar for a regulator to accept that "appropriate" was actually attempted.
- Agents refuse plaintext by default. From the 2026 agent release onwards, the installer aborts with an HTTPS-required error when pointed at an
http://URL unless-AllowHttpis explicitly passed (see the agent installation page for the flag).
Quick path — built-in nginx with TLS template¶
The on-prem image ships two nginx config templates: the default nginx.conf.template (HTTP-only, listens on :80) and nginx-ssl.conf.template (HTTPS on :443, HTTP redirect on :80). Switching to the TLS template is a 4-step flip:
cd /opt/sentrikat # or wherever you put the deploy
# 1. Disable the HTTP-only template
mv nginx/nginx.conf.template nginx/nginx.conf.template.disabled
# 2. Activate the TLS template
mv nginx/nginx-ssl.conf.template nginx/nginx.conf.template
# 3. Drop your cert + key into ./ssl/
mkdir -p ssl
cp /path/to/your/fullchain.pem ssl/cert.pem
cp /path/to/your/privkey.pem ssl/key.pem
chmod 600 ssl/key.pem
# 4. Recycle the stack
docker compose down
docker compose up -d
Verify with:
The cert.pem filename must contain the full chain (leaf + any intermediate certs concatenated). A bare leaf cert will pass curl -k but fail strict validation from agents and from public CT log monitors.
Cert acquisition¶
Three paths, pick the one that matches your network position.
Option A — Let's Encrypt via certbot (internet-facing deployments)¶
Free, automated, 90-day rotation. Runs on the host, not inside the container.
# One-time install
sudo apt install certbot python3-certbot-nginx # Debian / Ubuntu
sudo dnf install certbot python3-certbot-nginx # RHEL / Rocky / Alma
# Stop the stack so certbot can claim port 80 for the HTTP-01 challenge
docker compose stop nginx
sudo certbot certonly --standalone \
-d sentrikat.example.com \
--email [email protected] --agree-tos --no-eff-email
# Wire the resulting files into ./ssl/
sudo cp /etc/letsencrypt/live/sentrikat.example.com/fullchain.pem ssl/cert.pem
sudo cp /etc/letsencrypt/live/sentrikat.example.com/privkey.pem ssl/key.pem
sudo chown $USER:$USER ssl/*.pem
chmod 600 ssl/key.pem
docker compose up -d
Use this when SentriKat is reachable from the public internet on port 80 (HTTP-01) or via DNS API (DNS-01 — see certbot plugins for Cloudflare, Route53, etc.).
Option B — Internal CA (corporate / air-gapped)¶
Most enterprises run an AD CS / Vault / step-ca / private CA. The flow is:
-
Generate a key + CSR on the SentriKat host:
-
Submit the CSR to your internal CA (the exact mechanism is CA-specific: AD CS web enrollment,
step ca certificate, Vault PKI, etc.). -
Receive
cert.pem(with the full chain) from the CA and drop it into./ssl/cert.pem. -
Distribute the internal CA root to agent hosts so they trust the cert. Two paths:
- On Windows agents:
Import-CertificateintoLocalMachine\Root. - On Linux agents: drop the CA bundle into
/etc/ssl/certs/and runupdate-ca-certificates. - For the SentriKat container itself if it needs to talk to other internally-issued endpoints (e.g. an internal SMTP relay), mount the CA bundle into
/app/custom-certs— see the Container User & Privilege Model page for the bind-mount setup.
- On Windows agents:
Option C — Self-signed (dev / lab only)¶
Acceptable for short-lived test installs. Agents will refuse the cert in default mode; you must pass -AllowHttp (PowerShell installer) or --allow-insecure-tls (Linux/macOS installer) to skip verification. Do not use self-signed in any environment that holds real inventory data.
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
-keyout ssl/key.pem -out ssl/cert.pem \
-subj "/CN=sentrikat.local"
chmod 600 ssl/key.pem
docker compose down && docker compose up -d
Cert renewal automation¶
Let's Encrypt certs expire every 90 days. Inside the container is the wrong place to renew — use a host-level cron / systemd timer that:
- Runs
certbot renew(which is a no-op if the cert is more than 30 days from expiry). - Copies
fullchain.pemandprivkey.peminto./ssl/if they changed. - Sends nginx a
SIGHUPto pick up the new cert without dropping connections.
A complete /etc/cron.daily/sentrikat-cert-renew script:
#!/bin/bash
set -e
cd /opt/sentrikat
certbot renew --quiet --no-self-upgrade
LIVE=/etc/letsencrypt/live/sentrikat.example.com
if [ "$LIVE/fullchain.pem" -nt ssl/cert.pem ]; then
cp "$LIVE/fullchain.pem" ssl/cert.pem
cp "$LIVE/privkey.pem" ssl/key.pem
chown $(stat -c '%u:%g' .) ssl/*.pem
chmod 600 ssl/key.pem
docker compose kill -s SIGHUP nginx
fi
For internal-CA certs the analogous job invokes whatever your CA's renewal command is (step ca renew, Vault PKI auto-renew, scheduled CSR submission, etc.) — same cp + SIGHUP afterwards.
Troubleshooting¶
SSL handshake failed from curl -v¶
Almost always one of:
cert.pemhas wrong permissions or wrong owner. Inside the container nginx runs as a non-root user; if your host bind-mount has mode600 root:rootthe worker can't read the key. Fix:chmod 644 ssl/cert.pem(cert is public, can be world-readable) andchmod 600 ssl/key.pemwith ownership matching the nginx user inside the image.cert.pemis the leaf only, not the full chain. Some clients (browsers) tolerate this because they fetch missing intermediates; agents do not. Fix: concatenateleaf.pem+intermediate.pemintocert.pem(leaf first).- Wrong file format — DER instead of PEM, or PKCS#12 instead of PEM. Run
openssl x509 -in ssl/cert.pem -noout -textandopenssl rsa -in ssl/key.pem -check. Both must succeed and print parseable content.
cert verification failed from agents¶
The agent reaches the API but rejects the cert. Means the agent's local trust store doesn't contain the issuing CA. Pick one:
- Public CA (Let's Encrypt, DigiCert, Sectigo, etc.) — already in every OS trust store. If verification fails with a public CA, the cert chain on the server is incomplete (see "wrong chain" above).
- Internal CA — add the CA root to the agent host's trust store (per-OS instructions in the agent docs).
- Self-signed — reinstall the agent with
-AllowHttp/--allow-insecure-tls(never in production).
If the SentriKat container itself talks to your internal CA-signed endpoints (LDAP, SMTP relay, Jira, etc.), mount the CA bundle into /app/custom-certs and the container's entrypoint will append it to the system trust store at boot — see Container User & Privilege Model for the bind-mount layout.
nginx logs show SSL_CTX_use_PrivateKey_file error¶
Key and cert don't match. Confirm with:
openssl x509 -in ssl/cert.pem -noout -modulus | openssl md5
openssl rsa -in ssl/key.pem -noout -modulus | openssl md5
# the two MD5 values must be identical
If they differ you've mixed certs from different issuance batches — re-issue or copy the right pair.
Related¶
- Container User & Privilege Model — UID 999 permissions on the
./ssl/mount and the/app/custom-certsCA-bundle path. - External Postgres —
sslmode=verify-fullfor the DB connection (separate TLS layer from the API). - The agent installer's
-AllowHttpflag is documented in the agent installation page under "Insecure transports for lab use".