Skip to content

feat(reachability): add Caddy download, Caddyfile generation and Pebble tests - #204

Closed
Rinse12 wants to merge 6 commits into
masterfrom
feat/reachability-caddy
Closed

Rinse12 wants to merge 6 commits into
masterfrom
feat/reachability-caddy

Conversation

@Rinse12

@Rinse12 Rinse12 commented Nov 2, 2026

Copy link
Copy Markdown
Member

Part of #198 (step 4). Based on #203, so earlier commits show here until those merge.

Summary

src/reachability/
├── caddy.ts          # pinned download, Caddyfile generation, start/stop/reload via admin API
└── libp2p-dial.ts    # real handshake used to verify addresses
test/
├── helpers/pebble.ts                                 # pinned Pebble in skip-validation mode
└── reachability/caddy-pebble.integration.test.ts     # runs on all three OSes in CI

Caddyfile behaviour that came from running it, not from the issue:

protocols h1 h2                 Caddy's default HTTP/3 would take UDP on the HTTPS port, which kubo needs for WebTransport
auto_https disable_redirects    otherwise Caddy binds port 80 and fails to start if anything holds it
default_sni <ip>                browsers send no SNI for an IP, and behind NAT the local address is not the public IP
explicit issuer acme { dir }    Let's Encrypt only; Caddy's implicit fallback CA is never used

libp2p, @libp2p/websockets, @libp2p/noise, @libp2p/yamux and @libp2p/identify become direct dependencies, pinned to the versions already in the tree through pkc-js. They load lazily, only for a dial.

Deviation from the issue: Caddy obtains one certificate per identifier, so IPv4 and IPv6 get two certificates rather than one covering both. Browsers can't tell the difference. It costs one extra order per renewal and status lists both.

Evidence

  • Before: no way to terminate WSS for kubo.
    After: npm run test:cli: 55 files, 543 passed, 1 skipped.
Pebble issues for 127.0.0.1 with profile shortlived   -> covers 127.0.0.1, 100 < hours left <= 160
js-libp2p dial through Caddy to kubo                  -> Noise + yamux handshake, remote peer matches
same dial, Pebble's root not trusted                  -> refused
same dial, different expected peer id                 -> refused
UDP bind on the HTTPS port while Caddy runs           -> succeeds, so Caddy holds no UDP
Caddy reload via admin API                            -> no re-issue, dial still works
Caddy stop via admin API                              -> process exits

By hand, not in the suite: putting /ip4/127.0.0.0/ipcidr/8 back in Swarm.AddrFilters makes the dial fail, which confirms the issue's claim about the gater.

The hashes of all six Caddy archives were checked against Caddy's own SHA-512 list for v2.11.7. Each CI OS downloads and verifies the hash for its own platform.

Merge Danger

Door: two-way

Blast Radius: install-size

No command calls this code yet. Five new direct dependencies are already installed transitively at the same versions, so the installed tree should not grow. This adds a Pebble download to CI, and that download depends on GitHub releases being reachable.

computeKuboConfig(kuboConfig, reachabilityConfig, enabled) is the one place that
decides the kubo edits. planKuboConfig also returns a record of what changed,
which tells our entries from identical operator ones and lets disable restore
the touched fields byte for byte.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-02T13:11:53.600521Z 89ad237 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 42 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ec83c784-e363-4363-a51e-6173b39442df
Commits

Reviewing files that changed from the base of the PR and between 6121b54 and cb41e25.

Files ignored due to path filters: 3
  • package-lock.json is excluded by !**/package-lock.json
  • test/fixtures/pebble/listener-cert.pem is excluded by !**/*.pem
  • test/fixtures/pebble/listener-key.pem is excluded by !**/*.pem
Files selected for processing: 12
  • package.json
  • src/cli/commands/reachability/status.ts
  • src/reachability/caddy.ts
  • src/reachability/kubo-config.ts
  • src/reachability/libp2p-dial.ts
  • src/reachability/state.ts
  • test/cli/reachability-status.test.ts
  • test/helpers/pebble.ts
  • test/reachability/caddy-pebble.integration.test.ts
  • test/reachability/caddy.test.ts
  • test/reachability/kubo-config.test.ts
  • test/reachability/state.test.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@claude

claude Bot commented Nov 2, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89ad2376eb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

export const LOOPBACK_ADDR_FILTER = "/ip4/127.0.0.0/ipcidr/8";

export const WEBTRANSPORT_SWARM_ADDRESSES = [
"/ip4/0.0.0.0/udp/443/quic-v1",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid forcing Kubo to bind privileged UDP port 443

When the daemon runs as a normal Unix user, applying this transform makes Kubo fail to start with a permission error because every enable adds listeners on privileged UDP port 443. The integration test explicitly removes these listeners for the same reason (test/reachability/caddy-pebble.integration.test.ts:60-61), but production callers have no option to select an unprivileged port or omit them, so enabling reachability can take the node offline.

Useful? React with 👍 / 👎.

const status = await readReachabilityStatus(flags["pkcOptions.dataPath"] || defaults.PKC_DATA_PATH);

if (!status.configured) {
this.log("Reachability is not configured. Browsers cannot reach this node. Run: bitsocial reachability setup");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop directing users to a missing setup command

When status is run before configuration, this message tells the user to run bitsocial reachability setup, but the repository-wide command search finds only src/cli/commands/reachability/status.ts; no setup command or equivalent handler exists. Following the recovery instruction therefore produces a command-not-found error and leaves users unable to configure the feature.

Useful? React with 👍 / 👎.

reachability/config.json holds the operator's choices and refuses to load a
newer version rather than drop its fields. The daemon's check results go in a
separate file so they cannot overwrite a setup in progress.
…e status

Caddy keeps certificates for old addresses and other CAs until they expire, so
status now filters to the configured CA and current names. A damaged runtime
status file reads as no checks yet, and the text output prints domain and Caddy
checks.
…le tests

Caddy is downloaded on first use and checked against a sha256 pinned in source.
The generated Caddyfile keeps Caddy off UDP 443 and port 80. The integration test
issues a certificate for 127.0.0.1 from Pebble and completes a js-libp2p handshake
with kubo through Caddy.
@Rinse12

Rinse12 commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

Consolidated into #208.

@Rinse12 Rinse12 closed this Nov 2, 2026
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