Caddy Storage
Swytch ships a Caddy storage module. A pool of Caddy instances configured with it becomes a Swytch cluster: TLS certificates, ACME account state, and OCSP staples replicate peer-to-peer, and ACME issuance locks are coordinated through Swytch’s serializable transactional path.
Running Caddy in high availability normally requires an external KV store (Consul, Redis, S3 + DynamoDB) for certificate storage and issuance locking. With this module there is no external dependency: the Swytch effects engine is embedded in the Caddy process itself.
The module is published as a separate Go module, github.com/swytchdb/swytch/caddy, to keep its dependency tree off
the Swytch core. Build a Caddy binary with xcaddy:
xcaddy build --with github.com/swytchdb/swytch/caddy
{
storage swytch {
cluster_passphrase <secret> # empty = single-node (no replication)
connection_secret <secret> # Swytch Cloud durability; excludes cluster_passphrase + join
join <dns-name> # peers resolve via DNS; optional
cluster_port <num> # QUIC port; default 7380/UDP
cluster_advertise <addr:port> # this node's reachable address; auto-detect if empty
key_prefix __caddy: # default; must live under __caddy:
lock_ttl 30s # ACME issuance lock TTL; default 30s
}
}
:80 {
# ... your site config
}
Point every Caddy instance at the same join DNS name (which must resolve to at least one peer’s cluster_advertise
address) and they form a cluster. cluster_passphrase must match across every node; generate one with
swytch gen-passphrase.
The field names are the JSON equivalents of the Caddyfile keywords:
{
"storage": {
"module": "swytch",
"cluster_passphrase": "...",
"connection_secret": "...",
"join": "...",
"cluster_port": 7380,
"cluster_advertise": "10.0.0.1:7380",
"key_prefix": "__caddy:",
"lock_ttl": "30s"
}
}
Setting connection_secret enables Swytch Cloud durability and
is a self-contained cluster identity: the cluster passphrase derives from it and peers come from the Cloud roster, so
it is mutually exclusive with cluster_passphrase and join. TLS state still replicates peer-to-peer; Cloud is the
backstop that rehydrates keys evicted from every live peer. Generate the secret with swytch gen-passphrase --cloud.
- Certificate storage uses the reserved
__caddy:key namespace, kept separate from Swytch’s internal keys so certificate data participates in normal eviction. - ACME issuance locks are acquired through serializable transactions with a TTL (
lock_ttl). If the holder dies without unlocking, the lock expires and another node acquires it; releases wake waiting nodes through replication callbacks rather than polling. - Single-node mode (
cluster_passphraseempty) binds no QUIC port and runs no peer discovery. It is useful for local development.
The embedded engine is a process-wide singleton and Caddy reloads reuse it. Changing cluster_passphrase,
connection_secret, join, cluster_port, cluster_advertise, or key_prefix at reload time is rejected; these are
baked into the QUIC listener, TLS certificate SAN, or peer-discovery state at startup. Restart the process to change
them. lock_ttl does take effect on the next reload.