A small, file-based X.509 Certificate Authority with support for smart cards — no servers, no databases, just files.
nanoca is a lightweight Bash script that implements a fully functional X.509 Certificate Authority for use on home or private networks. It wraps openssl to manage the full certificate lifecycle — creation, signing, revocation, and CRL generation.
Certificate Authority — the trusted root that issues and signs certificates.
Certificate Signing Request — a PEM file created by the requester and sent to the CA for signing.
Certificate — a signed PEM file produced by the CA from a CSR.
Certificate Revocation List — a CA-issued list of revoked certificates.
A CA is nothing more than a directory. Each CA lives entirely in its own folder — portable, auditable, and offline by default.
Because each CA is self-contained in a directory, you can maintain as many CAs as needed by simply using different directories. Switch between them with cd.
# Typical CA directory layout myca/ ├── ca.key # CA private key ├── ca.crt # CA certificate ├── ca.srl # Serial counter ├── server.crt # Issued certificate └── ca.crl # Revocation list
Spin up a brand-new Certificate Authority in an empty directory. Parameters gathered interactively.
Create CSRs for servers, clients, or any entity that needs a certificate, including SAN support.
Sign CSRs with your CA key to produce trusted X.509 certificates accepted by browsers and OS trust stores.
Mark any previously issued certificate as revoked — tracked in the certificate database.
Generate and distribute Certificate Revocation Lists so clients can verify revocation status.
Generate CSRs using PKCS#11-enabled hardware tokens via pkcs11_engine and p11-kit.
| Command | Description |
|---|---|
| nanoca create | Initialise a new CA in the current directory. Prompts for all CA parameters interactively. |
| nanoca list | List all certificates issued by this CA, including their serial numbers and status. |
| nanoca sign <csr> | Sign a CSR with the CA key and produce a signed X.509 certificate file. |
| nanoca re-sign <crt> | Re-sign an existing certificate — useful for renewing a certificate about to expire. |
| nanoca recreate-crl | Recreate and update the Certificate Revocation List from the current revocation database. |
| nanoca revoke <crt> | Revoke a previously issued certificate (CA-internal, updates the database). |
Make an empty directory and run nanoca create. Answer the interactive prompts for country, organisation, and validity period.
Import ca.crt into the OS or browser trust store of every device on your network.
Run nanoca gencsr <hostname> on the target host, or with a PKCS#11 token for hardware-backed keys.
cd into the CA directory and run nanoca sign <hostname.csr>. The signed certificate is written back to the CA directory.
Copy the certificate to the service. Revoke with nanoca revoke and publish fresh CRLs as needed.
nanoca supports CSR generation using PKCS#11 hardware tokens (YubiKeys, smart cards, HSMs). The private key never leaves the device — only the CSR is exported and signed by the CA.
pkcs11_engine supportp11-kit installed and configured# CSR with a PKCS#11 token nanoca gencsr --pkcs11 myservice # Private key stays on the token # Only myservice.csr is produced nanoca sign myservice.csr # → myservice.crt
If an attacker compromises the machine, they cannot steal the private key — it physically cannot leave the token.
Issue trusted HTTPS certificates for self-hosted services — NAS, Proxmox, Home Assistant — without self-signed certificate warnings.
Secure internal microservices, APIs, and dashboards with mTLS using a CA that lives entirely within your network perimeter.
Issue client authentication certificates for OpenVPN or WireGuard, replacing or augmenting pre-shared keys with PKI.
Quickly spin up a CA for local development. Multiple isolated CAs can co-exist for different projects or teams.
nanoca intentionally avoids heavy dependencies. Everything runs on tools already present on any modern Linux system.
As long as bash and openssl are available, nanoca works. The PKCS#11 integration is purely optional and only needed when using hardware tokens.