acme

package
v1.11.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package acme handles the agent side of the per-agent direct-TLS feature (plex.direct model). The agent generates and keeps its private key LOCALLY, builds a CSR for *.<hash>.agent.unarr.app, and sends only the CSR to the web-side broker (which runs the ACME order against Let's Encrypt via DNS-01 and returns the signed chain). The key never leaves the machine.

File layout under the agent state dir:

certs/agent.key   ECDSA P-256 private key (PEM, persisted across renewals)
certs/agent.crt   issued certificate chain (PEM, hot-reloaded by the stream server)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildCSR

func BuildCSR(dataDir, hash, baseDomain string) (csrPEM string, err error)

BuildCSR ensures the persistent key exists and returns a PEM CSR requesting the wildcard *.<hash>.<baseDomain> (plus the bare <hash>.<baseDomain> so a future non-wildcard use still validates). baseDomain e.g. "agent.unarr.app".

func GenerateHash

func GenerateHash() (string, error)

GenerateHash returns a 32-hex-char (16-byte) high-entropy agent hash label.

func NeedsIssue

func NeedsIssue(dataDir, hash, baseDomain string) bool

NeedsIssue reports whether we should (re)request a cert: true when the cert is missing, unparseable, expired, within renewBefore of expiry, OR issued for a hash other than the current agent hash.

The hash-mismatch case is load-bearing: agent_hash can be regenerated (config reset / identity migration) while the OLD cert — for *.<oldHash>.<base>, not yet expired — stays on disk. The web then encodes every direct-TLS hostname under the NEW hash (<ip>.<newHash>.<base>), so the browser is served a cert whose CN/SAN don't match → TLS validation fails → direct-TLS is silently dead for up to the cert's ~90-day lifetime, forcing every remote https:// browser onto the (flaky) cloudflared funnel. Re-issuing whenever the on-disk cert doesn't cover the wildcard for the CURRENT hash makes direct-TLS self-heal on the next renewal tick. hash/baseDomain empty (direct-TLS not configured) skips the check and keeps the pure expiry semantics.

func Paths

func Paths(dataDir string) (keyPath, certPath string)

Paths returns the key/cert file paths under the agent state dir.

func WildcardName

func WildcardName(hash, baseDomain string) string

WildcardName is THE identity→SAN mapping for the per-agent cert: the wildcard name BuildCSR requests and NeedsIssue asserts on the issued cert. Single source so the two sides (request vs verify) can never drift — a silent drift would make NeedsIssue re-issue on every renewal tick forever.

func WriteCert

func WriteCert(dataDir, certPEM string) error

WriteCert persists the issued certificate chain atomically (temp file + rename) so a concurrent reader (NeedsIssue, or the listener's GetCertificate reload) can never observe a half-written PEM during a renewal.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL