Certificates & PKI
ReadyYdentifi runs on mutual TLS: every party — server, operator, your app, each device — proves who it is with a certificate. You own the whole chain: one root you generate and guard, and the certificates beneath it. ydfi bootstrap mints the lot in one command, and you hold the keys — Ydentifi never does.
Who this is for: whoever sets up and operates a deployment. Certificates have a reputation for being complex, so this page keeps it concrete: what gets made, where it lives, who holds each key, how long it lasts, and how to replace it. No prior PKI expertise assumed.
Why certificates at all#
Mutual TLS means both ends of every connection prove who they are — not just the server, as on a normal HTTPS website, but the client too.
A certificate is just a small signed file that says “this public key belongs to this identity,” vouched for by a certificate authority (CA) that both sides trust. In Ydentifi, you run the CA. That is the whole idea: you decide who is trusted, and nobody — including us — can mint a trusted identity without your root key. It is also why most requests carry no identity in the body: the certificate on the connection already says who is calling.
The whole thing, in one command#
ydfi bootstrap sets up a fresh deployment: its certificate kit, its secrets and a commented .env. The certificates go to a folder you choose:
$ ydfi bootstrap --cert-dir .cert --dns-name ydentifi.acme.internal --license-file license.jwt .cert/ ca/ca.crt root CA — your trust anchor (hand this out) ca/ca.key root CA private key — guard this; never share it servers/ydfi-server/ the gateway + identity listener cert servers/admin-server/ the admin listener cert admin/ operator client cert for admin access monitoring/ the metrics scraper’s client cert
That is everything the server and operators need to start. Relying-party and device certificates are added later, on demand (below).
The trust chain#
Everything traces back to one root you own. The root signs the certificates beneath it, and because every party is configured to trust that root, they will trust anything it signed — and reject anything it didn’t.
ca.keyDistribute the root’s public cert (ca.crt) as the trust anchor. Guard the root’s private key (ca.key) — it is the one secret everything else depends on.
Who holds which key#
The golden rule of this system: a private key never leaves the party it belongs to. Ydentifi never holds your keys for you.
- The root key is your crown jewel. The running server holds it: it signs each phone’s device certificate at enrollment and on rotation (
YDFI_SERVER_ROOT_CA_KEY_PATH). So keep it on the server and nowhere else — deliver it from your secret manager when the server starts, readable only by the server’s user, and never bake it into an image, a backup or a repository. Your own CA issues the deployment’s renewed certificates under this root, directly or through an intermediate the root signed. Anyone who has it can mint trusted identities for the deployment; it never serves live traffic itself. - Relying-party keys stay with the relying party. An RP generates its own key and sends you a certificate signing request (a CSR — a public key plus a “please vouch for me”). You sign it with
ydfi admin provision-rp-cert; the RP’s private key never travels. - Device keys never leave the device. Each phone generates a hardware-bound key in its secure element at enrollment and gets a device certificate signed then. The private half is non-exportable.
You issue, store, and rotate the keys that root trust in your deployment; Ydentifi secures the software and protocol that use them. See Security model.
The server reads its secrets — TLS keys, database credentials, master encryption keys, the license — from environment variables. That is deliberate: env vars are the lowest common denominator across every deployment context, so you can source them from a file on-prem, or wire them straight from a cloud secrets manager (GCP Secret Manager, AWS Secrets Manager, HashiCorp Vault) without Ydentifi needing to speak any vendor’s API. The full list of variables is in Configuration.
How long they last#
Lifetimes are deliberately long for the things that are laborious to rotate, and short for the things that rotate easily. Nothing silently expires without warning (below).
| Certificate | Default lifetime | How it’s issued or rotated |
|---|---|---|
| Root CA | 10 years | ydfi bootstrap. Replacing it re-issues the whole deployment and re-distributes the trust anchor — a coordinated operation, reserved for a compromised key or scheduled hygiene (below). |
| Server listeners | 90 days | ydfi bootstrap, then renewed by your own CA under the same root (step-ca, for example). |
| Operator and monitoring | 90 days | Issued by ydfi bootstrap; renewed the same way. |
| Relying party | 2 years (up to 5) | provision-rp-cert signs the RP’s CSR; the RP sets its next lifetime with SetCertificateTTL (1–1825 days). |
| Device | per enrollment | Minted at enrollment; re-enroll on a new or refreshed device to replace it. |
What the phone pins#
Every enrollment QR carries a pin of your deployment’s root: a SHA-256 hash of its public key, which ydfi pki pin-hash computes. A QR without one does not parse. The phone stores the pin at enrollment and checks it on every later connection, so a certificate from any other authority is refused — even a valid one. It turns “some certificate authority vouched for this server” into “this is the same server I enrolled against”.
What gets pinned is the top of the chain your server presents — your root, not the service leaf beneath it. That is what makes routine rotation free:
- Rotate a service leaf — enrolled phones neither notice nor care. The root they pinned is unchanged.
- Rotate the root — the anchor itself moved, so phones re-enroll. That is the trade: a decade-scale event in exchange for leaf rotation costing nothing.
The pin covers the public key rather than the whole certificate, so reissuing a certificate under the same key changes nothing either.
Rotating a certificate#
Rotation is always an explicit action — there is no automatic rotation. Pick the smallest one that fits; you rarely need to touch the root.
- One service cert (a listener got a new hostname, or you just want a fresh one) — your CA issues a new one under the existing root, and you replace the file. Enrolled phones are unaffected — they pinned the root, not this. Every listener serves the new file within ten seconds of it changing, usually about a second, so no restart is needed. The phone listener refuses a new certificate that phones would refuse, and keeps serving the old one.
- A relying party — the RP submits a new CSR and you re-sign with
provision-rp-cert, or the RP self-rotates within the five-year ceiling. Only that one RP is affected. - The root itself — the coordinated one, reserved for a compromised root key or scheduled hygiene. Walk-through below.
Rotating the root, in practice
The root is an internal trust anchor — it secures service-to-service mTLS inside your deployment and is never trusted by a browser or the public internet. Rotating it re-issues everything beneath it. Each server needs a restart to trust the new root, and it is the one rotation your users see: the root is what phones pinned at enrollment, so every enrolled device re-enrolls afterwards. Plan it as a coordinated change, not routine hygiene.
Ydentifi has no command for this: your CA mints the new root and re-issues the certificates beneath it. It comes with the step-ca recipes. Each server then needs a restart, because it reads its trust bundle once at boot. Two more things are yours to do:
- Distribute the new files. Push the re-signed server leaves and the new
ca.crttrust anchor to every service — volume mount, k8s Secret, a secrets-manager-backed CSI driver, however you ship secrets. - Re-issue client certs. Relying parties submit fresh CSRs (
provision-rp-cert); enrolled devices pick up the new anchor, re-enrolling if their chain no longer validates.
Until a party has the new root as its trust anchor, its handshake fails closed — correct behavior, but a hard failure, not a downgrade. So roll the new ca.crt out to every service and client as part of the same change, not afterwards. (Today ydfi bootstrap makes the root; using a CA you already run comes with the step-ca recipes.)
For the full day-2 playbook — bootstrap, rotation, revocation, incident response — see the operational runbook under Deploy.
The server tracks every certificate’s validity window and warns you well before expiry — check any deployment with ydfi admin health, or a caller’s own window with GetCertificateExpiry. Client certificates are never auto-rotated: that is a deliberate choice, so a renewal is always something you did on purpose, never a surprise. An expired cert fails the handshake closed — it never silently degrades.