Skip to content

Set Up the Certificate Chain (PKI)

What this is: setting up the chain of certificates that lets devices prove they're talking to the real servers, and lets servers trust each other. When you'd do it: once, when you first stand up a deployment — before any servers or clients go live. How long it takes: an hour or two of planning with your security team; the issuing is quick once you've decided the shape.

Who can do this: a security/PKI engineer does the certificate work, and an Admin ties it into the Directory. This is the one genuinely specialist job in the guide — if your organisation already has a PKI team, this is a conversation with them.

First, the thing people get wrong

In Bedrock, who a person or device is — their identity — comes from tokens, not certificates. A leaked or expired certificate doesn't let someone impersonate a user. (How identity actually works is the security model and PKI reference.)

So what are the certificates for? Transport security:

  • A client checks the server's certificate before connecting, so it knows it's reaching the genuine server and not an imposter in the middle.
  • Servers check each other's certificates before they federate (link up and share traffic).

That's it. Certificates protect the pipe; tokens protect the identity. Keep those two ideas separate and the rest of this page makes sense.

The shape of it

flowchart TD
    ROOT["Root CA<br/>(kept offline)"] --> SI["Server Intermediate<br/>(in a key vault / HSM)"]
    ROOT --> CI["Client Intermediate<br/>(in a key vault / HSM)"]
    SI --> SL["Server certificates<br/>(one per relay)"]
    CI --> CL["Transport certificates<br/>for clients/peers"]
    SL -.->|"clients check this"| TRUST["Everyone trusts<br/>the Root"]
    ROOT -.-> TRUST

Three tiers, top to bottom:

  1. Root CA — the anchor everyone trusts. Kept offline and used rarely. If this is safe, the whole chain is safe.
  2. Intermediates — day-to-day signers, kept in a key vault / HSM (e.g. cloud KMS). A Server Intermediate signs server certificates; a Client Intermediate signs the transport certs clients and peers use.
  3. Leaf certificates — the actual certs on each machine. Short-lived, replaced often.

In production this chain is anchored by the Directory and the leaves are issued automatically when a server enrols or a client logs in — you don't hand-cut them. Your job is to set up the root and intermediates once, the right way.

Which chain covers which device

Every client and peer validates the server's certificate. Identity is still tokens, so only servers (and a couple of interop links) ever need two-way certificates.

Component What it presents What it trusts Two-way certs (mTLS)?
Android / Web client nothing — it's identified by its token the Root CA, to check the server it connects to No — one-way (checks the server only)
Node (GPS/sensor daemon) nothing for identity (token) the server/peer CA, to check what it connects to No — message authenticity is a per-message signature, not a cert
Server (relay) its server certificate (Server Intermediate → Root) clients and peer servers Yes, for server-to-server federation (peer CA)
Gateway (interop bridge) its token to the mesh; plus certs for external systems the server CA and the external systems' own CAs (e.g. TAK, MQTT) One-way to the mesh; external links follow each system's own rules

The takeaway: one Root that everyone trusts, server certificates under it, and separate trust for the gateway's external connections.

Production vs staging

  • Production — use the Directory-anchored three-tier chain above (offline Root, intermediates in a vault/HSM, automatic leaf issuance). Don't hand-issue production leaves with openssl on a laptop.
  • Staging / demo only — the infrastructure repo ships a helper, pki/generate.sh, that mints a throwaway self-signed CA and one server cert per demo VM. Fine for a lab. Never use it for production — it's a local convenience, not a real trust chain.

Decide your Root: existing root vs standalone

This is the big decision, and it's your security team's call. Both work; the trade-off is manageability vs. attribution.

Option A — Chain under your existing enterprise root (preferred for most enterprises)

Issue Bedrock's Server and Client Intermediates from the root your organisation already runs, instead of standing up a new one.

  • Reuses your existing chain of trust — devices that already trust your corporate root trust Bedrock automatically; nothing new to distribute.
  • Centrally managed and revoked — it lives in the PKI estate your team already operates, monitors, and can revoke from one place.
  • ⚠️ It attributes the deployment to your enterprise. The certificates visibly chain to your organisation's root, so anyone who inspects them can tie this deployment back to your estate. Where that link is sensitive, this is a real downside.

Option B — Standalone offline Bedrock root

Stand up a dedicated root just for this deployment.

  • No attribution — nothing links the deployment to your wider estate; it stands alone. The usual choice when the deployment must be deniable or kept separate.
  • Self-contained — survives independently of the corporate PKI; good for air-gapped or disconnected sites.
  • ⚠️ You manage it yourself — its own root protection, rotation, and revocation, separate from your central tooling.

Rule of thumb: prefer Option A when central management and reusing existing trust matter most; choose Option B when keeping the deployment unattributable or isolated matters more.

Example: building a chain by hand

These commands show the shape of a chain — useful for a lab, or to understand what your HSM/Directory does for you in production. Production roots/intermediates should live in an HSM or KMS, not as files on disk.

1. Root CA (do this on an offline machine, keep root.key safe):

openssl genrsa -out root.key 4096
openssl req -x509 -new -key root.key -sha256 -days 3650 \
  -subj "/O=Your Org/CN=Bedrock Root CA" -out root.crt

2. An intermediate signed by the root (CA:TRUE makes it a signer; pathlen:0 stops it minting further CAs):

openssl genrsa -out server-int.key 4096
openssl req -new -key server-int.key \
  -subj "/O=Your Org/CN=Bedrock Server Intermediate" -out server-int.csr
openssl x509 -req -in server-int.csr -CA root.crt -CAkey root.key -CAcreateserial \
  -days 1825 -sha256 -out server-int.crt \
  -extfile <(printf "basicConstraints=critical,CA:TRUE,pathlen:0\nkeyUsage=critical,keyCertSign,cRLSign\n")

3. A server (leaf) certificate signed by the intermediate (serverAuth, with the server's hostnames in the SAN so clients accept it):

openssl genrsa -out relay.key 2048
openssl req -new -key relay.key -subj "/O=Your Org/CN=relay-north.example" -out relay.csr
openssl x509 -req -in relay.csr -CA server-int.crt -CAkey server-int.key -CAcreateserial \
  -days 90 -sha256 -out relay.crt \
  -extfile <(printf "basicConstraints=CA:FALSE\nextendedKeyUsage=serverAuth\nsubjectAltName=DNS:relay-north.example\n")

4. The chain file the server presents (leaf + intermediate, not the root):

cat relay.crt server-int.crt > relay-chain.crt

To use Option A, replace step 1 with your enterprise root and sign the intermediate in step 2 with it instead. Everything below stays the same.

How to know it worked

  • A client connects to a server without certificate warnings — it trusts the chain.
  • Two servers federate (link up and share traffic) without rejecting each other.
  • openssl verify -CAfile root.crt relay-chain.crt returns OK.

If something goes wrong

  • Clients reject the server ("untrusted"). They don't have the Root. Make sure the Root CA is distributed to clients, and that the server presents the chain (leaf + intermediate), not just the leaf.
  • Servers won't federate. Each must trust the CA the other's certificate chains to — check both ends share the same Root/intermediate.
  • A hostname mismatch error. The server's certificate SAN doesn't list the name the client used. Reissue the leaf with the right hostname in the SAN.
  • A certificate expired. Leaves are short-lived by design — reissue and redeploy. Plan rotation before they lapse.

See also

  • Operator training index
  • PKI reference — the full trust model (token-only identity, trust roots, rotation, revocation).
  • Security model — how identity and revocation actually work.
  • Add a server — where a server's certificate gets used.
  • The infrastructure repo (pki/) — the staging generate.sh helper and the production CA notes.

Verified against directory@e8287cd on 2026-06-07 — model cross-checked with security/pki.md, the infrastructure repo (pki/README.md, pki/generate.sh), and the server/gateway/node transport configs. Identity is token-based; certificates here are transport-only.