Domains & SSL
Give a site a real hostname with automatic HTTPS β point one DNS record at it, and SpipCP handles the certificate, renewal, and a check that it actually serves.
Attaching a domain gives a site a real hostname with automatic HTTPS. You give
the site a hostname and point one DNS record at the node. SpipCP routes the traffic, issues the TLS
certificate, and proves https://yourdomain actually serves the site before marking it green. A
domain that doesn't pass that check is never shown as working β it's failed with a fix to apply.
You attach domains from the site
Domains belong to a site, so you manage them under the site workspace's Networking tab β there's no separate top-level Domains page. The Networking tab has three sub-tabs: Domains (attach and manage hostnames), SSL (the certificate dashboard), and Routes (the underlying edge routes).
Domains your app's customers bring
This page is for domains you attach. If your app serves its own customers on their domains
(status.client.com), that's a different feature β see
Custom customer domains, where the certificate is issued on demand
and nobody adds each hostname in the panel.
The one thing you do in DNS
SpipCP asks for exactly one DNS record, and never anything else:
An A record:
yourdomainβ your node's IP (shown to you when you attach).
That's the whole DNS setup. Once that record resolves to the node, the attach continues on its own β verify DNS, issue the certificate, test HTTPS, go green. You don't create challenge records, upload anything, or click "activate."
Cloudflare users: DNS only, not Proxied
If your DNS is on Cloudflare, create that A record as DNS only (grey cloud), not Proxied (orange cloud) β unless you attach with the Cloudflare driver (below). This only applies to Cloudflare: the orange-cloud proxy is a Cloudflare feature, so DNS on Bunny, Hetzner, deSEC, Gcore, or your own nameservers has nothing to flip.
The orange cloud hides your server's real IP behind Cloudflare. With the manual driver SpipCP
checks that the hostname resolves to your node's IP, so a proxied record makes the check fail with
dns: failed even though the record exists β SpipCP sees Cloudflare's IPs, not your node. SpipCP
catches this and the remedy says so: "the record is proxied β set it to DNS only." Flip that one
record to grey, then Retry attach.
What the wizard tells you before you attach
As soon as you type a valid hostname, the wizard resolves its authority tier and shows a banner β before you commit β so you know what will happen:
- Hosted β "zone
example.comis on your nameservers; the DNS record will be created automatically." - Connected β "zone found in a provider account you hold (e.g. Bunny); the record will be created automatically." If your cascade's default account doesn't hold this zone, the banner warns of a mismatch and suggests a per-domain override so the attach doesn't fail at record-write time.
- External β "no connected account holds this zone (detected nameserver
dns1.registrar.com); you'll get the exact records to create by hand." This sets the expectation up front instead of surprising you at the DNS-verify gate. When the detected nameserver is one SpipCP recognises (e.g. Cloudflare), the banner also offers the fix as a cross-link β "Want automatic records and wildcards? Connect Cloudflare β" β which deep-links into the managed-provider journey with that provider preselected. On an unrecognised nameserver it links the bring-your-own-DNS journey instead.
The pre-flight is advisory: the real record write at attach time is always the source of truth. It just turns a late failure into an up-front expectation.
The guided journeys open this same wizard, prefilled
When you reach the attach step from a guided setup journey, the panel picks the site, then opens this wizard with the hostname and the right DNS driver preselected β the manage-records-myself and bring-your-own-DNS journeys preselect the manual driver, the managed-token journey preselects the provider. There is no separate attach form; the journey just drives the one you see here.
Attaching a domain
Enter the hostname. The FQDN the site answers on (e.g. app.example.com). HTTPS is automatic from
here β a free Let's Encrypt certificate, nothing to buy or upload. The wizard shows the detected
authority tier (above) as you type.
Pick a DNS driver.
- Manual β SpipCP shows you the A record to create; you add it at your DNS provider. (Cloudflare: set it DNS only.)
- A provider driver β Cloudflare, Bunny, Hetzner, deSEC, or Gcore β SpipCP creates the record for you through that provider's API, using a DNS account you set up once. With the Cloudflare driver, the proxy (orange cloud) is safe to leave on, because SpipCP reads the record from Cloudflare's API instead of a public lookup. The other providers have no proxy.
Certificate + check. SpipCP requests the certificate from Let's Encrypt, then tests that the hostname serves the site over a valid HTTPS connection. Only then does it go green.
If a domain fails (wrong record, still proxied, DNS not propagated yet), fix the record and press Retry attach on the domain row β it re-runs the whole flow from the DNS check. No need to detach and start over.
The SSL dashboard
Networking β SSL is a certificate dashboard β one row per domain, so you always know what you're running and when it expires:
| Column | What it tells you |
|---|---|
| Domain | The hostname the certificate covers. |
| Issued by | The certificate authority β Let's Encrypt (the default) in production, ZeroSSL / Actalis if you chose them, an uploaded custom cert, or the local dev CA (Pebble) in development. |
| Certificate | Its state: issued, pending, renewing, failed, or none. |
| Expires | The expiry date and time left (e.g. in 62 days); amber within 21 days. |
| HTTPS | Whether the check confirmed https://yourdomain serves with a valid certificate. |
| DNS | Which driver manages the record (manual, or a provider β Cloudflare / Bunny / Hetzner / deSEC / Gcore). |
| Renew now | Force an early renewal (rarely needed β see below). |
A summary strip at the top counts what's secured, what's expiring within 21 days, and what needs attention. The same certificate detail also appears inline on each domain's row in the Domains sub-tab.
Issuance and renewal are both automatic
You don't buy, upload, or activate a certificate. When you attach a domain, the node's reverse proxy (Caddy) requests a free certificate from Let's Encrypt and installs it. It then renews each certificate roughly 30 days before expiry β no downtime, no cron job. The Renew now button only forces an early renewal; you never need it in normal use. A certificate-expiry check also warns you long before one could lapse. The one exception is a custom (bring-your-own) certificate β it doesn't auto-renew; SpipCP still warns on its expiry, and you re-upload before it lapses (see Choosing a certificate issuer).
Automating DNS with provider accounts
To let SpipCP create the record for you, connect a named DNS account under Settings β DNS providers β a reusable credential you set up once and assign to many domains. SpipCP supports Cloudflare (US), Bunny (EU), Hetzner (German), deSEC (EU, DNSSEC by default), and Gcore (EU). Each account holds the provider's token, scoped to edit DNS records; the token is encrypted, write-only, and never reaches a node. See DNS providers for where to get each token and the EU/GDPR/free-tier notes.
The DNS-account cascade
You don't pick an account per domain by hand every time β a DNS account cascades node β instance β domain, exactly like git accounts:
| Level | Where you set it | Who inherits it |
|---|---|---|
| Node default | A node's DNS tab | every instance + domain under that node |
| Instance default | An instance's DNS tab | every domain on that instance |
| Per-domain override | The attach wizard / the domain row | just that domain |
A level left blank inherits from the one above, and the most-specific value wins: a domain override beats the instance default, which beats the node default. Change a node's default and every domain that never overrode follows automatically β no re-attach. Delete an account something pointed at and that reference falls back to "inherit the level above," never a broken pointer.
Set up an account first
Until at least one DNS account is available for a site, that provider's driver is disabled in the attach wizard, labelled "needs token in Settings", with a link to Settings β DNS providers β so you're never led down a path that fails at attach. Full guide: DNS providers.
Wildcard subdomains and the Caddy DNS module
A wildcard certificate for *.example.com is issued over a DNS-01 challenge β the node's Caddy
proves control of the domain by writing a TXT record through your provider's API. That needs the
matching caddy-dns/<provider> module built into the Caddy on the node serving the site. A single
hostname (no wildcard) uses the simpler HTTP-01 challenge and needs no DNS module.
If you request a wildcard and the node's Caddy lacks the right module, SpipCP doesn't fail silently β
the wizard names the missing caddy-dns/<provider> module, so you know exactly what the node needs
before the wildcard can issue.
Choosing a certificate issuer
Let's Encrypt is the default β free, automatic, nothing to configure. For operators who need an alternative, the issuer is selectable (an advanced choice in the attach wizard) and cascades node β instance β domain just like the DNS account:
| Issuer | What it is | Needs an account? |
|---|---|---|
| Let's Encrypt | The default ACME CA β automatic issue + renew. | No |
| ZeroSSL | An ACME CA requiring EAB (External Account Binding). | Yes β an EAB issuer account |
| Actalis (EU) | An EU ACME CA, also EAB-based. | Yes β an EAB issuer account |
| Custom | Bring-your-own certificate β paste the chain + private key (PEM). | Yes β a custom (PEM) issuer account |
ZeroSSL and Actalis need an EAB issuer account (a Key ID + HMAC key from the provider's dashboard), and Custom needs a PEM account (the certificate chain + private key). You add both under Settings β SSL issuers, where each secret is encrypted at rest and never reaches a node. Like the DNS account, the issuer account cascades β set a default per node or instance, override it per domain β and a chosen issuer with no account fails the attach with a remedy rather than going green.
β Full guide: SSL issuer accounts.
Custom certificates don't auto-renew
A custom certificate isn't issued automatically, so SpipCP can't renew it. It reads the PEM on upload to record the expiry, then warns you just like an automatic cert (amber within 21 days, then an alert) β but the fix is to re-upload a fresh chain before it expires (Edit the issuer account with the new PEM). Let's Encrypt, ZeroSSL, and Actalis all renew automatically.
What you can manage
| Control | What it does |
|---|---|
| Attach domain | Point a hostname at the site (one A record + the certificate). |
| DNS driver | Manual (you set the record) or a provider (Cloudflare / Bunny / Hetzner / deSEC / Gcore β SpipCP sets it). |
| Issuer (advanced) | The certificate authority β Let's Encrypt by default; ZeroSSL / Actalis or a custom PEM; Pebble for local dev. Cascades node β instance β domain. |
| DNS account | Which named DNS provider account drives the DNS write β inherited from the node/instance default, or overridden per domain. |
| SSL issuer account | Which named issuer account supplies the EAB / custom-cert credential for a non-default issuer β inherited or overridden per domain. |
| Retry attach | Re-run the attach after fixing a failed record (e.g. turning the proxy off). |
| Renew now | Force an early certificate renewal (rarely needed β renewal is automatic). |
| Orange-cloud | Toggle Cloudflare's proxy for a Cloudflare-driver domain (hidden for other providers β it's a Cloudflare product). |
| Wildcard subdomain | Optionally catch *.domain for the site (requires a provider driver + the matching caddy-dns module on the node, since wildcards need a DNS-01 challenge). |
How it works
The node's reverse proxy (Caddy) routes the hostname to the site's port on its instance, issues and auto-renews the certificate, and a certificate-expiry check warns you long before one lapses. The test before going green means "green" always means "actually serving."
β Routes detail: Sites β Networking. Β· Certificate alerts: Monitoring. Β· DNS accounts: Settings β DNS providers. Β· Self-hosted DNS: DNS β Self-hosted. Β· Issuer accounts: Settings β SSL issuers.
Sites
Launch and run a real website β domains, TLS, a database, files, and git deploys β all from the site workspace.
Custom customer domains
Let a hosted app serve its own customers on their domains β status.client.com, shop.client.ie β with automatic HTTPS, without anyone adding those domains in SpipCP. One toggle, one CNAME per customer, certificates issued on demand.

