Skip to content

Custom domains ​

A frontier edge exists to serve your own domain: a browser hits https://app.example.com, the edge terminates TLS with a certificate the console issued, and the request travels end-to-end encrypted to the target on your gateway. This page walks app.example.com → a target named web, through an edge at edge.example.com.

Domains, certificates, and routes are all console-owned: you attach the domain in the console, the console issues the certificate and pushes both cert and route down to your edge over the carrier. The edge machine itself never runs an ACME client.

1. Attach the domain in the console ​

In console.burrowee.com, open ACM → Add custom domain:

  • Gateway — the gateway that owns the target.
  • Hostname — app.example.com.
  • Service — the target name on the gateway (web).
  • Relay — when the gateway connects through more than one relay, a selector appears. Auto (all relays) serves the domain on every relay the gateway uses; picking your edge pins the domain to it.

If you have already verified example.com as a wildcard in the pool above, you can choose the existing *.example.com certificate — instant, no DNS step, skip to pointing the domain. Otherwise pick Issue a new certificate for this exact host and continue.

2. Publish the DNS records ​

Two records at your DNS provider:

The routing record — point the domain at the edge itself, with an A record to the edge's public IP or a CNAME to its hostname:

app.example.com.    CNAME    edge.example.com.

The validation record — the console shows this one after the attach (the Setup panel on the domain row): a _acme-challenge CNAME delegating certificate validation to Burrowee's ACME zone:

_acme-challenge.app.example.com.    CNAME    <slug>.acme.burrowee.net.

Copy the exact name and target from the console — the <slug> is unique per domain. This record is what lets the console prove domain control and issue the certificate without you ever handling a challenge; leave it in place so renewals keep working.

3. Verify and wait for issuance ​

Press Verify on the domain row. Issuance takes about a minute after the DNS records propagate; the row's certificate badge flips when the certificate is ready, and the console pushes the certificate and the app.example.com → (gateway, web) route to your edge over the carrier.

4. Confirm on the edge ​

On the edge machine:

sh
burrowee edge doctor
burrowee edge status

doctor confirms the console link is up (the cert can only arrive over it) and, on a frontier edge, includes a custom domain routing row that checks every console-attached domain is present in the installed nginx SNI front and reachable — burrowee edge doctor --fix reconciles the front if a pushed domain drifted out of it. status prints the signed config the edge is serving — app.example.com should appear under served domains. If status still shows the old config, make sure the edge is running and give the carrier a moment, then re-check.

Then prove it end to end from anywhere:

sh
curl -I https://app.example.com

A response served over a valid certificate means the whole chain — DNS, cert, route, edge, gateway, target — is live. For a web target, opening https://app.example.com in a browser is the same proof.

Troubleshooting ​

  • Issuance never completes. DNS propagation is the usual cause. Check that _acme-challenge.app.example.com resolves to the exact <slug>.acme.burrowee.net target the console shows, wait a few minutes, and press Verify again.
  • Certificate issued but curl can't connect. The routing record is missing or points elsewhere — confirm app.example.com resolves to the edge's address, and that the edge is running in frontier mode with :443 reachable (burrowee edge doctor).
  • The edge restarted and the domain serves an error. Certificates are re-pushed when the edge reconnects; if a domain stays broken after a restart, run burrowee edge doctor — a red custom domain routing row means the domain drifted out of the nginx front, which burrowee edge doctor --fix reconciles. If that's healthy, check burrowee edge status for the domain and re-verify from the console's ACM page.
  • Visitors see a "not available yet" page. The domain and route are fine — the gateway behind it is offline. That page is the offline placeholder (a 503 with Retry-After: 60): bring the gateway's tunnel back up and the next request goes through.

The edge's own certificate ​

The certificates above are for your custom domains — they cover app.example.com, not edge.example.com itself. The edge also needs a certificate for its own host FQDN — the name it's reachable at directly, and the name the console associates with this specific edge — and that one you issue, since it's your machine, not a gateway target the console manages:

sh
burrowee edge cert issue                                    # issue/renew via Cloudflare DNS-01
burrowee edge cert issue --hostname edge.example.com --cf-token @/path/to/token
burrowee edge cert status                                   # print expiry, or "none"

cert issue issues a Let's Encrypt certificate for the nginx SNI front via Cloudflare DNS-01 (a Cloudflare token with Zone:DNS:Edit on that zone), or --manual to publish the _acme-challenge TXT record yourself with no token. bootstrap's frontier prompt and doctor --fix both call this the same way. Renewal isn't automatic in the background: cert status flags a certificate expiring within 30 days, and doctor --fix is what actually renews it — run doctor on a schedule (or rely on it after a console-pushed config change) rather than the host cert quietly lapsing.

The host FQDN is not load-bearing for routing: an edge serving only custom domains routes fine without a host_fqdn, and if the config key ever ends up empty or drifted the edge self-heals it from the host certificate on disk — a drift that used to surface as 5xx errors on a CDN-proxied host.

Unmatched hosts ​

A request that hits the edge with no matching route — a scanner probing the IP directly, or a stale/wrong hostname — is answered with a generic, unbranded placeholder page rather than an error that identifies the edge. The pages live in covers/ under the edge's data root (/usr/local/var/burrowee/edge/covers/ on a system install) — the installer lays down defaults (never overwriting ones you've customized); drop your own HTML there to control what an unmatched request sees.

A routed custom domain whose tunnel is offline is different: a visitor gets a self-contained "not available yet" page — an HTTP 503 with Retry-After: 60, never cached — instead of an error or a redirect. The domain exists, the target just isn't reachable right now; the page tells the visitor exactly that, without leaking anything about the setup. Unmatched hosts still get the placeholder page above, so an unrouted probe learns nothing about which domains this edge serves.