SG SealGrid Athena Docs

Server TLS Certificate

Athena serves the web console and API directly over HTTPS — no separate web server is required. On first start it issues its own certificate from its built-in Root CA, so browsers that don't trust that CA show a certificate warning. This page explains how to install your own CA-issued certificate to remove that warning, and how the certificate is used when Athena runs behind a reverse proxy or load balancer.

Two certificates, two ports#

Athena listens on two TLS ports, and they use certificates for different reasons. It is important to understand the split before changing anything:

PortUsed byCertificate
8443 — web console & REST APIBrowsers, the REST API, the PowerShell moduleReplaceable. Serves your own certificate when one is configured; otherwise falls back to the auto-generated Athena CA certificate.
8444 — agent gateway (gRPC over HTTP/2)Enrolled agents onlyAlways the Athena CA certificate. Agents trust this CA and authenticate with mutual TLS, so this port is not replaceable.

Only the web port (8443) certificate is meant to be swapped. Leave the agent gateway (8444) on the Athena CA certificate — agents receive and pin that CA during enrollment, and changing it would break agent connectivity. See Certificates & PKI for the agent-side trust model.

The default self-signed certificate#

When you don't supply your own certificate, Athena generates a web certificate signed by its own Root CA on first start and serves it on port 8443. It is a fully valid certificate — traffic is encrypted with TLS 1.2 or 1.3 — but because public browsers and operating systems don't trust the Athena Root CA out of the box, they display a “not secure” / “certificate not trusted” warning. You have two ways to remove that warning:

Naming the self-signed certificate#

Even if you keep the self-signed certificate, set Server:Hostnames so the certificate matches the address people actually type. Its value is a comma-separated list of DNS names; the first name becomes the certificate subject and every name is added as a Subject Alternative Name (SAN). If you leave it empty, the certificate is issued for the server's machine name only, which usually won't match a browser URL and can still trigger a name-mismatch warning.

# Names the auto-generated web certificate answers to
Server__Hostnames=athena.contoso.com,athena

Installing your own certificate#

To serve the web port with your own certificate, provide it as a PFX/PKCS#12 file (.pfx) and point Athena at it:

SettingEnvironment variablePurpose
Server:WebCertPathServer__WebCertPathFull path to your PFX certificate file, inside the container.
Server:WebCertPasswordServer__WebCertPasswordPassword that protects the PFX. Supply as an environment variable, not in appsettings.json.

The certificate must be reachable inside the container, so mount it in from the host and use the container path in Server__WebCertPath. A typical run:

# Mount your PFX read-only and point the web port at it
docker run -d --name athena \
  -p 8443:8443 -p 8444:8444 \
  -v /etc/athena/certs:/app/certs:ro \
  -e Server__WebCertPath=/app/certs/athena.pfx \
  -e Server__WebCertPassword=<pfx-password> \
  -e Server__PublicUrl=https://athena.contoso.com:8443 \
  sealgrid/athena:latest

The change takes effect when the server starts, so restart the container after adding or replacing the certificate. On start-up the server log records whether the web port is serving your external certificate or the Athena CA fallback.

Fallback when the file is missing

If Server:WebCertPath is empty or the file it points to can't be found, Athena silently falls back to the auto-generated Athena CA certificate on the web port. If your certificate isn't taking effect, first confirm the path is correct inside the container (check your volume mount) and that the container can read the file.

Preparing the PFX#

If your CA gave you a separate certificate and private key (for example a PEM fullchain.pem and privkey.pem from Let's Encrypt), bundle them into a single PFX first. Include the full chain so clients can build a path to the trusted root:

# Combine a PEM certificate chain + key into a PFX
openssl pkcs12 -export \
  -inkey privkey.pem \
  -in fullchain.pem \
  -out athena.pfx

Use the export password you set here as Server__WebCertPassword. Make sure the certificate's subject or SAN includes the exact hostname clients use to reach the console.

TLS version & HSTS#

Both ports negotiate TLS 1.2 or TLS 1.3 only. The legacy TLS 1.0 and 1.1 protocols are permanently disabled and cannot be re-enabled, so very old clients will simply fail to connect. This applies whether you use the built-in certificate or your own.

Athena also sends an HTTP Strict-Transport-Security (HSTS) response header with a one-year max-age, instructing browsers to only ever reach the console over HTTPS. The header does not include subdomains and is not submitted to the browser preload list, which suits an internal deployment reached by IP or a specific hostname. HSTS is one of several hardening headers Athena sends on every response — see HTTP Security Headers & Content Security Policy for the full set and how a reverse proxy can affect them.

Behind a reverse proxy or load balancer#

Athena terminates TLS itself and needs no reverse proxy, but you can place one in front — for TLS offload, a shared virtual IP, or a corporate load balancer. When you do, tell Athena which front-end addresses it should trust, otherwise it ignores forwarded client information and records the proxy's address for every request.

Athena honors the X-Forwarded-For (original client IP) and X-Forwarded-Proto (original scheme) headers, but only when the connection comes from an address on your trusted-proxy allowlist. If the allowlist is empty (the default), these headers are ignored and the direct connection address is used as-is. This protects per-IP rate limiting and the audit trail from spoofed headers. Configure the allowlist with either or both of:

SettingEnvironment variableValue
Security:TrustedProxiesSecurity__TrustedProxies__0, __1, …Individual proxy IP addresses, e.g. 10.0.0.5.
Security:TrustedProxyNetworksSecurity__TrustedProxyNetworks__0, …Proxy subnets in CIDR notation, e.g. 10.0.0.0/24.

In JSON these are arrays; as environment variables, each list element is indexed with a numeric suffix:

# appsettings.json
"Security": {
  "TrustedProxies": ["10.0.0.5"],
  "TrustedProxyNetworks": ["10.0.0.0/24"]
}

# or as environment variables
Security__TrustedProxies__0=10.0.0.5
Security__TrustedProxyNetworks__0=10.0.0.0/24

When a proxy handles the public TLS, also set Server:PublicUrl to the externally reachable base URL so links the server generates point at the front-end address rather than the internal host:

Server__PublicUrl=https://athena.contoso.com

The agent gateway on 8444 speaks gRPC over HTTP/2 with mutual TLS and should be exposed end-to-end, not TLS-terminated at a generic HTTPS proxy. Front only the web port (8443) with your proxy, and pass the agent port straight through.

Verifying the certificate#

After restarting, confirm the web port is presenting the certificate you expect. From a client that trusts the issuing CA, the console should load with no browser warning. You can also read the presented certificate directly:

# Show the certificate the web port presents (subject, issuer, validity)
openssl s_client -connect athena.contoso.com:8443 -servername athena.contoso.com </dev/null \
  | openssl x509 -noout -subject -issuer -dates

The issuer line should name your CA (not Athena Root CA), and the subject/SAN should match the hostname you connect with. The server also reports its TLS posture and which web certificate is in use in the start-up log — see Server Logging.

Troubleshooting#

SymptomLikely cause & fix
Browser still warns after installing a certificateThe web port fell back to the Athena CA certificate. Check that Server__WebCertPath points to a path that exists inside the container and that the volume is mounted, then restart.
“Name mismatch” warningThe certificate subject/SAN doesn't include the hostname clients use. Re-issue with the correct name, or (for the self-signed certificate) set Server:Hostnames.
Certificate loads but chain is “incomplete”The PFX is missing intermediate CA certificates. Rebuild it from the full chain (e.g. fullchain.pem).
Old client can't connect at allIt only supports TLS 1.0/1.1, which are disabled. Update the client — these protocols cannot be re-enabled.
Audit trail / rate limiting shows the proxy IP for everyoneThe proxy isn't on the trusted-proxy allowlist. Add it to Security:TrustedProxies or Security:TrustedProxyNetworks.