Skip to content

Update docs for the next release - #390

Open
JackDoan wants to merge 32 commits into
mainfrom
release-docs
Open

JackDoan wants to merge 32 commits into
mainfrom
release-docs

Conversation

@JackDoan

@JackDoan JackDoan commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Brings the docs up to date with nebula master (since v1.11.0) for the next release. Includes the offload and CPU pinning docs from #376 (plus fixes to them), so this supersedes #376.

New pages

  • config/local-api: the control socket and the info API
  • Guide: nebula ctl and the info HTTP API, including the caveat about trusting identity answers
  • Guide: FIPS 140-3 mode

Fixed wrong values

  • tun.tx_queue default is 5000, not 500
  • static_map.lookup_timeout default is 5s, not 250ms
  • pki.disconnect_invalid default is true, not false
  • pki.initiating_version default is 1 or 2 depending on the certs loaded, not 0
  • stats.protocol: only tcp, tcp4 or tcp6 work; udp never did
  • FreeBSD/OpenBSD/NetBSD tun.dev naming
  • logging.timestamp_format, which no longer exists, and the log levels
  • Stale lighthouse DNS TXT output, and old-format log samples
  • The ssh debug command list: profiling commands removed, identity added

Newly documented behavior

  • Offloads and CPU pinning (from Document offload and CPU pinning config #376)
  • IPv6 non-TCP/UDP/ICMP traffic only matches proto: any
  • Firewall group value rules and conntrack timeouts
  • An IPv4 listen.host means Nebula ignores IPv6 underlay addresses
  • The 8937 MTU cap
  • Route entry fields, and macOS unsafe_route ownership
  • Windows network_category and windows_bypass_wdf, and DNS registration being off
  • UDP buffer fallback without CAP_NET_ADMIN
  • handshakes.query_buffer
  • Newer metrics
  • Automatic rekeying
  • When a reload restarts sshd
  • Relay reload behavior
  • Static map lookup failures keeping the last good addresses
  • Reloadable / not reloadable labels across most config pages

Notes for review

  • "Added in v1.12.0" labels assume that's the next version.
  • relay.am_relay now says a relay does not check the target's relay.relays. That matches the code, but the old text promised otherwise.
  • Sidebar positions were renumbered to fit the new pages.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for docs-nebula ready!

Name Link
🔨 Latest commit a99e214
🔍 Latest deploy log https://github.com/DefinedNet/nebula-docs/actions/runs/40734053378
😎 Deploy Preview Url https://6576e8e1.docs-nebula.pages.dev
😎 Deploy Preview Alias https://release-docs.docs-nebula.pages.dev

Comment thread docs/config/firewall.mdx Outdated
Quote group names. YAML converts unquoted values before Nebula sees them, so `group: 007` would be read as `7` and
`group: 1.10` as `1.1`. Unquoted integers and booleans still work, but log a warning. A float, a date, a map, a nested
list, a `null` entry in `groups`, or `group: []` is rejected with an error, which fails startup or fails the reload and
keeps the previous firewall. A `group` or `groups` key with no value is treated as not set.

@nbrownus nbrownus Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A group or groups key with no value is treated as not set. - this is now rejected unless a host, other group or cidr is set

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BEEP BOOP ROBOT REPLY: Fixed in 216b1a5. Now says a group or groups key with no value is rejected unless the rule also sets host, cidr, or a non-empty group/groups (matching the #2017 check in convertRule), and points at host: any.


Every reload ends with one summary line in the log:

| Log line | Level | Meaning |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing: "Config reload failed, the new config did not load and a restart is still required".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BEEP BOOP ROBOT REPLY: Added in 216b1a5 (config/reload.go:26): "Nothing was applied, and an earlier reload still needs a restart".


| Platform | Settings |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| All | `cipher`, `routines`, `listen.host`, `listen.port`, `lighthouse.am_lighthouse`, `handshakes.*`, `stats.message_metrics`, `stats.lighthouse_metrics`, `tun.disabled`, `tun.drop_local_broadcast`, `tun.drop_multicast`, `firewall.conntrack.routine_cache_timeout`, `timers.*` |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

timers.requery_wait_duration is reloadable, I wonder if we want this guide at all since each config stanza has it's own "reloadable" pill?

@JackDoan JackDoan Oct 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BEEP BOOP ROBOT REPLY: Jack says drop it, so the guide is gone in f7e2d46 and the two links to it are removed.

Comment thread docs/config/logging.mdx Outdated

<Pill className="mb-24">Reloadable</Pill>
Timestamps are always [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339) with nanosecond precision, e.g.
`2006-01-02T15:04:05.999999999Z07:00`. The `logging.timestamp_format` setting was removed in v1.11.0 and is ignored.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Technically the precision depends on text (milliseconds) or json (nanoseconds) mode

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Actually one of my robots told me yesterday we no longer respect this setting post slog migration? Need to check.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Correct but the precision still changes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ohhhh I see what you mean

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BEEP BOOP ROBOT REPLY: Fixed in 216b1a5: text is millisecond (slog's appendRFC3339Millis), json is RFC3339Nano with trailing zeros trimmed. Re the setting: logging.disable_timestamp is still honored post-slog, logging.Handler.Handle zeroes r.Time and slog omits a zero time.

Comment thread docs/config/firewall.mdx Outdated
match a `tcp` or `udp` rule. These packets are now classified as their real protocol. If you carry such a protocol over
IPv6 in the overlay, make sure a `proto: any` rule allows it.

IPv6 packets whose extension headers are truncated or more than 8 headers deep are dropped.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"8 or more"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BEEP BOOP ROBOT REPLY: Right, IPv6FindUpperProtocol walks at most 8 headers and fails closed if the 8th is still an extension header, so 8 or more is dropped. Fixed in 216b1a5. (The function's doc comment in iputil/packet.go has the same off-by-one.)

@JackDoan
JackDoan marked this pull request as ready for review October 28, 2026 15:18
@@ -0,0 +1,72 @@
---
title: FIPS 140-3 mode

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could be helpful to note encrypting keys at rest will be rejected in FIPS mode

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm trying to decide if we should add an AES mode for that, or lean on "if you need fips, you ought to have your CA key somewhere hardware-backed"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can certainly improve the encryption at rest story for FIPs folks but it's not gonna make v1.12 unless there is a strong desire for it. Easier to call the gap out or hold this guide until then.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BEEP BOOP ROBOT REPLY: Added in 216b1a5. Verified with a GOFIPS140=v1.0.0 -tags fips140enforce build of master: nebula-cert ca -encrypt fails, and nebula-cert sign can't use a CA key encrypted by a non-FIPS build, both on cipher.NewGCM being refused in FIPS 140-only mode.

JackDoan and others added 21 commits October 28, 2026 10:32
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r fallback and reloadability, and listen.windows_bypass_wdf

@jasikpark jasikpark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Checked the added and changed claims against nebula master (2f5232e2). About 200 hold up, including relay.am_relay: the relay never reads the target's relay.relays. The site builds with no broken links or anchors, and prettier is clean. These don't line up with the code:

Wrong

  • reloading-configuration:46: "Changing a setting back to the value Nebula is running with does not need a restart." RestartRequiredIfChanged compares against the previously loaded config, not running state (config/reload.go), and needsRestart is sticky (config/config.go:230), which the sentence before already says. Only cipher, Windows tun.network_category, and the conditional tun.dev compare against running values.
  • lighthouse.mdx:67,85 / using-lighthouse-dns:77: the TXT answer isn't JSON as nebula-cert print -json prints it. dns.NewRR(fmt.Sprintf("%s TXT %s", …, crt.MarshalJSON())) doesn't quote the JSON, so miekg/dns splits it into character-strings and strips the quotes; dig shows "{" "details" ":{" …. That's a nebula bug, but the doc shouldn't promise JSON until it's fixed. (print -json also wraps in an array; TXT returns one object.)
  • tunnels.mdx:38: messages.tx.exhausted only exists with stats.message_metrics: true (nil in newMessageMetricsOnlyRecvError). stats.mdx says so; tunnels.mdx should too.
  • tun.mdx:198: tun.windows_bypass_wdf is amd64/arm64 only (tun_bypass_windows_386.go is a no-op), like listen.windows_bypass_wdf already says.

Narrower than written

  • tun.mdx:134: duplicate unsafe_routes: the warning is "only the last entry's via is used", which covers the route tree only. macOS installs the first entry's system route; on Linux, duplicates with different metrics both stay in the kernel.
  • reloading-configuration:78 / pki.mdx:52: a cert with different networks is refused only for a version already loaded (or when removing v2). Adding a new version with different networks is accepted, then asks for a restart (pki.go:111-118).
  • lighthouse.mdx:68: other TXT queries get an empty NOERROR answer, not "no answer".
  • pki.mdx:127: blocklisted handshakes log at debug on the responder side, at warn on the initiator side when the handshake fails.
  • debug-ssh-commands:106: print-cert also prints JSON with no flag, and its -raw isn't documented.
  • local-control-and-info-api:106: real ?pretty output is 4-space MarshalIndent with one array element per line.

Structure

  • +1 to Nate on the restart table in the reloading guide. It already drifted (timers.*), and it duplicates the per-key labels. Relatedly, "Reloadable" is a pill but not-reloadable is prose in about a dozen phrasings ("Not reloadable.", "is not reloadable, changing it takes effect after a restart", …). A Restart required pill would make the config pages the single source, and the guide could link there instead of listing keys.

Unconfirmed

  • "Added in v1.12.0" labels: everything is still under [Unreleased]; fine once nebula#2027 (v1.12.0 changelog) lands as 1.12.0.

— Caleb + Cache

Comment thread docs/config/lighthouse.mdx Outdated
`TXT` records can only be queried over the Nebula network, and contain certificate information for the requested host IP
address.
`TXT` records can only be queried from hosts on the Nebula network or from the lighthouse itself, and contain the
certificate of the requested host IP address as JSON. Other `TXT` queries get no answer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

TXT records don't parse as JSON today and they are only served locally from a lighthouse, maybe redirecting them to the local api socket would be valuable. This also applied to the using-lighthouse-dns guide.

@jasikpark jasikpark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-checked at dbf8049 against nebula v1.12.0 (fb4ef139). Dropping the reloading guide and the not-reloadable prose resolves the structure point: the pill is now the single source, and the pill audit is consistent. The trims also cleared the duplicate-unsafe_routes, TXT "no answer", and blocklist log-level items. v1.12.0 is tagged, so the "Added in" labels hold.

Blocking

  • Check prettier has been red since fc1b33b: docs/config/static-host-map.mdx lost its trailing newline.

Still open from last round

  • lighthouse.mdx:67,84 / using-lighthouse-dns:77: TXT answers still aren't JSON (dns_server.go:416 builds the RR from unquoted MarshalJSON()). +1 to Nate: drop the JSON promise, or point at the info API, which serves the same identity as real JSON.
  • tunnels.mdx:40: messages.tx.exhausted is only registered with stats.message_metrics: true. stats.mdx:78 says so, tunnels.mdx doesn't.
  • tun.mdx:181: tun.windows_bypass_wdf is amd64/arm64 only (overlay/tun_bypass_windows_386.go), the same as listen.windows_bypass_wdf says.
  • local-control-and-info-api:103: the ?pretty sample is 2-space with inline arrays. Real output is 4-space MarshalIndent (info_api.go:146), with one array element per line.

From the trim

  • local-api.mdx:87: "On Windows, a change to group takes effect after a restart" leaves out the part that bites. A reload that removes or narrows the group stops the socket until restart (localapi/endpoint.go:66), so nebula ctl goes away mid-reload. The earlier text said this.
  • local-control-and-info-api (the info API caveat): "only answers for established tunnels and addresses inside this node's own overlay networks" reads as two things it answers for. Suggest "only answers for addresses inside this node's own overlay networks that have an established tunnel".
  • firewall.mdx tip, nit: "decimal integers" → "integers". groupName sees an int whatever the YAML spelling, so 0x1F is accepted as 31 too.

— Caleb + Cache

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.

3 participants