Skip to content

Domains

Every Inky Labs domain is registered in the default Porkbun account, and its DNS is served from there. There is no Inky Labs subaccount, and none is planned, so that account also holds personal domains (latilde.org, symbolics.dev and others).

That matters for its API keys. Porkbun’s API has no notion of subaccounts: each account has one key pair, and it reaches every domain in the account. The keys Inky Labs’ CI holds therefore reach the personal domains too (AWS says where they go, and how that might be narrowed). They are kept in ~/.env:

Terminal window
PORKBUN_API_KEY=pk1_…
PORKBUN_SECRET_KEY=sk1_…

porkbun uses them with no --profile.

Check every account you have keys for. Porkbun answers a request for a domain held by another account with INVALID_DOMAIN and the hint “The domain name is invalid. Check the formatting.” The domain is fine; the key is the wrong one. porkbun catches that error and names the profile that does hold the domain, when you have keys for it (here, SVRBC’s subaccount):

$ porkbun dns list svrbc.org
porkbun: svrbc.org is not in the default account; it is in profile svrbc. Rerun with --profile svrbc.

To see everything at once:

Terminal window
porkbun domains --all # every configured account, with a profile column

A hostname says what is served there, not what serves it:

  • A site is its domain: inkylabs.com, qev.inkylabs.com, lofi.inkylabs.com. The GitLab project serving it has the same name.
  • A service is <what it serves>.<domain>: bazel-cache.inkylabs.com (the Bazel cache, on Inky Labs’ domain because every project uses it), developers.inkylabs.com (this handbook). Not s3.… or cdn.…: the provider can change without the name changing.
  • assets.<domain> is a site’s large files (PDFs, audio, video): CloudFront in front of the site’s own bucket, inkylabs-<domain>-assets, with every file at a content-addressed key, /<sha256>/<name>. The site keeps its own paths and redirects them there (Builds and CI). Inky Labs has none yet; SVRBC’s assets.doreancon.org is one.
  • A subdomain under a wildcard needs a placeholder record before its certificate. Until the name exists, a *.<domain> record answers for it, and the certificate authority reads the wildcard target’s CAA records (Vercel’s don’t allow Amazon, so ACM fails with CAA_ERROR). Add a TXT at the name first, then replace it with the real record.

The AWS resources behind them follow AWS naming.

This is how developers.inkylabs.com is to be set up (not done yet):

  1. In the project, add the domain with automatic HTTPS. With glab:

    Terminal window
    glab api -X POST "projects/inkylabs%2F<project>/pages/domains" \
    -f domain=<name>.inkylabs.com -F auto_ssl_enabled=true

    The response carries a verification_code.

  2. Add the two records, as porkbun_dns_records in infra/inkylabs-com-dns (DNS changes go through OpenTofu): a CNAME from <name> to inkylabs.gitlab.io, and a TXT at _gitlab-pages-verification-code.<name> holding gitlab-pages-verification-code=<code>. Release it, so CI applies it. To look before and after:

    Terminal window
    porkbun dns list inkylabs.com --name <name>
  3. Ask GitLab to verify. It runs the DNS check itself, then issues a Let’s Encrypt certificate within a few minutes:

    Terminal window
    glab api -X PUT "projects/inkylabs%2F<project>/pages/domains/<name>.inkylabs.com/verify"
  • Disable DNSSEC before starting a transfer. Once a transfer is pending, the registry blocks every update, so neither registrar can remove the DS records. A signed domain whose DNS moves while its DS records stand resolves nowhere. Check with dig +short DS <domain>. If it answers, disable DNSSEC and wait out the DS TTL first.
  • Export the zone from the old registrar’s panel, rather than probing for records. Probing finds only the names you think to guess.
  • A DKIM TXT record is one unbroken string. Control panels display a space at the 255-character split, and copying that space breaks DKIM silently.
  • Afterwards, porkbun check <domain> checks the delegation, the nameservers and public resolution in one go.