Domains #
Buy and wire up vanity domains for AC pieces from the command line, via Porkbun (the registrar) and Cloudflare (the DNS).
A vanity domain (e.g. notepat.com, laklok.com) is just two things:
- DNS pointing the host at lith —
A → 209.38.133.33 - A host block in
lith/Caddyfilethat rewrites/to the piece and reverse-proxies the rest tolocalhost:8888
The registrar is only needed twice per domain: once to buy it, once to hand its nameservers to Cloudflare. After that a new host is one API call.
Setup (one time) #
-
Porkbun API access. Log into Porkbun → Account → API Access → create an API Key (
pk1_…) and Secret Key (sk1_…). Two things bite here: API access must also be enabled per-domain on the domain's own page, and the account needs a default WHOIS contact — registration borrows it, so buys fail without one. -
Store the keys in
aesthetic-computer-vault/.env:PORKBUN_API_KEY=pk1_… PORKBUN_SECRET_API_KEY=sk1_… -
Cloudflare uses the account-wide Global API Key already in the vault (
CLOUDFLARE_EMAIL+CLOUDFLARE_API_KEY).cloudflare.mjslooks through the same candidate env fileslith/deploy.fishdoes, since no single one has ever been canonical. -
Verify:
npm run domain ping→ prints your IP.
Commands #
npm run domain ping # test the registrar keys
npm run domain price .games .com .ac # register/renew/transfer prices per TLD
npm run domain check nom.games a.com # availability + price
npm run domain buy nom.games # register (prompts to confirm price)
npm run domain caddy nom.games nom # print the Caddyfile block
npm run domain cf adopt nom.games # create the Cloudflare zone (+ @ and www)
npm run domain cf adopt nom.games midi # …and extra hosts while you're there
npm run domain cf add nom.games api # add one host to an existing zone
npm run domain cf list nom.games # show the zone's records
npm run domain ns nom.games # registrar's current nameservers
npm run domain ns nom.games a.ns b.ns # repoint them (prompts)
npm run domain dns nom.games # registrar-side records, if still there
npm run domain dns nom.games add A midi 209.38.133.33
Moving a domain onto Cloudflare #
npm run domain cf adopt oskiewar.com midi # prints the two nameservers
npm run domain ns oskiewar.com cloe.ns.cloudflare.com rob.ns.cloudflare.com
Adopting is inert — Cloudflare will happily serve a zone nobody is pointed at, so you can verify it answers correctly before cutting over:
dig +short @cloe.ns.cloudflare.com midi.oskiewar.com A
Then repoint the nameservers. Check the old zone first (npm run domain dns <domain>) and carry over anything that is not just @ and www — an MX or a
verification TXT left behind is how mail and domain ownership quietly break.
Adding a subdomain to a domain already on Cloudflare #
npm run domain cf add oskiewar.com midi
Then add the host to its block in lith/Caddyfile and fish lith/deploy.fish.
Caddy obtains the certificate itself on first request.
Order matters. If the Caddyfile learns a hostname before DNS exists, Caddy
fails the ACME challenge (NXDOMAIN looking up A for …), backs off for five
minutes, and falls back to Let's Encrypt staging to protect the production
rate limit. TLS then answers with an internal-error alert and no certificate,
which reads like a broken cert but is really a missing record. Create the DNS
first; if you did it the other way round, systemctl restart caddy on lith
clears the backoff and the certificate lands in about fifteen seconds.
Why records are DNS-only #
cf adopt and cf add create records grey-cloud (unproxied) on purpose.
Proxying puts Cloudflare's certificate in front of lith, which forces that
host's Caddy block off its Let's Encrypt issuer and onto the origin-certificate
pattern used by the :443 block. That is a deliberate migration with its own
testing, never a side effect of adding a domain. Turn it on per host once you
actually want the CDN in front.
Roadmap #
- One
npm run domain add <domain> <piece>that buys, adopts, adds the host, writes the Caddy block, and redeploys. - Read the Caddyfile to check a host block exists before promising the certificate will issue.