Sentinel Secure X

Readable deployment docs on the live domain.

Installation, operator guidance, endpoint service setup, and platform references in one browsable library.

NGINX mTLS Proxy

Terminate browser TLS and device mTLS at the reverse proxy while keeping the API local-only.

NGINX mTLS proxy

Use the checked-in NGINX template when you want Sentinel Secure X to terminate browser TLS and device mTLS at the proxy while the Flask API stays on the local Waitress listener.

  1. Keep the API bound to the local host, for example http://127.0.0.1:8000, and do not expose that listener directly.
  2. In the control-plane .env file, keep SENTINEL_REQUIRE_DEVICE_MTLS=true and set SENTINEL_TRUST_PROXY_CERT_HEADERS=true because NGINX will forward the verified client-certificate metadata that the heartbeat path depends on.
  3. Run the proxy-aware control-plane preflight:
python3 -m server.preflight \
  --env-file /opt/sentinel-secure-x/.env \
  --expect-proxy-cert-headers
  1. Render and install the proxy config:
sudo python3 deploy/nginx/install_mtls_proxy.py \
  --output-path /etc/nginx/conf.d/sentinel-secure-x.conf \
  --server-name sentinel.example.com \
  --tls-cert-path /etc/nginx/certs/server.crt \
  --tls-key-path /etc/nginx/certs/server.key \
  --client-ca-path /etc/nginx/certs/device-ca.crt \
  --upstream-url http://127.0.0.1:8000 \
  --env-file /opt/sentinel-secure-x/.env \
  --check-nginx-config \
  --reload-nginx
  1. Smoke-check the proxy path over HTTPS:
python3 deploy/nginx/smoke_test_proxy.py \
  --base-url https://sentinel.example.com

This verifies that /api/health/live and /api/health/ready are reachable through the proxy and that POST /api/heartbeat is rejected with 401 when no client certificate is presented.

If you want a stronger end-to-end probe with a real device certificate, add:

python3 deploy/nginx/smoke_test_proxy.py \
  --base-url https://sentinel.example.com \
  --client-cert /path/to/device.crt \
  --client-key /path/to/device.key \
  --device-id device-demo-01

If the proxy uses a private CA, add --ca-file /path/to/proxy-ca.pem or --insecure for an intentional one-off check. When you use the authenticated probe, the device certificate common name should match --device-id.

Notes

  • The rendered config keeps browser access open, but it requires a verified client certificate specifically on POST /api/heartbeat.
  • The proxy forwards the certificate headers Sentinel expects when SENTINEL_TRUST_PROXY_CERT_HEADERS=true, including subject, issuer, serial number, certificate PEM, fingerprint, and validity timestamps.
  • The helper defaults the upstream origin to http://127.0.0.1:8000, which matches the checked-in systemd API service.
  • The installer can run the same proxy smoke test automatically when you add --smoke-test.
  • For a quick local preview, run make nginx-proxy-render or pass custom arguments with make nginx-proxy-render NGINX_PROXY_ARGS='--stdout --server-name sentinel.example.com'.
  • For a quick local proxy check, run make nginx-proxy-smoke NGINX_PROXY_SMOKE_ARGS='--base-url https://sentinel.example.com --ca-file /path/to/proxy-ca.pem'.
  • Use --stdout to preview the rendered config without writing it.
  • If you already manage NGINX elsewhere, you can still use the template as a reference as long as the forwarded certificate headers and heartbeat protection remain equivalent.