Local Quick Start¶
This guide creates a complete local IronRoot PKI, issues a website certificate, installs the Root CA trust bundle, and opens a local HTTPS site without browser warnings.
Local demo only
The passwords below are intentionally simple so the flow is copyable. Do not reuse local demo keys or passwords in production.
What You Are Building¶
flowchart TD
Root[Offline Root CA<br/>trust anchor] -->|signs| Intermediate[Online Intermediate CA<br/>operational issuer]
Intermediate -->|signs| Website[demo.home.arpa certificate]
Server[IronRoot API server] --> Intermediate
Client[ironroot-client] -->|enroll / CSR / request| Server
Browser[Browser trust store] -->|trusts| Root
Browser --> Website
Trust starts at the Root CA. The Root signs the Intermediate. IronRoot uses the Intermediate to sign website certificates. Your browser trusts the website certificate only after you install the Root CA into the local trust store.
1. Generate a Root CA¶
The Root CA is the trust anchor. In production it should live on an offline or air-gapped machine and should only sign Intermediate CAs.
flowchart TD
Root[Offline Root CA] -->|signs| Intermediate[Intermediate CA]
ironroot-admin ca create-root \
--name "IronRoot Local Root CA" \
--key-password ironroot-local-root \
--out ./pki/root
This beginner command still uses production-minded defaults: ECDSA P-384, 20 year validity, encrypted private key, max path length 1, and no leaf certificate usages on the Root CA.
It writes:
root-ca.key: encrypted private key; keep offline in production.root-ca.crt: public Root CA certificate; distribute as trust material.root-ca.pub: public key.root-ca.pemandroot-ca.der: export formats.metadata.json: Root CA settings and fingerprints.fingerprints.txt: SHA-256 fingerprint for verification.recovery.txt: backup and recovery reminders.trust-bundle/root-ca.crt: public trust bundle copy.
2. Generate an Intermediate CA¶
The Intermediate CA is the operational issuer. It lives on the IronRoot server and signs website/server certificates.
flowchart TD
Root[Offline Root CA] --> Intermediate[Intermediate CA]
Intermediate --> Website[Website certificates]
ironroot-admin ca create-intermediate \
--root-cert ./pki/root/root-ca.crt \
--root-key ./pki/root/root-ca.key \
--root-password ironroot-local-root \
--password ironroot-local-intermediate \
--out ./pki/intermediate
Verify the CA chain:
ironroot-admin ca verify-chain \
--root-cert ./pki/root/root-ca.crt \
--intermediate-cert ./pki/intermediate/intermediate-ca.crt
3. Bootstrap IronRoot¶
ironroot-admin bootstrap \
--config ./examples/config.local.yaml \
--non-interactive \
--acknowledge-risk \
--output-checklist ./ironroot-security-checklist.md
4. Start the Server¶
ironroot-server --config ./examples/config.local.yaml
For the local demo the API uses HTTP on localhost:8443; the website certificate you request later is the browser-trusted HTTPS certificate.
5. Create a Bootstrap Token¶
ironroot-admin --config ./examples/config.local.yaml create-token \
--host local-demo \
--ttl 24h
Copy the returned token.
6. Enroll a Client¶
flowchart TD
Client[Client generates local identity metadata] --> API[IronRoot API]
API --> Token[Validate bootstrap token]
API --> DB[(Store enrollment)]
ironroot-client enroll \
--server http://localhost:8443 \
--hostname local-demo \
--token <token>
The hostname must match the --host value used when the bootstrap token was created. If you omit --hostname, the client sends the operating system hostname.
Copy the returned enrollment_id.
Enrollment ID versus token
Use the UUID returned by ironroot-client enroll for --enrollment-id. Do not reuse the bootstrap token for certificate requests.
7. Request a Website TLS Certificate¶
The client generates the private key locally. The key never leaves your machine. Only the CSR is sent to IronRoot.
flowchart TD
Client[Client generates key locally] --> CSR[CSR]
CSR --> API[IronRoot API]
API --> Intermediate[Intermediate signs cert]
Intermediate --> Bundle[Certificate chain returned]
ironroot-client request-cert \
--server http://localhost:8443 \
--enrollment-id <enrollment_id> \
--dns demo.home.arpa \
--out ./certs
This writes:
certs/tls.keycerts/tls.crtcerts/ca-chain.crtcerts/fullchain.crtcerts/metadata.jsoncerts/fingerprints.txtcerts/README.txt
Verify the full chain:
ironroot-admin ca verify-chain \
--root-cert ./pki/root/root-ca.crt \
--intermediate-cert ./pki/intermediate/intermediate-ca.crt \
--cert ./certs/tls.crt
8. Point a Local Name at Your Machine¶
Prefer demo.home.arpa for local testing. The .local suffix can conflict with mDNS on macOS and many Linux desktops.
Add this to /etc/hosts:
127.0.0.1 demo.home.arpa
9. Run a Local HTTPS Website¶
Nginx example:
podman build -f examples/nginx/Containerfile -t ironroot-nginx-demo examples/nginx
podman run --rm \
-v ./certs:/certs:ro,Z \
-p 8444:443 \
ironroot-nginx-demo
Caddy example:
podman-compose -f examples/caddy/podman-compose.yaml up
Python example:
cd examples/python-https
python3 server.py
10. Install the Root CA Trust Bundle¶
Browser trust works because the browser builds this chain:
flowchart TD
Root[Root CA trusted by OS/browser] --> Intermediate[Intermediate CA]
Intermediate --> Website[Website Certificate]
Website --> Browser[Browser accepts HTTPS]
macOS:
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ./pki/root/root-ca.crt
Debian/Ubuntu:
sudo cp ./pki/root/root-ca.crt /usr/local/share/ca-certificates/ironroot-local.crt
sudo update-ca-certificates
Fedora/RHEL:
sudo trust anchor ./pki/root/root-ca.crt
sudo update-ca-trust
Windows:
Open mmc, add the Certificates snap-in for the local computer, and import root-ca.crt into Trusted Root Certification Authorities.
Firefox:
Firefox may use its own trust store. Import root-ca.crt in Settings → Privacy & Security → Certificates → View Certificates → Authorities.
11. Open the Website¶
Open:
https://demo.home.arpa:8444
You should see a valid HTTPS connection with no browser warning. The certificate should chain from demo.home.arpa to the IronRoot Intermediate CA and then to the IronRoot Local Root CA.
How This Maps to Air-Gapped Production¶
In production:
- Generate and store the Root CA offline.
- Move only the Intermediate CSR to the offline machine.
- Sign the Intermediate offline.
- Move only the signed Intermediate certificate and trust bundle back to the online IronRoot server.
- Distribute the Root CA trust bundle through your approved offline package path.
- Never copy the Root CA private key to the server, Kubernetes, containers, or CI.