Skip to content

setup-origin: ask the registry to sign, serve the chain, renew on a timer - #25

Merged
ralyodio merged 1 commit into
mainfrom
feat/registry-cert
Sep 16, 2026
Merged

ralyodio merged 1 commit into
mainfrom
feat/registry-cert

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

What

setup-origin.sh asks the registry to sign the name's certificate and serves the chain, so a client that trusts the pit's root (TronBrowser, a box that ran moshcode dns enable) accepts the name over https with no pin lookup and no per-name import. Renewal is a daily timer the script installs itself.

Registry side: moshcoder/moshcode#519. Client side: moshcoder/moshcode#520 (v0.102.0) and profullstack/tronbrowser.dev#109.

How

  • After the self-signed certificate is made as before, with MOSHPIT_API_KEY set and not --self-signed: check GET /api/moshpit/ca is enabled, make a CSR from the same key (openssl req -new), POST /api/moshpit/tlds/<tld>/certs { label, csr }, and write the returned chain (leaf, issuer, root) over $CERTDIR/<name>.crt, which is what the nginx block already serves. Same key, so the published pin does not move and pin clients keep working. The registry's root is kept at $CERTDIR/moshpit-root-ca.crt.
  • Fallbacks say what happened and keep the self-signed certificate: no key, --self-signed, a registry with no CA (enabled: false or 503), a refusal (the body is shown), a chain that does not parse or does not name the host.
  • With a signed chain the "trust it on this box" step installs the pit's root into the system store under moshpit-root-ca.crt, the same file moshcode dns enable uses, instead of the leaf.
  • scripts/moshpit-renew.sh: for each registry-signed certificate under $CERTDIR (issuer is not the name itself) within 10 days of expiry, re-run setup-origin.sh <name> --no-trust. Self-signed names are never touched. Reads the API key from /etc/moshpit/renew.env, which the script writes root-only (umask 077) on the first signed issuance.
  • systemd/moshpit-renew.{service,timer}: daily, randomised by an hour, persistent. Installed and enabled by setup-origin.sh on the first signed certificate when systemctl exists, from /opt/moshpit/systemd, so there is no step to remember.
  • --self-signed flag and MOSHPIT_SELF_SIGNED, MOSHPIT_RENEW_ENV environment; help updated.

Verified

  • tests/setup-origin-registry.test.ts (5): a dry run with a key says it would ask the registry and names the exact endpoint; --self-signed and no-key runs never mention the registry; moshpit-renew.sh exits 0 with a message on a box that was never signed, and with a fake setup-origin.sh renews only the signed certificate within the window while leaving the self-signed one and the still-valid signed one alone.
  • Existing tests/setup-origin.test.ts unchanged and green; full suite 92/92. sh -n on both scripts.
  • Not run against a live origin: that needs root on a box serving a name. The first real run is bonita or the dev droplet with MOSHPIT_API_KEY set, and openssl s_client -connect <name>:443 -servername <name> should then show a chain issued by CN=Moshpit Issuing CA.

🤖 Generated with Claude Code

…imer

The registry now runs a certificate authority for the names it holds (moshcoder/moshcode#519). With MOSHPIT_API_KEY set, setup-origin.sh sends a CSR for the name to POST /api/moshpit/tlds/:tld/certs and writes the chain it returns (leaf, issuer, root) over the certificate nginx serves, so any client that trusts the pit's root, TronBrowser or a box that ran moshcode dns enable, accepts the name with no pin lookup and no per-name import. Same key, so the published pin does not move and pin-checking clients keep working. The self-signed certificate stays as the fallback: no key, --self-signed, a registry without a CA, or a refusal all leave it in place and say so. With a signed chain the box trusts the pit's root instead of the leaf, under the same file moshcode uses. The 30-day leaf is renewed by scripts/moshpit-renew.sh, run daily by moshpit-renew.timer, which the script installs the first time it gets a signed certificate; the API key it needs is kept root-only at /etc/moshpit/renew.env.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit ddfa560 into main Sep 16, 2026
3 checks passed
@ralyodio
ralyodio deleted the feat/registry-cert branch September 17, 2026 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant