Certificates & PKI
Athena runs its own internal certificate authority. On first start the server generates a self-signed Root CA and stores it on disk; from then on every agent that enrolls is issued a per-machine X.509 client certificate signed by that CA, and the server's own gRPC TLS certificate is signed by it too. There is nothing to buy, no public CA to reach, and no internet dependency — the whole trust chain lives inside your network, which is exactly what an air-gapped deployment needs.
This page covers the certificate authority and the certificate lifecycle. For how a host first joins the fleet — installer one-liners and the token handshake — see Agent Enrollment and Registration Tokens.
The Root CA#
When the PKI subsystem initializes, the server looks for a CA certificate and private key on disk. If they exist it loads them. If they are missing on a fresh install (no agents enrolled and no encrypted secrets stored yet) it creates a new self-signed Root CA. If they are missing on a server that already has agents or stored secrets, the server refuses to start rather than silently minting a replacement. The generated CA is a standard certificate authority:
| Property | Default |
|---|---|
| Subject | CN=Athena Root CA, O=Athena Deploy Center |
| Key | RSA 4096-bit, signed with SHA-256 |
| Validity | 10 years from creation |
| Basic constraints | CA = true, path length 1 |
| Key usage | Certificate Sign, CRL Sign, Digital Signature |
The CA is stored under the server's PKI directory (see the CertificatesPath setting
below). The CA private key is generated and kept on the server with restricted permissions and
never leaves it — only the public CA certificate is ever handed out to agents.
Agents and browsers need the public CA certificate to trust Athena. Download it from
GET api/pki/ca/download in PEM (.crt, for
Linux/macOS and manual import) or CER/DER (.cer, for Windows Group
Policy deployment), or with the Save-AthenaCACertificate cmdlet. Push the
.cer to the Trusted Root store via GPO for a whole domain at once.
The CA key also protects stored secrets#
The Root CA private key does more than sign agent certificates. Athena derives the encryption key for its stored secrets from it, so the same key protects:
- passwords in the Credential Vault;
- per-agent RustDesk access passwords;
- BitLocker recovery passwords, and the startup PINs set by BitLocker policies or per-agent PIN overrides (when the BitLocker module is in use).
In practice this means the database and the PKI are a matched pair. A database
paired with a different CA still holds those secrets, but nothing can decrypt them, and the enrolled
agents' certificates no longer chain to the server's CA. Back up the PKI directory together with the database, and restore them together — on
the virtual appliance, back up /data/athena and /data/pki together. See
Data Directories & Backup and
Database Restore & Recovery.
If the CA is missing at startup#
If the CA certificate or its private key is missing when the server starts, Athena first checks whether the database depends on the old CA, meaning it holds any agent or any encrypted secret from the list above.
- Nothing depends on it (a genuinely fresh install): a new Root CA is created as usual.
- Something depends on it: the server refuses to start. It logs a fatal message beginning "Root CA files are missing … but the database holds agents and/or encrypted secrets. Refusing to start" and exits with code 1, instead of coming up with an empty trust chain.
This usually means the database came back without its PKI, for example a restore that skipped the PKI directory, or a storage volume that failed to attach. The fix is to restore the PKI directory from the same backup as the database and start the server again. The log message tells you exactly what is missing.
If the old CA is truly gone and cannot be restored, you can tell the server to mint a new one
anyway by setting Pki:AllowNewCaWithExistingData to true (as an
environment variable: Pki__AllowNewCaWithExistingData=true). The server then starts,
logs the decision at Critical, and creates a new CA. Every stored secret
listed above is lost (re-enter credential passwords, RustDesk passwords and BitLocker
PINs, and expect stored BitLocker recovery passwords to be unreadable) and every agent must
re-enroll. Set it for one start only, then remove it.
Per-agent certificates#
During enrollment (after the registration token is validated) the server generates a fresh RSA key pair for the agent and issues it a client certificate signed by the Root CA. The certificate has:
- Subject
CN=<hostname>, O=Athena Agent, with the hostname also set as a DNS Subject Alternative Name. - Enhanced Key Usage = Client Authentication (OID
1.3.6.1.5.5.7.3.2) — these certificates authenticate the agent to the server, not the other way around. - An RSA key of the configured leaf key size (default 2048-bit), SHA-256 signature, and a validity of the configured agent certificate lifetime (default 30 days).
The issuance response contains the certificate, its private key, and the CA
certificate. The private key is returned to the agent only once at issuance — the
server stores just the public certificate (PEM), thumbprint, serial number, and validity dates in
its database. Issuing a certificate also stamps the agent's
CertificateThumbprint and CertificateExpires fields.
The agent's private key is delivered in the issuance/renewal response and is never stored on the server. If it is lost, the agent must obtain a new certificate (renew, or re-register).
How a certificate is validated#
On every authenticated agent connection the server validates the presented certificate. A certificate is accepted only when all of these hold:
- It chains to — and was issued by — this server's Root CA (issuer matches the CA subject).
- The current time is within its
ValidFrom…ValidUntilwindow. - It is present in the server database and not revoked.
Otherwise validation fails with a specific reason — no certificate provided, invalid format, not signed by the CA, expired, not yet valid, revoked, agent not found, or certificate not found. Revocation is checked against the database (the server tracks revoked certificates itself), so a revoked certificate stops working immediately.
Renewal & auto-renewal#
Because agent certificates are short-lived (30 days by default), they are renewed continuously.
An agent renews by presenting its current certificate to
POST api/pki/renew (certificate authentication, not a JWT). The server verifies the
current certificate belongs to that agent, issues a brand-new certificate, and then
revokes the old one with the reason "Renewed".
Automatic renewal is enabled by default (EnableAutoRenewal), driven by two settings:
certificates are renewed once they are within 7 days of expiry
(AutoRenewBeforeDays), and the check runs every 6 hours
(AutoRenewalCheckIntervalHours). In normal operation you never renew agent
certificates by hand.
Revoking certificates#
An administrator can revoke all certificates for an agent with
POST api/pki/agents/{agentId}/revoke and a reason. Revocation:
- Marks every non-revoked certificate for that agent as revoked, recording the reason, who revoked it, and when.
- Sets the agent's status to Revoked.
- Disconnects the agent if it is currently connected, and writes an audit entry.
A revoked agent can no longer authenticate and must re-register to rejoin the fleet. Revoked
certificates remain queryable via GET api/pki/revoked for the audit trail.
Extending vs. regenerating the CA#
The Root CA has a long life, but it will eventually approach expiry. There are two very different operations for renewing it — choose carefully:
| Extend | Regenerate | |
|---|---|---|
| Endpoint | POST api/pki/ca/extend | POST api/pki/ca/regenerate |
| Private key | Keeps the same CA key | Creates a new CA key |
| Existing agent certs | Stay valid — no disruption | All revoked — every agent must re-register |
| Effect | Issues a new CA certificate for the same key with fresh validity (default: the configured CA validity, 10 years; or pass additionalYears) | Full key rotation for emergencies (key compromise / breach) |
| Stored secrets | Untouched — the key they depend on does not change | Re-encrypted under the new key as part of the operation (see below); no restart needed |
| Old files | Old CA certificate backed up alongside it (.bak) | Old CA certificate and key backed up (.bak) |
| When to use | Routine renewal as the CA nears expiry | Last resort only |
Regenerating the CA revokes every agent certificate and forces the whole
fleet to re-enroll. Prefer Extend for normal renewals and reserve regenerate
for a confirmed key compromise. Both operations are written to the audit log
(CAExtended / CARegenerated; the initial CA logs
CACreated).
What regenerate does to stored secrets#
Because the stored secrets depend on the CA key, regenerating the CA carries
them over to the new key. Regenerate (from Settings → Security → Certificate,
POST api/pki/ca/regenerate, or Invoke-AthenaCACertificateRegenerate)
works in this order:
- Every stored secret is read with the current key first. If any secret cannot be decrypted, or secrets exist but the server cannot read them at all, regenerate is refused and nothing changes: same CA, same key, same agent certificates. Over REST the call returns HTTP 500 with a message starting "CA NOT regenerated" that says how many secrets were affected; in the console you see "Failed to regenerate Root CA certificate".
- The new CA is created.
- In a single database transaction, every agent certificate is revoked (reason "CA certificate regenerated - all certificates invalidated") and every stored secret is re-encrypted under the new key.
- The new CA goes live immediately. The old CA certificate and key are kept beside it as
.bakfiles, and the server uses the new key without a restart.
Two audit events are written: VaultReencrypted (the description gives the number of
secrets re-encrypted) followed by CARegenerated (the number of agent certificates
revoked). Saved credentials, RustDesk passwords and BitLocker recovery passwords and PINs keep
working after a regenerate. Only the agents need attention: they must re-enroll.
After a regenerate, the database's secrets match only the new CA. Take a fresh backup of the database and the PKI directory together, so that no older PKI backup gets paired with the newer database by mistake.
Monitoring expiry#
To stay ahead of renewals, list certificates expiring soon with
GET api/pki/expiring?withinDays=7 (default 7 days). The CA's own metadata —
subject, thumbprint, serial, key size, and validity dates — is available from
GET api/pki/ca/info, which also flags the CA as expiring soon when it is
within one year of expiry. In the console, the Root CA card lives under
Settings → Security → Certificate.
Configuration#
PKI behavior is controlled by the Pki configuration section. The defaults are sensible
for most deployments:
| Setting | Default | Meaning |
|---|---|---|
CertificatesPath | ./pki | Root directory for PKI files (CA under ca/, server cert under server/). |
CaSubject | CN=Athena Root CA, O=Athena Deploy Center | Distinguished name for the Root CA. |
CaValidityYears | 10 | Root CA validity in years. |
RootCaKeySize | 4096 | RSA key size for the Root CA. |
KeySize | 2048 | RSA key size for leaf certificates (agent client certs and the server gRPC TLS cert). Use 4096 for higher security. |
AgentCertValidityDays | 30 | Agent certificate lifetime in days. |
AutoRenewBeforeDays | 7 | Renew a certificate once it is within this many days of expiry. |
EnableAutoRenewal | true | Enable the automatic renewal background check. |
AutoRenewalCheckIntervalHours | 6 | How often the renewal check runs. |
ServerCertValidityDays | 365 | Validity of the server's gRPC TLS certificate. |
ServerCertPassword | (random) | Password for the server certificate PFX. If empty, a random one is generated and stored. |
AllowNewCaWithExistingData | false | Lets the server create a new CA at startup even though the CA is missing and the database already holds agents or encrypted secrets. Those secrets are lost and agents must re-enroll. Use for one start only; see If the CA is missing at startup. |
See Configuration for how to set these values.
Roles#
CA download and info (api/pki/ca, ca/download, ca/info) are
anonymous — agents need them before they hold a certificate. Agent registration
(api/pki/register) is gated by a valid registration token. Renewal
(api/pki/renew) and my-certificates require the agent's own
certificate authentication. Everything else is gated by a permission:
pki.view to list an agent's certificates and view expiring or revoked certificates,
pki.revoke to revoke an agent's certificates, and pki.manage to extend or
regenerate the CA. Of the built-in roles, only Admin holds these permissions.
Callers without the permission receive 403; unauthenticated callers receive
401. See Roles & Permissions and
Permission Model & Role Bundles.
REST API#
| Method & path | Auth | Purpose |
|---|---|---|
GET api/pki/ca | Anonymous | Root CA certificate (PEM text). |
GET api/pki/ca/download?format=pem|cer | Anonymous | Download the CA as a .crt (PEM) or .cer (DER) file. |
GET api/pki/ca/info | Anonymous | CA metadata (subject, thumbprint, serial, key size, validity). |
POST api/pki/register | Token | Register an agent and issue its certificate. |
POST api/pki/renew | Agent cert | Renew the calling agent's certificate. |
GET api/pki/my-certificates | Agent cert | List the calling agent's certificates. |
GET api/pki/agents/{agentId}/certificates | Admin | List an agent's certificates (includeRevoked default true). |
POST api/pki/agents/{agentId}/revoke | Admin | Revoke all of an agent's certificates. |
GET api/pki/expiring?withinDays=7 | Admin | Certificates expiring within N days. |
GET api/pki/revoked | Admin | All revoked certificates. |
POST api/pki/ca/extend | Admin | Extend the CA validity, same key (additionalYears optional). |
POST api/pki/ca/regenerate | Admin | Regenerate the CA with a new key (revokes all agent certs). |
PowerShell#
The Athena module ships cmdlets for the CA and certificate operations:
| Cmdlet | Purpose |
|---|---|
Get-AthenaCACertificate | Retrieve the Root CA certificate (PEM). -Server, -Port (default 8443). |
Get-AthenaCACertificateInfo | Show CA metadata and validity. |
Save-AthenaCACertificate | Save the CA to a file. -Path (required), -Format pem|cer, -Force. |
Get-AthenaExpiringCertificates | List certificates expiring soon. -Days (default 7). |
Get-AthenaRevokedCertificates | List revoked certificates. -Page, -PageSize (default 50). |
Revoke-AthenaAgentCertificate | Revoke all certificates for an agent. -AgentId, -Reason (both required), -Force. |
Invoke-AthenaCACertificateExtend | Extend the CA validity. -AdditionalYears; prompts for confirmation. |
Invoke-AthenaCACertificateRegenerate | Regenerate the CA with a new key. High-impact; prompts for confirmation, -Force to skip. |
# Export the CA and push it to a domain via GPO (Windows .cer)
Save-AthenaCACertificate -Path "C:\pki\athena-root-ca.cer" -Format cer
# See what's expiring in the next two weeks
Get-AthenaExpiringCertificates -Days 14
# Revoke a decommissioned host's certificates
Revoke-AthenaAgentCertificate -AgentId $id -Reason "Decommissioned" -Force
See the PowerShell Module reference for full cmdlet details.
Athena's CA is generated and stored entirely on your server — there is no external CA, no OCSP responder to reach, and no internet dependency. Revocation is tracked in the server's own database, so certificate trust works fully offline. See Air-Gapped Operation.