aethercert
Dokumentation
Referenz

Security and data handling

Where private keys live, what the control plane stores, how secrets are encrypted, data residency, and how to report a vulnerability.

aethercert runs an agent as root or LocalSystem on your servers and handles the material that identifies them. This page states what that means: what is stored, where, what an attacker would get from each component, and what they would not.

Private keys

A certificate's private key is generated on the host that will serve it, by the agent, at the moment of issuance - including at every renewal. It is written to the deploy target on that host and nowhere else.

It is not transmitted to the control plane, not escrowed, and not backed up. What the agent reports back is metadata: serial number, fingerprint, validity window, and success or the error text.

The consequence is worth being explicit about, in both directions:

  • A compromise of the control plane does not yield your private keys. They are not there to take.
  • aethercert cannot recover a lost key for you. If a host is destroyed, its certificate is reissued rather than restored. For a renewing certificate that is a non-event; it is the correct trade.

The network boundary

Agents make outbound HTTPS connections and accept none. There is no inbound port, no callback, no listener - so aethercert needs no firewall hole, no VPN and no public address on your side.

The one exception is the CA connector, which does listen, on your internal network only, on a port you choose. It is not reachable from the internet, and every request to it carries a short-lived, job-bound token that the connector verifies and then confirms against the control plane before touching the CA.

What the control plane stores

CategoryStored
ConfigurationDomains, certificate authorities, deploy target definitions, agents, agent groups, policies.
Certificate metadataCommon name, SANs, issuer, serial, fingerprints, validity, status. For external certificates, the full parsed public record and its PEM.
Credentials you supplyDNS provider credentials, deploy target passwords, SSO client secrets, reseller API credentials, mail app credentials, monitoring integration secrets. Encrypted - see below.
Audit trailThe event log, for the retention window of your plan.
Account dataEmail addresses, display names, organization profile and billing details.
Never storedPrivate keys of issued certificates. Script content for custom deploy targets.

Secrets at rest

Every secret you paste into the dashboard goes into Supabase Vault, encrypted, rather than into a plain column.

They are write-only from the browser's point of view. Once saved, a credential is never returned to a client again - editing shows an empty field, and leaving it empty keeps the stored value. Replacing a secret deletes the one it replaced, so a rotated credential is genuinely gone rather than merely superseded.

Secrets are compared by hash, never by string equality, and never appear in a log line or in an error body that reaches an API response.

DNS credentials are handed to agents as short-lived values fetched at the moment a challenge is being solved. They are not stored on the agent host.

The dashboard is not a code-delivery channel

This is the most important boundary in the product.

A deploy target can run a reload command or a script as root or LocalSystem on every host it applies to. That is the product working as intended - installing a certificate means telling a service to pick it up.

What is deliberately not possible is introducing new code through the dashboard:

  • Custom scripts are never uploaded. The script has to already exist in the agent's scripts directory, be a regular file, not be group- or world-writable, and be owned by root. The dashboard only selects it by filename.
  • Script variables are passed as environment variables (AC_VAR_<NAME>), never interpolated into a shell command, so no variable value can inject a command. Even a variable named PATH becomes AC_VAR_PATH.

A compromised dashboard account can therefore at most change which already-approved script runs, and with what variables. Placing new script content on a host requires access to the host.

Configuring a deploy target is separated from ordinary certificate work for the same reason: it requires the admin role, while issuing and renewing certificates with existing targets requires only member. See Roles and permissions.

Access control

The four roles - viewer, member, admin, owner - are enforced in the database through row-level security, not only in route handlers. A request the interface would not offer is refused server-side too.

The organization is the isolation boundary. Under an MSP plan, each customer is a separate organization rather than a filtered view of a shared tenant, so there is no cross-customer query to get wrong.

Reaching a workspace you are not a member of takes two things, and the database checks both on every query: the organization you belong to must manage that workspace - it either owns it or was granted it, and neither is inherited any further - and your own membership must reach it, which is either all managed workspaces, only the ones assigned to you, or none. Your role in an assigned workspace is the one recorded for it, not the one you hold in your own organization.

Authentication

Multi-factor authentication is mandatory and cannot be switched off. Password plus an authenticator code, a passkey, or Microsoft Entra SSO in an organization that relies on its own Conditional Access policies. At least one authenticator app stays enrolled regardless, so no single method is ever the only way in.

Irreversible actions re-check the requirement server-side rather than trusting the browser, and changing how you sign in asks for a fresh code even in a session that did not need one.

Sign-up is invite-only, enforced by a database hook on user creation rather than only by the sign-up form - so posting directly to the identity provider's own API does not get around it.

Repeated wrong passwords are throttled server-side. After 10 failed attempts an account is locked for 5 minutes, and each further failure doubles the next lockout up to a 24-hour ceiling; the same applies per source address at 50 attempts. While a lock is in effect the request is refused before it reaches the identity provider, and the attempt - address, browser, approximate location, count - is recorded. Fifteen minutes without a failure resets the counter, and a successful sign-in clears it.

Data residency

ComponentLocation
ApplicationHetzner, Nuremberg, Germany
DatabaseSupabase, Frankfurt (eu-central-1), Germany
EdgeCloudflare, as a TLS-terminating proxy for DDoS protection. It handles traffic, not storage
Your keys and certificatesYour own hosts, wherever they are

Storage and processing stay in Germany.

Your rights over your data

ExportSettings > Profile > Your data returns your profile and organization memberships as JSON (GDPR Art. 20), rate-limited to once per hour.
DeletionSettings > Security > Delete account erases your account and any organization you solely own (GDPR Art. 17). It requires a completed second factor and is refused if it would strand other members or MSP customer workspaces.
Anything elseCertificate and event-log export is not self-service. Ask if a specific compliance requirement needs it.

Transport and browser hardening

HSTS with a two-year max-age and includeSubDomains, X-Frame-Options: DENY and a frame-ancestors 'none' content security policy so the dashboard can never be framed, X-Content-Type-Options: nosniff, and a strict-origin-when-cross-origin referrer policy.

Any fetch of a customer-supplied URL - a webhook endpoint, an internal CA, a DNS provider's API - goes through a guard that blocks internal address ranges and re-checks at connect time against DNS rebinding.

Agent supply chain

An update is verified three times before it is installed, and none of the three can be skipped by a flag: the declared size, the SHA-256 - which comes from the control plane over TLS, so a compromised CDN cannot get past it - and a detached Ed25519 signature, whose key is on no server, so a compromised control plane cannot either.

The agent never decides which version to install. The control plane answers that per host, from the release catalogue: channel, staged rollout, downgrade protection. See Updates and release channels.

Auto-update can be turned off per agent to pin a version, in which case the dashboard shows the exact manual command instead.

Reporting a vulnerability

Do not open a public issue. Use GitHub private vulnerability reporting on the repository, or email [email protected].

Include the affected component and version, what an attacker gains, and enough detail to reproduce. If a certificate or private key is involved, send the fingerprint and serial - never the key material.

StageTarget
Acknowledgement3 business days
Initial assessment and severity10 business days
Fix or documented mitigation for critical and high30 days

Researchers are credited in the release notes unless they ask not to be. There is no paid bounty. Please allow 90 days before public disclosure, or less if a fix ships sooner.

Explicitly out of scope

An organization admin or owner configuring a deploy target, a reload command or a custom script is intended to result in code running as root on that organization's own hosts. That is the product. What is in scope is any way to make it happen across an organization boundary, or from a role below admin.

Auf dieser Seite