From state.apply to revoked in under 60 seconds
Salt for declarative configuration. Vault for secret delivery. HAProxy for TLS termination. mTLS for service-to-service authentication. Woodpecker CI to wire it together. The result: a zero-trust runtime where access is granted by certificate, observable in real time, and revocable in under a minute.
Identity is the only perimeter
Network boundaries are leaky. VPNs add latency without adding meaningful trust. The only durable answer is mTLS: every service holds a certificate, every connection is mutually authenticated, and revocation propagates in seconds — not after a quarterly review.
What we replace
- Username + password to internal servicesPhishable, log-leakable, never revoked when an employee leaves.
- Static API keys in env varsLive forever in Git history, container images and Slack DMs.
- "Trusted" IP rangesVPN gateways and NAT traversal assume the network is the trust boundary. It isn't.
- Manual cert renewalsCalendar reminders that get missed at 02:00 on a bank holiday.
What we deliver
- mTLS everywhereEvery internal service authenticates clients by certificate. EJBCA-issued, short-lived, revocable.
- Vault as the credential brokerAppRole plus dynamic secrets. Apps fetch credentials at boot and never store them.
- Salt as the configuration substrateDeclarative state with grain-based opt-in. CI dispatches; it never bypasses.
- Live revocationRevoke a cert in EJBCA — OCSP propagates in seconds — and clients lose access. Demonstrable on every prospect call.
The components, wired together
A simplified view of the SkyQon zero-trust reference stack. Each box is something we deploy, configure and operate against your real workloads.
Salt master + minions
Salt for configuration management. Hosts opt into automated state apply via a pipeline_env grain — Root CA and HSM hosts are excluded by design. salt-api is fronted by nginx for TLS termination (a Salt 3006 cherrypy chain-bug workaround).
Vault + AppRole
KV-v2 for application secrets, AppRole for non-human authentication, CIDR-bound tokens, file audit log. Pipelines fetch secrets at runtime — no long-lived credentials in CI configs.
HAProxy + PROXY-v2
TLS termination, SNI-based routing, mTLS verification at the edge. PROXY protocol v2 to backends so client IP survives — critical for Galera authentication and audit trails.
EJBCA + ACME + REST
The CA backend issues server certs via ACME and service-account mTLS via REST. Two trust roots (Issuing G2 + Management) — explicitly separated, never conflated.
Woodpecker CI
Pipeline runners that lint, test-render, then dispatch state.apply through salt-api. Vault credentials fetched per run via AppRole — the token is revoked at step end.
Battle-tested, not bleeding edge
Every component runs in production at SkyQon and has been hardened against the gotchas you'd otherwise discover at 03:00.
Configuration
Declarative state, idempotent application, gated by host grain so safety boundaries can't be bypassed by accident.
Secrets
Short-lived tokens, CIDR-bound roles, file audit log, and dynamic secrets when the backend supports it.
Edge / proxy
TLS termination with SNI routing, mTLS verification at the edge, PROXY v2 to preserve client IPs through TCP-mode listeners.
CI / CD
Self-hosted Gitea + Woodpecker. Pipelines lint, render and dispatch through salt-api. No production access without a passing PR.
Containers / VM
Proxmox-hosted LXC for stateful services, RKE2 for stateless workloads. mTLS-protected ingress and inter-pod traffic.
Observability
A single observability sink. All pipeline events, all CA audit events, all mTLS handshake failures — one query, one timeline.
Want to see the live revocation demo?
It's the headline of every prospect call. Issue a cert, access an mTLS-protected service, revoke the cert, watch the access disappear — all in under 60 seconds.