Skip to content

feat(reachability): make kubo dialable from browsers - #208

Merged
Rinse12 merged 30 commits into
masterfrom
feat/reachability
Nov 3, 2026
Merged

Rinse12 merged 30 commits into
masterfrom
feat/reachability

Conversation

@Rinse12

@Rinse12 Rinse12 commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Closes #198
Closes #209

Closes #216
This replaces #202, #203, #204, #205, #206 and #207, which were one feature split across a stack. Their review comments stay on those PRs.

Summary

bitsocial reachability setup     # discover, configure, issue, verify; safe to rerun
bitsocial reachability enable    # repair from stored choices, no prompts
bitsocial reachability disable   # stop serving, keep state; --purge moves it to a timestamped backup
bitsocial reachability status    # mode, addresses, cert expiry, last checks; --json
src/reachability/
├── kubo-config.ts   # pure (kubo, reachability, enabled) -> kubo, plus a record of what changed
├── state.ts         # versioned config.json; runtime-status.json is written only by the daemon
├── caddy.ts         # pinned download, Caddyfile generation, admin API
├── libp2p-dial.ts   # real handshake used to verify an address
├── discovery.ts     # interfaces, kubo addresses, port holders, container
├── nat.ts           # UPnP
├── setup.ts         # Path A, Path B, apply, verify
├── runtime.ts       # the daemon's side: keep Caddy up, 5-minute checks, IP moves, stale names
├── lifecycle.ts     # disable, purge
└── guidance.ts      # per-OS messages, proxy snippets

Evidence

  • Before: a bitsocial-cli node had no WSS address once libp2p.direct went away, and nothing reported it.
    After: npm run test:cli: 64 files, 961 passed, 2 skipped.

Real binaries, on Linux locally and on all three OSes in CI (Pebble as the CA, 127.0.0.1 as the "public" address):

setup on a running daemon            -> certificate issued, kubo restarted, js-libp2p handshake through the daemon's Caddy
wrong CA / wrong peer id             -> dial refused
Caddy stopped                        -> daemon brings it back, handshake works again
disable                              -> touched kubo fields byte-identical to before setup, Caddy gone
enable                               -> same fields as before disable, certificate reused, handshake works
--announce through a separate proxy  -> announced only after a handshake through it
daemon stops                         -> Caddy gone

Pure logic, with a fake clock where it matters:

17 kubo config shapes: disable(enable(x)) == x and enable(disable(enable(x))) == enable(x), byte for byte
stale name: warn at 0 h, silent at 30 min, warn at 61 min, dropped after 24 h, restored on recovery
IP change: acted on after 2 readings; no result for a family is not a change

Another Caddy on the machine, real binaries:

holds HTTPS, no domain      -> left running, exit 2, kubo gets only UDP 443 listeners, prints a block for its Caddyfile
--announce before forwarding -> refused, WSS edits rolled back
--announce after forwarding  -> real handshake through that Caddy, then announced
holds HTTP only             -> Pebble really validating: certificate obtained through the HTTPS port, handshake works

Fixed from review, each with a test:

kubo config rewritten with default permissions   -> mode kept, private key stays private
port probe on Windows missed a [::] listener     -> both address families checked
no certificate after an IP change                -> addresses kept, retried after 1 h, doubling up to 24 h
disable during an IP change                      -> disable stands
adopted Caddy stopped                            -> noticed, daemon starts its own
something else on our admin port                 -> not adopted, stopped or reloaded; setup picks a new port
hand-added loopback ws listener                  -> reused rather than adding a second
forced domain on rerun                           -> kept
another server takes 443                         -> our sites leave the Caddyfile
router leases                                    -> requested at daemon start, released once disabled
stale domain during a setup rerun                -> keeps its Caddy site; daemon announces it again on recovery
setup moves to another domain                    -> old dropped name forgotten, not announced with no site
proxy address matching the domain                -> IP change no longer adds a site Caddy would keep ordering for
no public IP found on a setup rerun              -> serving node left as it was; --announce refused
Caddy may not bind its port, e.g. after a bump   -> daemon warns with the fix for the current binary
Caddy download stalled at daemon start           -> kubo watchdog and GC scheduler no longer wait for it
stop during a certificate wait or download       -> shutdown no longer waits; old Caddyfile restored
stop during the first start                      -> no timers or router forwards set up afterwards
ufw blanket, list and range rules                -> read correctly; ALLOW OUT no longer counts as open

Live evidence through this code: on a real server with a public IPv4, reachability setup got a staging and then a trusted production Let's Encrypt IP certificate. From another network, the WebSocket upgrade returned 101 with the certificate verified and a libp2p handshake matched the node's peer ID. Real Chromium, with default certificate checks, completed libp2p handshakes over WSS and over WebTransport on UDP 443. Details are on #198.

Live evidence, by hand, not through this code: real staging and production issuance for a bare IP, with the same Caddy version and settings, is recorded on #198. A js-libp2p dial using this PR's dial code then reached that terminator from another network.

Not proven yet:

Known issues

Where this differs from #198

  • Two certificates, not one. Caddy obtains one per identifier, so IPv4 and IPv6 get separate ones. Browsers can't tell.
  • NAT-PMP is not implemented, only UPnP. pmpNat needs the router's address. libp2p's upnp-nat is also UPnP only.
  • kubo needs UDP 443 permission too. setcap on Caddy doesn't help it. kubo starts normally, logs nothing and just doesn't listen, so setup checks swarm/addrs/listen and prints the fix.
  • Config fields beyond the issue: kuboEdits, acmeDirectory, caddyAdminPort, domainForced, externalAnnounce, droppedAnnounce.

Caddyfile choices that came from running it

protocols h1 h2                 default HTTP/3 would take UDP 443 from kubo
auto_https disable_redirects    otherwise Caddy binds port 80 and fails if anything holds it
default_sni <ip>                browsers send no SNI for an IP, and behind NAT the local address isn't the public IP
explicit issuer acme { dir }    Let's Encrypt only, no implicit fallback CA

Setup refuses the production Let's Encrypt directory when CI is set.

Merge Danger

Door: one-way, once released

config.json v1 becomes a format later versions must read. Everything else can be reverted, and disable restores the kubo fields.

Blast Radius: daemon-startup

  • Every daemon loads the runtime at start and may print one extra line. A runtime failure logs and never stops the daemon. It is skipped for an external kubo.
  • An enabled node gains a Caddy child process, and the daemon restarts kubo on an IP change.
  • Five libp2p packages and @achingbrain/nat-port-mapper become direct dependencies. The libp2p ones are already installed through pkc-js at the same versions.

Summary by CodeRabbit

  • New Features
    • Added browser reachability setup, status, enable, and disable commands, including options for domains, announcements, and certificate staging.
    • Setup can configure secure browser connections and obtain certificates; the daemon monitors reachability and maintains configured connections.
    • Status displays reachability requirements, addresses, certificates, and potential issues. Disable can optionally remove saved reachability data.
  • Documentation
    • Added command guidance, setup prerequisites, troubleshooting tips, and detailed reachability documentation.

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.
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.
Discovers public addresses from interfaces, kubo and the router, obtains an IP
certificate, applies the kubo config and restarts kubo. It checks what kubo really
listens on, because kubo stays silent when it cannot bind UDP 443.
--domain gets a normal certificate when 443 is free, or prints a proxy snippet for
the detected server when it is busy. --announce is added only after a libp2p
handshake through it succeeds. A name that does not resolve here is refused unless
--force is passed.
The daemon spawns Caddy and keeps it up, re-derives public IPs and verifies announced
names every 5 minutes, and moves the certificate and announcement on an IP change. A
stale name warns hourly and is dropped after 24 hours. Without a configuration it
prints one line naming the setup command.
enable repairs from stored choices without asking. disable restores the kubo fields
and keeps state; --purge moves it to a timestamped backup.

Also: announced addresses no longer confirm an old IP, a dead Caddy no longer holds
the CLI open, a domain typed at the prompt is checked like a flag, and mode keeps a
proxy alongside a domain.
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

Adds browser reachability setup, status, enable, and disable commands. The commands configure Kubo and Caddy for WebSocket Secure and WebTransport. The daemon maintains configured Caddy sites, certificates, addresses, and router leases. The change also adds reachability documentation and unit and integration tests.

Changes: Browser Reachability

Layer / File(s) Summary
Kubo paths and reachability state
src/util.ts, src/ipfs/startIpfs.ts, src/reachability/state.ts, src/reachability/kubo-config.ts, test/kubo/*, test/reachability/state.test.ts, test/reachability/kubo-config.test.ts
Adds shared Kubo path and API helpers, validated reachability state, certificate storage, and reversible Kubo configuration edits.
Address discovery and reachability checks
src/reachability/discovery.ts, src/reachability/checks.ts, src/reachability/guidance.ts, src/cli/commands/reachability/status.ts, test/reachability/discovery.test.ts, test/reachability/checks.test.ts, test/cli/reachability-status.test.ts
Adds public-address discovery, port and firewall checks, setup guidance, and status checks for Kubo listeners and announcements.
Setup, certificates, and CLI commands
src/reachability/setup.ts, src/reachability/caddy.ts, src/reachability/nat.ts, src/reachability/libp2p-dial.ts, src/reachability/cli-support.ts, src/cli/commands/reachability/{setup,enable}.ts, package.json, test/reachability/*, test/cli/reachability-setup.integration.test.ts, test/cli/reachability-existing-caddy.integration.test.ts, test/helpers/pebble.ts
Adds setup orchestration, Caddy certificate issuance, router port mapping, announcement handshake verification, and setup and enable commands.
Daemon maintenance and lifecycle
src/reachability/runtime.ts, src/reachability/lifecycle.ts, src/cli/commands/daemon.ts, src/cli/commands/reachability/disable.ts, test/reachability/runtime.test.ts, test/cli/reachability-daemon.integration.test.ts
Adds scheduled Caddy and address maintenance, certificate and stale-name checks, runtime shutdown, and disable or purge behavior.
Documentation and command references
README.md, docs/reachability.md, docs/README.md, AGENTS.md
Documents reachability commands, setup options, state handling, daemon behavior, troubleshooting, and maintainer guidance.

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Feature · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant Setup as runReachabilitySetup
  participant Discovery as discoverPublicIps
  participant Caddy
  participant Kubo
  participant Dial as dialWithLibp2p
  Operator->>Setup: Run reachability setup
  Setup->>Discovery: Discover public addresses
  Setup->>Caddy: Obtain certificates and serve configured names
  Setup->>Kubo: Apply configuration and verify listeners
  Setup->>Dial: Verify announce address
  Dial->>Kubo: Complete libp2p handshake
Loading

Possibly related issues

Possibly related PRs

Merge Risk: Low · up to 202e8

Before merging, confirm that Kubo client URLs use connectable hosts and that disabling reachability preserves operator-added configuration entries.

Pre-merge checks: Passed 3 · Failed 2

Failed Failed checks: 2 warnings

Check name Status Explanation Resolution
Linked Issues check Warning The PR satisfies the reported coding requirements for [#209] and [#216]. It preserves an existing HTTPS server, limits no-WSS setup to WebTransport changes, gates --announce on a libp2p handshake, r… Implement NAT-PMP discovery, external-address lookup, TCP and UDP port mapping, lease refresh, and release for [#198]. Add automated tests for NAT-PMP success, refusal, refresh, and cleanup.
Docstring Coverage Warning Docstring coverage is 40.28% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 3 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title "feat(reachability): make kubo dialable from browsers" matches the main change. The PR adds reachability setup, enable, disable, and status commands, plus daemon runtime support that keeps c…
Out of Scope Changes check Passed The changes remain connected to [#198], [#209], and [#216]. The CLI commands, daemon runtime, Kubo helpers, Caddy support, NAT handling, status checks, guidance, documentation, dependencies, and tests…
Full details: Title check

Explanation

The title "feat(reachability): make kubo dialable from browsers" matches the main change. The PR adds reachability setup, enable, disable, and status commands, plus daemon runtime support that keeps configured browser-reachable addresses available. The title names the primary feature, uses the conventional commit prefix, and avoids file lists or vague wording.

Full details: Out of Scope Changes check

Explanation

The changes remain connected to [#198], [#209], and [#216]. The CLI commands, daemon runtime, Kubo helpers, Caddy support, NAT handling, status checks, guidance, documentation, dependencies, and tests support reachability setup, maintenance, verification, or announcement checks. No demonstrated unrelated product change appears in the reviewed scope.

Full details: Linked Issues check

Explanation

The PR satisfies the reported coding requirements for [#209] and [#216]. It preserves an existing HTTPS server, limits no-WSS setup to WebTransport changes, gates --announce on a libp2p handshake, returns exit code 2 when input is required, and checks both Kubo configuration and live /api/v0/id announcements. The PR does not satisfy the NAT-PMP requirement in [#198]. src/reachability/nat.ts uses @achingbrain/nat-port-mapper for UPnP discovery and mapping only. The PR description confirms that NAT-PMP is not implemented.

Resolution

Implement NAT-PMP discovery, external-address lookup, TCP and UDP port mapping, lease refresh, and release for [#198]. Add automated tests for NAT-PMP success, refusal, refresh, and cleanup.

Full details: Docstring Coverage

Explanation

Docstring coverage is 40.28% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 72 functions across 34 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/cli/commands/daemon.ts

Oops! Something went wrong! :(

ESLint: 8.27.0

Error: ESLint configuration in --config » eslint-config-oclif is invalid:

  • Unexpected top-level property "__esModule".

Referenced from: /.eslintrc
at ConfigValidator.validateConfigSchema (/.eslint-tmp/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2156:19)
at ConfigArrayFactory._normalizeConfigData (/.eslint-tmp/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2998:19)
at ConfigArrayFactory._loadConfigData (/.eslint-tmp/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2963:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/.eslint-tmp/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3264:21)
at ConfigArrayFactory._loadExtends (/.eslint-tmp/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3135:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/.eslint-tmp/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3074:25)
at _normalizeObjectConfigDataBody.next ()
at ConfigArrayFactory._normalizeObjectConfigData (/.eslint-tmp/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:20)
at _normalizeObjectConfigData.next ()
at ConfigArrayFactory.loadFile (/.eslint-tmp/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2829:16)

src/reachability/caddy.ts

ESLint skipped: the matched ESLint configuration already failed (config-incompatibility).

src/reachability/checks.ts

ESLint skipped: the matched ESLint configuration already failed (config-incompatibility).

  • 7 others

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

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
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: 68284e14-f10b-4e82-9c24-ce42d50dc7ce
Commits

Reviewing files that changed from the base of the PR and between 8db1bbc and 202e809.

Files selected for processing: 11
  • docs/reachability.md
  • src/cli/commands/daemon.ts
  • src/reachability/caddy.ts
  • src/reachability/checks.ts
  • src/reachability/runtime.ts
  • src/reachability/setup.ts
  • test/cli/reachability-daemon.integration.test.ts
  • test/reachability/caddy.test.ts
  • test/reachability/checks.test.ts
  • test/reachability/runtime.test.ts
  • test/reachability/setup.test.ts
Files skipped from review as they are similar to previous changes: 1
  • docs/reachability.md

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@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:42:49.420332Z ec82dea 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.

Comment thread src/reachability/runtime.ts Resolved
Comment thread src/reachability/runtime.ts Resolved
Comment thread src/reachability/state.ts Resolved
Comment thread src/reachability/runtime.ts Resolved
Comment thread src/reachability/runtime.ts Resolved
Comment thread src/reachability/runtime.ts Resolved
Comment thread src/reachability/setup.ts Resolved
Comment thread src/reachability/runtime.ts Resolved

@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: ec82dea084

ℹ️ 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".

Comment thread src/cli/commands/daemon.ts Resolved
Comment thread src/reachability/setup.ts Resolved
Checks permission for Caddy and kubo to bind port 443, including UDP 443 where kubo
otherwise silently does not listen, what holds TCP 80, TCP 443 and UDP 443, active
ufw and firewalld rules, and what kubo really listens on. Each result names its fix.
status took "Announced addresses" from reachability's own state, so it
looked healthy after an address was removed from kubo's config, or while
kubo ran from an older copy of it. A new kubo-announce check compares that
state with kubo's config file and with running kubo's /id.

enable could not repair the second case, because it restarted kubo only
when the file changed. setup and enable now also restart kubo when it is
not announcing the addresses, and warn if a restart does not help, as when
Addresses.NoAnnounce hides one.

The integration tests stand in 127.0.0.1 for a public address, which a repo
created by the daemon hides through NoAnnounce, so they now clear that entry.

@coderabbitai coderabbitai 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.

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread docs/reachability.md Resolved
Comment thread docs/reachability.md Resolved
Comment thread docs/reachability.md Resolved
Comment thread src/reachability/checks.ts Resolved
A host with a global IPv6 behind a router's firewall could never get a
certificate for it, yet the address looked new on every check. The daemon
asked the CA again about every 10 minutes, forever. It now waits per
address family, from 1 hour doubling up to 24, and no longer reports a
move or rewrites kubo's config when nothing moved.

- status: skip the kubo-ws check on a node setup left without WSS, where
  the listener is absent on purpose and enable could not add it.
- runtime: take what is dropped from the config. setup can announce an
  address again without touching the status file, which left a broken
  name announced forever, and a lost status file stopped a recovered name
  being restored.
- runtime: stopping an adopted Caddy no longer hides the next crash's
  warning, since an adopted Caddy never reports an exit.
…tificate

A rerun that could not issue any certificate, say on an IP change or a
move to another CA, wiped the Caddyfile sites and announced addresses and
set serveWss to false, turning a working node into WebTransport-only. It
now leaves such a node exactly as it was, and refuses --announce.

- checks: the Nginx HTTP and Apache ufw profiles open only port 80, so
  they no longer count as allowing TCP 443.
- kubo-config: undoing our edits removes one copy of each entry, so an
  identical entry the operator added while enabled survives disable.
- docs: reachability sets up two of the ways a browser can dial a node,
  not the only two.
Comment thread src/reachability/setup.ts Resolved
Comment thread src/reachability/runtime.ts Resolved
On Windows CI the test's edit to Addresses.NoAnnounce was gone by the time
kubo was checked. pkc-js sets kubo's Routing config in the background right
after the daemon starts, which rewrites the same file, so the helper now
repeats the edit until running kubo has it, and logs any retries.

Commands run by this test now time out with their output, instead of leaving
only the test's own timeout to report a hang.
Comment thread src/reachability/runtime.ts Resolved
Comment thread src/reachability/caddy.ts Resolved
…errors

Stale domain: a setup rerun removed the Caddy site of a stored domain whose
DNS no longer pointed here, and did not record a shorter outage as dropped.
When DNS recovered, Caddy failed the TLS handshake for the announced name, or
the daemon never announced the name again. The site is now kept and the address
moves to droppedAnnounce.

Certificate retries: when no certificate could be issued for a moved address,
the daemon ordered again every other check, which is 6 attempts an hour against
Let's Encrypt's limit of 5 failed validations. It now backs off. The stored old
address no longer ends the wait, since only a newly held address proves that
a certificate was issued.

Proxy names: an IP change added a site for any domain with a matching proxy
address, so Caddy kept ordering a certificate for a name that points elsewhere.
An IP change now keeps the domain sites setup chose.

Bind errors: each Caddy version is a new file without the setcap capability,
which nothing here can grant. The daemon now prints the fix for the current
binary when Caddy may not bind its port.
Comment thread src/cli/commands/daemon.ts Resolved

@coderabbitai coderabbitai 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.

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread src/reachability/checks.ts Resolved
Comment thread src/reachability/runtime.ts Resolved
…hdog

No public IP: a setup rerun that found no public address emptied the stored
addresses and the Caddyfile of a node serving WSS. The daemon then stopped
looking at IPs, so WSS stayed off until setup ran again. A router not answering
says nothing about the address, so this now leaves the node as it was, and
refuses --announce, the same as a rerun that gets no certificate.

Kubo watchdog: the daemon waited for its first Caddy start before setting up the
kubo watchdog and the repo GC scheduler, and that start can spend minutes
downloading Caddy. If kubo's restart failed during the download, nothing retried
it. Reachability now starts after both.
Shutdown: stopping the daemon waited for a certificate wait of up to 90 s, or a
stalled Caddy download up to the 120 s shutdown limit. Both now end when the
runtime stops. A stop during an IP change also restores the old Caddyfile, so
the next start does not serve an address the config does not hold yet, and it
is not counted as a failed issuance.

ufw: a blanket Anywhere rule counted as allowing TCP 443 but not UDP 443, so
status and setup warned about a port that was open.
Comment thread src/reachability/setup.ts Resolved
…domain

A setup run with a new --domain kept the old domain's address in
droppedAnnounce. If that name later pointed here again, the daemon announced it
on DNS alone, with no Caddy site behind it, so browser dials failed the TLS
handshake. Setup now keeps only dropped addresses of the current domain or of a
proxy.
Comment thread src/reachability/runtime.ts Resolved
Comment thread src/reachability/checks.ts Resolved
Router forwards: a stop during the first Caddy download found nothing to clean
up, then start() carried on, set its timers and asked the router for forwards
that outlived the release in stop(). Both start() and refreshLeases() now check
for a stop first.

ufw: rules such as 80,443/tcp and 443:444/udp were not read as including 443, so
status and setup warned about a port that was open. Outgoing rules, which print
as ALLOW OUT, were counted as opening the port, and no longer are.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant