Skip to main content

Static certificates

The simplest approach is to provide certificate files directly:
Arc selects the certificate by matching the client’s SNI against each entry in order. Wildcards (*.example.com) are supported. The first entry in the certificates array is used as the default when no SNI matches. Arc reads certificate files at startup and re-reads them on hot reload (SIGHUP or file watcher change).

ACME — automatic certificate management

Arc can automatically obtain and renew certificates from Let’s Encrypt or any ACME-compatible CA. The certificate request and challenge are handled on the HTTPS listener itself. No HTTP port or DNS access needed:

HTTP-01 challenge

Requires an HTTP listener on port 80:

DNS-01 challenge

Supports Cloudflare, Route53, RFC2136, webhook, and external command: Cloudflare:
Route53:
External command (hook):

Account key configuration

The ACME account key is stored encrypted on disk. Arc reads the passphrase from an environment variable or a file:
or from a file:

TLS version and cipher control

mTLS to upstreams

Configure mutual TLS for upstream connections by adding a tls block inside the upstream definition:
When tls is present, Arc performs a TLS handshake with the upstream on every new connection. If client_cert_pem and client_key_pem are set, Arc presents a client certificate (mutual TLS).

SNI-based routing

Arc selects the appropriate certificate based on the TLS SNI extension in the ClientHello. The matching order:
  1. Exact match (example.com)
  2. Wildcard match (*.example.com)
  3. Default (first certificate in the array)
Rendezvous hashing across cluster nodes ensures the same domain always hits the same node during ACME challenges, preventing race conditions when multiple nodes are active.

Certificate renewal

Arc tracks certificate expiry and renews before the renew_before threshold (default: 30 days). On renewal:
  1. Arc contacts the ACME CA and completes the configured challenge
  2. The new certificate is stored and activated atomically via ArcSwap
  3. Existing TLS connections continue using the old certificate until they close
  4. New connections use the renewed certificate immediately
No process restart or hot reload is needed for certificate renewal.

Troubleshooting

Check that the sni field in certificates matches the hostname exactly, including wildcard syntax (*.example.com). The first certificate in the array is the default fallback when no SNI matches. Use openssl s_client -connect localhost:8443 -servername example.com to see which certificate Arc presents.
TLS-ALPN-01 requires port 443 to be publicly reachable and the listener name must match the listener field in acme.challenge. HTTP-01 requires port 80 and an http listener bound to that port. DNS-01 requires the DNS provider credentials to be correct and the domain’s authoritative nameservers to be reachable. ACME errors are written as system log entries. Check the access log for kind: "system" entries.
Arc renews renew_before ahead of expiry (default 720h). If the certificate is newer than renew_before, no renewal fires. Check arc_tls_cert_expiry_seconds in /metrics to see the time remaining. If renewal is overdue, check ACME challenge reachability.
The listener kind is https or h3 but no tls.certificates are present and tls.acme is not configured. Add at least one certificate entry or configure ACME.
Ensure the upstream tls.ca_pem points to the correct CA bundle. If the upstream uses a self-signed certificate, add tls.insecure: true (use only in development).