[PR #7047] [CLOSED] [management] agent network private proxies #30116

Closed
opened 2026-08-05 08:10:11 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/7047
Author: @bison
Created: 8/3/2026
Status: Closed

Base: mainHead: feat/agent-network-zone


📝 Commits (8)

  • b2d7253 feat(agentnetwork): adjective-noun subdomain label generation
  • df3619e feat(agentnetwork): add a placement-free Zone to settings
  • fabface feat(store): globally unique subdomains and an insert that surfaces conflicts
  • 6203528 feat(agentnetwork): thread the zone config through to the manager
  • 29ad3fa feat(agentnetwork): allocate subdomains transactionally, retrying on conflict
  • 58d0793 perf(agentnetwork): resolve endpoints by indexed subdomain lookup
  • 91dd9fa feat(dns): derive the mesh DNS apex for zone-based endpoints
  • e493efd chore(agentnetwork): fix config grouping, dead code, comments, coverage

📊 Changes

29 files changed (+993 additions, -181 deletions)

View changed files

📝 combined/cmd/config.go (+2 -0)
📝 combined/config.yaml.example (+8 -0)
📝 infrastructure_files/management.json.tmpl (+3 -0)
management/internals/modules/agentnetwork/allocate_test.go (+296 -0)
management/internals/modules/agentnetwork/domainlookup_test.go (+120 -0)
📝 management/internals/modules/agentnetwork/handlers/handlers_test.go (+1 -1)
management/internals/modules/agentnetwork/labelgen/adjectives.go (+39 -0)
📝 management/internals/modules/agentnetwork/labelgen/labelgen.go (+14 -32)
📝 management/internals/modules/agentnetwork/labelgen/labelgen_test.go (+79 -72)
📝 management/internals/modules/agentnetwork/labelgen/words.go (+1 -1)
📝 management/internals/modules/agentnetwork/manager.go (+84 -33)
📝 management/internals/modules/agentnetwork/provider_bootstrap_test.go (+1 -1)
📝 management/internals/modules/agentnetwork/synthesizer.go (+35 -33)
📝 management/internals/modules/agentnetwork/types/settings.go (+18 -2)
management/internals/modules/agentnetwork/types/settings_test.go (+31 -0)
📝 management/internals/modules/reverseproxy/service/service.go (+8 -0)
📝 management/internals/modules/reverseproxy/service/service_test.go (+11 -0)
📝 management/internals/server/config/config.go (+9 -0)
📝 management/internals/server/modules.go (+1 -0)
📝 management/server/agentnetwork_budgetrule_realstack_test.go (+2 -2)

...and 9 more files

📄 Description

Describe your changes

Agent Network endpoints are currently <subdomain>.<cluster>, where the cluster half is the address of the proxy serving the account. That couples a tenant's hostname to placement, so it cannot change which proxy serves them without changing their address.

This adds an optional parent DNS zone. With one configured, new endpoints become <subdomain>.<zone> and both DNS directions resolve it:

  • forward — the mesh A record's zone apex is derived from the account's zone
  • reverse — hostname → account resolution is now a single indexed lookup on the first DNS label, replacing a prefilter that assumed the parent was a proxy address (it also removes a per-request table scan on the auth path)

Subdomain labels move from single words to adjective-noun pairs (brave-otter), and allocation becomes transactional: it inserts inside a transaction and retries on a unique-constraint rejection, replacing a read-then-write over a pre-computed "taken" set. That set was per-cluster, its read and write were not atomic, and its exhaustion fallback appended four characters of the account ID with no retry and no uniqueness check — and those four characters are constant for accounts created within roughly the same hour, so two such accounts could be handed the same label.

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)
  • I ran and tested this change locally — I did not rely on CI to find out whether it works
  • This PR has a single purpose (not a fix + refactor + feature in one)
  • This change is a trivial fix, OR it links an issue the NetBird team agreed on beforehand. Changes to the public API, gRPC protocols, functionality behavior, CLI / service flags, or new features always need that agreement first. See CONTRIBUTING.md.

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

This is not yet changing any default behavior. It's new plumbing to allow for different deployment models in the future.

Docs PR URL (required if "docs added" is checked)

N/A


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/7047 **Author:** [@bison](https://github.com/bison) **Created:** 8/3/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `feat/agent-network-zone` --- ### 📝 Commits (8) - [`b2d7253`](https://github.com/netbirdio/netbird/commit/b2d72534c5773ae9930ea590d3468164442f31cf) feat(agentnetwork): adjective-noun subdomain label generation - [`df3619e`](https://github.com/netbirdio/netbird/commit/df3619e1e53529d021e45f9838465655d47b905e) feat(agentnetwork): add a placement-free Zone to settings - [`fabface`](https://github.com/netbirdio/netbird/commit/fabfacee5559bf8dd13517e8af0bd8eadcb557f5) feat(store): globally unique subdomains and an insert that surfaces conflicts - [`6203528`](https://github.com/netbirdio/netbird/commit/6203528f3ab1654c8b1547c7901f3eca3eb299f7) feat(agentnetwork): thread the zone config through to the manager - [`29ad3fa`](https://github.com/netbirdio/netbird/commit/29ad3fad43b95501a69ce54b5934dcf3c93f37db) feat(agentnetwork): allocate subdomains transactionally, retrying on conflict - [`58d0793`](https://github.com/netbirdio/netbird/commit/58d07938708d940069b131a1a4554da2e85f3948) perf(agentnetwork): resolve endpoints by indexed subdomain lookup - [`91dd9fa`](https://github.com/netbirdio/netbird/commit/91dd9fa2392fdf7dd23780da3dabe8d8ca99b99f) feat(dns): derive the mesh DNS apex for zone-based endpoints - [`e493efd`](https://github.com/netbirdio/netbird/commit/e493efd5329e1f196bd474f990ef9affc8f0a694) chore(agentnetwork): fix config grouping, dead code, comments, coverage ### 📊 Changes **29 files changed** (+993 additions, -181 deletions) <details> <summary>View changed files</summary> 📝 `combined/cmd/config.go` (+2 -0) 📝 `combined/config.yaml.example` (+8 -0) 📝 `infrastructure_files/management.json.tmpl` (+3 -0) ➕ `management/internals/modules/agentnetwork/allocate_test.go` (+296 -0) ➕ `management/internals/modules/agentnetwork/domainlookup_test.go` (+120 -0) 📝 `management/internals/modules/agentnetwork/handlers/handlers_test.go` (+1 -1) ➕ `management/internals/modules/agentnetwork/labelgen/adjectives.go` (+39 -0) 📝 `management/internals/modules/agentnetwork/labelgen/labelgen.go` (+14 -32) 📝 `management/internals/modules/agentnetwork/labelgen/labelgen_test.go` (+79 -72) 📝 `management/internals/modules/agentnetwork/labelgen/words.go` (+1 -1) 📝 `management/internals/modules/agentnetwork/manager.go` (+84 -33) 📝 `management/internals/modules/agentnetwork/provider_bootstrap_test.go` (+1 -1) 📝 `management/internals/modules/agentnetwork/synthesizer.go` (+35 -33) 📝 `management/internals/modules/agentnetwork/types/settings.go` (+18 -2) ➕ `management/internals/modules/agentnetwork/types/settings_test.go` (+31 -0) 📝 `management/internals/modules/reverseproxy/service/service.go` (+8 -0) 📝 `management/internals/modules/reverseproxy/service/service_test.go` (+11 -0) 📝 `management/internals/server/config/config.go` (+9 -0) 📝 `management/internals/server/modules.go` (+1 -0) 📝 `management/server/agentnetwork_budgetrule_realstack_test.go` (+2 -2) _...and 9 more files_ </details> ### 📄 Description ## Describe your changes Agent Network endpoints are currently `<subdomain>.<cluster>`, where the cluster half is the address of the proxy serving the account. That couples a tenant's hostname to placement, so it cannot change which proxy serves them without changing their address. This adds an optional parent DNS zone. With one configured, new endpoints become `<subdomain>.<zone>` and both DNS directions resolve it: - forward — the mesh A record's zone apex is derived from the account's zone - reverse — hostname → account resolution is now a single indexed lookup on the first DNS label, replacing a prefilter that assumed the parent was a proxy address (it also removes a per-request table scan on the auth path) Subdomain labels move from single words to adjective-noun pairs (brave-otter), and allocation becomes transactional: it inserts inside a transaction and retries on a unique-constraint rejection, replacing a read-then-write over a pre-computed "taken" set. That set was per-cluster, its read and write were not atomic, and its exhaustion fallback appended four characters of the account ID with no retry and no uniqueness check — and those four characters are constant for accounts created within roughly the same hour, so two such accounts could be handed the same label. ## Issue ticket number and link <!-- Required for anything that changes behavior. Link the issue (or the validated discussion it came from) that the NetBird team already agreed on. See https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#ticket-first-pr-second --> ## Stack <!-- branch-stack --> ### Checklist - [ ] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [x] It is a refactor - [ ] Created tests that fail without the change (if possible) - [ ] I ran and tested this change locally — I did not rely on CI to find out whether it works - [ ] This PR has a single purpose (not a fix + refactor + feature in one) - [ ] This change is a trivial fix, **OR** it links an issue the NetBird team agreed on beforehand. Changes to the public API, gRPC protocols, functionality behavior, CLI / service flags, or new features always need that agreement first. See [CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#ticket-first-pr-second). > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [ ] I added/updated documentation for this change - [x] Documentation is **not needed** for this change (explain why) This is not yet changing any default behavior. It's new plumbing to allow for different deployment models in the future. ### Docs PR URL (required if "docs added" is checked) N/A --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 08:10:11 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#30116