docs: add Networks site-to-site use-case guide (#773)

* docs: add Networks site-to-site use-case guide

Add a canonical site-to-site guide built on Networks/Resources/Policies,
which is the recommended and actively developed approach. Reposition the
legacy Network Routes site-to-site Note to point at the new page and scope
Network Routes to the wide-open, no-policy case only. Add the new page to
the docs sidebar under Networks > Use Cases.

* docs: fix Resource fields, policy heading, and prerequisites in Networks site-to-site

- Remove non-existent 'Type: Subnet' field; describe Resource Groups under
  Additional Options to match the actual UI
- Rename Step 4 to 'Create access control policies'
- Trim prerequisites (drop account line and device examples)

* docs: clarify Masquerade requirement and Linux-only SNAT for site-to-site
This commit is contained in:
Jack Carter
2026-06-01 11:23:44 +02:00
committed by GitHub
parent 93e57b61f6
commit e49d920fb6
3 changed files with 149 additions and 5 deletions

View File

@@ -215,6 +215,10 @@ export const docsNavigation = [
title: 'Site-to-VPN',
href: '/manage/networks/use-cases/site-to-vpn',
},
{
title: 'Site-to-Site',
href: '/manage/networks/use-cases/site-to-site',
},
],
},
],
@@ -464,15 +468,15 @@ export const docsNavigation = [
links: [
{
title: 'Getting Started',
href: '/manage/integrations/kubernetes'
href: '/manage/integrations/kubernetes',
},
{
title: 'Routing Peer',
href: '/manage/integrations/kubernetes/routing-peer'
href: '/manage/integrations/kubernetes/routing-peer',
},
{
title: 'Client Sidecar',
href: '/manage/integrations/kubernetes/client-sidecar'
href: '/manage/integrations/kubernetes/client-sidecar',
},
{
title: 'Gateway API',
@@ -1051,4 +1055,4 @@ function NavigationGroup({ group, className, hasChildren }) {
</div>
</li>
)
}
}

View File

@@ -12,7 +12,9 @@ Site A device ──► Routing Peer ──► NetBird Tunnel ──► Routing
```
<Note>
For one-way access from a NetBird peer to clientless devices behind a routing peer (VPN-to-Site), prefer [Networks](/manage/networks) — it has per-resource access control and simpler setup. Network Routes is required when you need Site-to-Site, source-IP preservation (masquerade disabled), or ACL Groups.
For most site-to-site setups, prefer [Networks Site-to-Site](/manage/networks/use-cases/site-to-site) — it has per-Resource access control and is the actively developed system.
Network Routes is still the right choice when you need site-to-site without any Policy gating traffic — the legacy "wide open" mode with empty Access Control Groups. Networks requires at least one Policy per Resource and has no equivalent.
For the reverse — clientless devices at a site initiating connections to NetBird peers — see [Site-to-VPN](/manage/networks/use-cases/site-to-vpn).
</Note>

View File

@@ -0,0 +1,138 @@
import { Note } from '@/components/mdx'
# Site-to-Site
Site-to-Site connects two networks through routing peers at each end. Neither end-device needs NetBird installed — the routing peers forward traffic across the NetBird tunnel. This guide builds it with [Networks](/manage/networks), where each site is a Resource gated by its own Policy.
## Architecture
```
Site A device ──► Routing Peer ──► NetBird Tunnel ──► Routing Peer ──► Site B device
(no NetBird) (peer) (peer) (no NetBird)
```
<Note>
Networks is the recommended way to build site-to-site. It has per-Resource access control, is Zero Trust by default, and is the actively developed system.
Use [Network Routes](/manage/network-routes/use-cases/site-to-site) instead only when you need site-to-site without any Policy gating traffic — the legacy "wide open" mode with empty Access Control Groups. Networks requires at least one Policy per Resource and has no equivalent.
For the reverse — clientless devices at a site initiating connections to NetBird peers — see [Site-to-VPN](/manage/networks/use-cases/site-to-vpn).
</Note>
## Prerequisites
- An always-on device at each site to act as the routing peer
- Different subnets at each site. If both sites use the same range (e.g. `192.168.1.0/24`), see [Overlapping Routes](/manage/network-routes/overlapping-routes)
## Example
Two sites, A and B:
- Site A: `10.0.0.0/24`, routing peer group `site-a-routers`
- Site B: `10.1.0.0/24`, routing peer group `site-b-routers`
## Step 1: Create setup keys for each site
Create one setup key per site with an auto-assigned group for that site's routing peers.
1. Go to **Setup Keys** → **Create Setup Key**
2. For Site A: name "Site A Routing Peer", auto-assign group `site-a-routers`
3. Repeat for Site B with group `site-b-routers`
<Note>
You can also assign groups manually after the peer connects, under **Peers** → select peer → **Assigned Groups**.
</Note>
## Step 2: Install NetBird on the routing peers
On each site's routing peer:
```bash
curl -fsSL https://pkgs.netbird.io/install.sh | sh
sudo netbird up --setup-key YOUR_SETUP_KEY
```
## Step 3: Create a Network for each site
Each site becomes its own Network: a Resource for that site's subnet, served by that site's routing peers.
**Network A:**
1. Go to **Networks** → **Add Network**, name it `site-a`, and click **Create Network**
2. Inside the network, click **Add Resource**:
- Enter a name like `site-a-subnet`
- Enter the address `10.0.0.0/24` (a subnet, or a single host like `10.0.0.50/32`)
- Expand **Additional Options** and under **Resource Groups**, create a group called `site-a-cidr` (this group represents the subnet for use in policies)
3. Click **Add Routing Peer**, select the `site-a-routers` group, and leave **Masquerade** enabled (the default)
<Note>
Leave Masquerade enabled on both routing peers. NetBird's tunnel drops traffic whose source isn't the peer's NetBird IP, so Masquerade is what makes site-to-site work — disabling it on a routing peer breaks the flow. Masquerade is enabled by default everywhere, and the toggle to turn it off only exists on Linux.
NetBird only performs the required outbound SNAT itself on Linux routing peers. Other platforms (OPNsense and pfSense are common examples) don't do this SNAT unless you configure it manually, so use a Linux routing peer for site-to-site.
</Note>
**Network B:** repeat the steps — name `site-b`, Resource address `10.1.0.0/24` with group `site-b-cidr`, and routing peer group `site-b-routers`.
## Step 4: Create access control policies
Networks requires a Policy on every Resource — without one, the dashboard will not allow access to it. Add one Policy per Network:
- **Network A's Resource:** Source Groups = `site-b-routers` → destination = the `site-a-subnet` Resource
- **Network B's Resource:** Source Groups = `site-a-routers` → destination = the `site-b-subnet` Resource
Tighten by protocol/port if needed; use **All** to allow any.
## Step 5: Tell clientless devices about the remote subnet
Devices without NetBird need a static route pointing to the local routing peer.
**Router-level (recommended)** — add a static route on the site's router so all devices inherit it:
```
Destination: 10.1.0.0/24 # remote network
Gateway: 10.0.0.50 # local routing peer
```
**Per-device fallback** — Linux:
```bash
sudo ip route add 10.1.0.0/24 via 10.0.0.50
```
Windows (PowerShell, persistent):
```powershell
route -p add 10.1.0.0 mask 255.255.255.0 10.0.0.50
```
<Note>
The Linux `ip route add` form above applies only until the next reboot. For persistent Linux routes (Netplan or systemd-networkd), follow the same pattern shown in [Persistent configuration](/manage/networks/masquerade#persistent-configuration), substituting your remote site's CIDR (`10.1.0.0/24` in this example) for the destination shown there. The Windows `route -p add` form is already persistent.
</Note>
Repeat this on the other site with the values swapped, so Site B's router or devices know to reach `10.0.0.0/24` via the local Site B routing peer. Bidirectional site-to-site needs the static routes on both sides.
This step assumes Masquerade is enabled on both routing peers (the default in Step 3). Site-to-site over Networks requires Masquerade to be on — disabling it on a routing peer causes the WireGuard tunnel to drop traffic whose source isn't the peer's NetBird IP, so source-IP preservation isn't currently supported for site-to-site. If you need to preserve source IPs end to end, use the [Network Routes site-to-site setup](/manage/network-routes/use-cases/site-to-site) instead, which supports running with Masquerade disabled.
## Step 6: Verify
From Site A, ping a device at Site B:
```bash
ping 10.1.0.100
```
Reverse from Site B to confirm both directions work. The destination sees the connection coming from its local routing peer's LAN IP — source IPs are masqueraded at both routing peers.
## Cloud routing peers
When the routing peer is a cloud instance, the VPC needs to allow it to forward traffic on behalf of other addresses:
- **AWS**: Disable the source/destination check on the routing peer's ENI. Add a VPC route table entry with the remote CIDR as the destination and the routing peer's ENI as the target. Security groups must allow traffic from the routing peer.
- **GCP**: Enable IP forwarding on the instance. Add a custom route in the VPC with the remote CIDR as the destination and the routing peer instance as the next hop. Firewall rules must allow traffic from the routing peer's internal IP.
- **Azure**: Enable IP forwarding on the routing peer's NIC. Add a route table entry with the remote CIDR pointing at the routing peer. Network security groups must allow the traffic.
## Next steps
- [Masquerade](/manage/networks/masquerade) — how source NAT works on routing peers
- [Site-to-VPN](/manage/networks/use-cases/site-to-vpn) — clientless devices initiating connections to NetBird peers
- [Access Home Devices](/manage/networks/use-cases/access-home-devices) — reach a single site from your NetBird peers
- [Network Routes Site-to-Site](/manage/network-routes/use-cases/site-to-site) — the legacy approach, for wide-open no-policy setups