Skip to content

mTLS and Certificate Management

Every connection between a sensor and the Console uses mutual TLS. The sensor presents a client certificate, and the Console presents its server certificate; both sides verify each other. There is no fallback to API keys or shared secrets for sensor communication.

Prerequisites

  • Console already installed and running (Telovix self-hosted)
  • TLS certificate files already generated (server cert, CA cert, issuer key)
  • admin role to configure TLS settings
  • Each sensor must reach the Console on the configured port

Network topology

The sensor always initiates outbound connections to the Console. Two ports are involved:

PortPurpose
15483HTTP API port (used by sensors for enrollment, heartbeat, and all sensor communication; also serves the operator UI and API) (Telovix self-hosted default)
15484Dedicated mTLS sensor listener (alternate; configurable in Console Settings)

The sensor's Console URL is set during sensor setup and points to port 15483 (Telovix self-hosted default). The Console configuration determines which listener handles sensor mTLS traffic. In the default configuration, sensor traffic goes to 15483.

The Console makes no inbound connections to sensors. Sensors connect out; the Console responds.


Enrollment: initial certificate issuance

What the sensor does

At first startup after the binary is installed, the sensor performs enrollment:

  1. Reads the configured Console URL and enrollment token from its configuration.
  2. Fetches the Console CA certificate from the trust bootstrap endpoint (using Bearer token auth).
  3. If a bootstrap CA certificate path is configured, loads that PEM as the CA trust anchor for the enrollment-only phase. If not set, accepts self-signed certs with a warning log.
  4. Generates an RSA key pair locally using rcgen.
  5. Creates a Certificate Signing Request with CN=<node_name>, O=Telovix Sensor.
  6. Submits the enrollment request with the enrollment token, CSR PEM, node name, declared role, tags, software version, and Kubernetes cluster name if applicable.

What the Console returns

json
{
  "sensor_id": "...",
  "control_plane_certificate_pem": "...",
  "control_plane_ca_certificate_pem": "...",
  "policy_signing_public_key_pem": "...",
  "certificate_expires_at": "2026-06-01T00:00:00Z",
  "certificate_reference": "..."
}

The Telovix Console signs the CSR using its issuer key and returns the signed client certificate with a TTL of 720 hours (30 days) by default.

Store credentials

The sensor atomically writes credentials to the state directory (/var/lib/telovix-sensor by default):

/var/lib/telovix-sensor/
├── client.key.pem              (mTLS client private key)
├── client.cert.pem             (mTLS client certificate)
├── client.prev.key.pem         (previous key kept for overlap period)
├── client.prev.cert.pem        (previous cert kept for overlap period)
├── console-ca.cert.pem         (Console CA certificate)
├── policy-signing.pub          (Ed25519 public key for policy verification)
└── sensor-state.json           (enrollment state, trust_state, cert expiry, renewal status)

After successful enrollment, sensor-state.json records trust_state="trusted" and renewal_status="ok".

Subsequent connections

After enrollment, the sensor builds a reqwest::Client with the mTLS identity (client key + cert + Console CA). All heartbeats, WebSocket connections, policy downloads, and upgrade requests use this client. The enrollment token is never used again.


Steady-state: certificate use

The sensor sends a heartbeat every 30 seconds over mTLS. The client certificate identifies the sensor; the Console verifies it against the issuer CA on every request. The current certificate trust state is reported in every heartbeat payload and is visible on the sensor's detail page in Sensors.

The WebSocket stream for real-time event delivery also uses mTLS via tokio_tungstenite with a rustls connector.


Renew certificates

Triggers

TriggerCondition
ProactiveCertificate expiry is less than 72 hours away
ManualOperator triggers renewal from Sensors > [sensor] > Renew Certificate (increments the manual_renewal_generation counter; sensor picks this up on the next heartbeat)

Renewal process

  1. Sensor generates a new RSA key pair and CSR.
  2. Submits the renewal request over the existing mTLS connection.
  3. Console issues a new certificate with a fresh TTL.
  4. Sensor writes the new key first, then the certificate (atomic ordering). If the process crashes between these two writes, re-enrollment is triggered rather than a corrupt state.
  5. Previous credentials are retained as client.prev.key.pem and client.prev.cert.pem for the overlap period.

The overlap period (default 86400 seconds) allows the previous certificate to remain valid during the transition.

Renewal timing

The following thresholds apply by default and are configurable in Console Settings:

SettingDefaultMeaning
Certificate TTL720 hours (30 days)Certificate TTL issued to sensors
Renewal recommended threshold259200 seconds (3 days)Threshold for renewal_recommended trust state
Renewal due threshold86400 seconds (1 day)Threshold for renewal_due trust state; sensor begins proactive renewal
Renewal overlap86400 seconds (1 day)Previous cert validity after renewal
Trust error recent window900 seconds (15 min)Window for classifying a trust error as recent

Trust states

StateMeaning
trustedCertificate is valid; renewal is not yet approaching
renewal_recommendedCertificate expiry is within 3 days; renewal is advised
renewal_dueCertificate expiry is within 1 day; sensor is initiating proactive renewal
trust_revokedOperator has revoked this sensor; mTLS requests are rejected

Trust state is evaluated on every heartbeat. The Console maintains trust health at the fleet level, visible on the Fleet view trust summary, and exposes active trust alerts on the Trust Alerts page.


Revoke or disable a sensor

Both operations require the admin role and are recorded in the audit log.

Disable

In the Console, navigate to Sensors, click the sensor name to open its detail page, and click Disable Sensor.

Sets the sensor status to disabled. The sensor can no longer send accepted heartbeats. Telco snapshots are cleared asynchronously. The sensor identity is preserved and the sensor can be re-enabled.

Use disable for temporary suspension: planned maintenance, node rebuild, or investigation hold.

📸 Screenshot: sensor-detail-disable Sensor detail page showing the Disable Sensor action in the Actions menu.

Revoke

In the Console, navigate to Sensors, click the sensor name to open its detail page, and click Revoke Sensor.

Sets the sensor status to revoked and sets trust_state to trust_revoked. The Console rejects all mTLS requests from this sensor identity. Telco snapshots are cleared. The sensor is visible in the Console but cannot reconnect without a new enrollment.

Use revoke when a node is decommissioned, rebuilt from scratch, or its certificate material may be compromised. After revocation, generate a new enrollment token and re-enroll the rebuilt node.


Configure Console TLS

The Console requires several TLS files to operate the sensor mTLS listener. These are provided during Console installation and managed through the setup wizard.

FileRequiredDescription
Server certificateYesConsole server certificate presented to sensors
Server private keyYesConsole server private key
Client CA certificateYesCA cert used to verify sensor client certificates
Issuer certificateYesIssuer certificate used to sign sensor client CSRs
Issuer private keyYesIssuer private key used to sign sensor client CSRs
mTLS bind addressNomTLS bind address (default: 0.0.0.0)
mTLS listener portNomTLS listener port (default: 15484)

The issuer cert and key are what the Console uses to sign sensor CSRs during enrollment and renewal. The client CA cert is what the Console uses to verify incoming mTLS connections from sensors. In a standard deployment these are related: the issuer is the CA, so the issuer cert and the client CA cert are the same file.

The server cert and key are the Console's own identity, presented to sensors during TLS handshake so sensors can verify they are connecting to the right Console.


Monitor trust health

Fleet trust summary

In the Console, navigate to Fleet. The trust health summary is displayed in the header row, showing counts by trust state and sensors with active alerts.

📸 Screenshot: fleet-trust-summary Fleet view header showing trust state counts: trusted, renewal_recommended, renewal_due, and revoked sensors.

Trust alerts

In the Console, navigate to Fleet > Trust Alerts. This page lists all active trust alerts across the fleet. Alert types include certificate nearing expiry (renewal_recommended, renewal_due) and active trust errors.

Per-sensor trust detail

In the Console, navigate to Sensors, click a sensor name, and select the Trust tab. This shows enrollment status, certificate expiry timestamp, certificate reference, current trust state, renewal status, and any active trust alerts for that sensor.

📸 Screenshot: sensor-trust-tab Sensor detail Trust tab showing certificate expiry date, trust state badge, renewal status, and the manual renewal button.

Manual renewal trigger

In the Console, navigate to Sensors, click the sensor name, select the Trust tab, and click Trigger Renewal. This increments the manual_renewal_generation counter on the Console. The sensor reads this on its next heartbeat and initiates a renewal cycle.


Troubleshooting

Sensor fails enrollment

The enrollment token may have expired or already been used, or the Console URL is not reachable from the sensor node. Verify the token is still valid by checking its timestamp in the Console. Confirm the Console URL is reachable from the sensor host. If the Console uses a self-signed or private CA certificate, configure the bootstrap CA certificate path (set during sensor setup) to the Console's CA certificate PEM file before enrolling.

Sensor enrolled but heartbeats rejected

The client certificate may have expired or been revoked. Check sensor-state.json in the sensor state directory for the trust_state field. If the value is trust_revoked, re-enroll the sensor using a new token from the Console. If certificate_expires_at is in the past, trigger re-enrollment.

Clock skew causes certificate rejection

TLS certificate validation is sensitive to system clock accuracy. A sensor node with a clock significantly behind the real time will treat a valid certificate as not-yet-valid; a clock that is ahead will treat a valid certificate as already expired. Verify NTP synchronization on both the Console host and all sensor nodes:

bash
timedatectl status

Expected output on a synchronized host:

               Local time: Thu 2026-04-26 14:22:00 UTC
           Universal time: Thu 2026-04-26 14:22:00 UTC
                 RTC time: Thu 2026-04-26 14:22:00
                Time zone: UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

If System clock synchronized: no or NTP service: inactive, enable NTP synchronization before attempting enrollment or renewal.

Checking trust state from the sensor host

If the Console shows a sensor with an unexpected trust state, verify the sensor's local trust record:

bash
cat /var/lib/telovix-sensor/sensor-state.json

Expected output on a healthy sensor:

json
{
  "sensor_id": "tlvs_...",
  "trust_state": "trusted",
  "certificate_expires_at": "2026-06-01T00:00:00Z",
  "renewal_status": "ok"
}

If trust_state is trust_revoked, re-enroll the sensor using a new token from the Console. If certificate_expires_at is in the past, the sensor should have already attempted automatic renewal; check the sensor logs for renewal errors.

Renewal stuck in renewal_due

The sensor cannot reach the Console due to a network partition or firewall rule change, so proactive renewal is failing silently. The sensor continues to operate on the existing certificate until it expires. Restore connectivity between the sensor and Console and renewal will complete automatically on the next heartbeat attempt.


Further reading

Released under the Telovix Commercial License.