Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions src/pages/selfhosted/migration/enable-reverse-proxy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,18 @@ The proxy authenticates with the management server using an access token. Genera
```bash
docker exec -it netbird-server /go/bin/netbird-server token create \
--name "my-proxy" --config <netbird-data-dir>/config.yaml

# NOTE: <netbird-data-dir> is usually located at `/etc/netbird`.
```


**Multi-container** (separate `netbirdio/management` image):

```bash
docker exec -it netbird-management /go/bin/netbird-mgmt token create --name "my-proxy"
```

This outputs a token in the format `nbx_...` (40 characters). **Save the token immediately** - it is only displayed once. The management server stores only a SHA-256 hash.
This outputs a token in the format `nbx_...` (40 characters). **Save the token immediately** - it is only displayed once. The management server stores only a SHA-256 hash. Make sure not to accidentally copy the 20 character Token ID instead.

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Hyphenate the compound adjective.

"20 character" should be hyphenated when used as a compound adjective before a noun.

📝 Proposed fix
-This outputs a token in the format `nbx_...` (40 characters). **Save the token immediately** - it is only displayed once. The management server stores only a SHA-256 hash. Make sure not to accidentally copy the 20 character Token ID instead.
+This outputs a token in the format `nbx_...` (40 characters). **Save the token immediately** - it is only displayed once. The management server stores only a SHA-256 hash. Make sure not to accidentally copy the 20-character Token ID instead.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
This outputs a token in the format `nbx_...` (40 characters). **Save the token immediately** - it is only displayed once. The management server stores only a SHA-256 hash. Make sure not to accidentally copy the 20 character Token ID instead.
This outputs a token in the format `nbx_...` (40 characters). **Save the token immediately** - it is only displayed once. The management server stores only a SHA-256 hash. Make sure not to accidentally copy the 20-character Token ID instead.
🧰 Tools
🪛 LanguageTool

[grammar] ~86-~86: Use a hyphen to join words.
Context: ...ake sure not to accidentally copy the 20 character Token ID instead. You can man...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/selfhosted/migration/enable-reverse-proxy.mdx` at line 86, Update
the phrasing "20 character Token ID" to use a hyphenated compound adjective:
change it to "20-character Token ID" (look for that exact phrase in the
paragraph that explains the nbx_ token format and the Token ID). Ensure any
other instances of numeric + adjective before a noun (e.g., "40 characters" used
as adjective) are hyphenated similarly if present.


You can manage tokens later with:

Expand Down Expand Up @@ -263,7 +266,7 @@ A CrowdSec LAPI (Local API) container runs alongside your deployment, syncs deci
| **enforce** | Blocked IPs are denied immediately. If the bouncer is not yet synced, connections are denied (fail-closed). |
| **observe** | Blocked IPs are logged but not denied. Use this to evaluate CrowdSec before enforcing. |

#### 7a. Add the CrowdSec container
#### 7a. Add the CrowdSec container and configure Traefik/proxy.

Add the following service to your `docker-compose.yml`:

Expand Down Expand Up @@ -303,6 +306,35 @@ Add `crowdsec_db:` to the `volumes:` section, and update the proxy's `depends_on
condition: service_healthy
```

Inside the configuration for the `traefik` service, inside the `command:` section, add:
```yaml
- "--providers.file.filename=/etc/traefik/dynamic.yaml"
```

Inside the `traefik` service `volumes:` section, add:
```yaml
- ./traefik-dynamic.yaml:/etc/traefik/dynamic.yaml:ro
```

Inside the `proxy` service `labels:` section, add:
- traefik.tcp.services.proxy-tls.loadbalancer.serverstransport=pp-v2@file~

Finally, create a new file called `traefik-dynamic.yaml` containing the following:
```yaml
tcp:
serversTransports:
pp-v2:
proxyProtocol:
version: 2
```


Then restart Traefik, we will restart the proxy later.

```bash
docker compose up -d traefik
```

#### 7b. Start CrowdSec and register a bouncer

```bash
Expand Down Expand Up @@ -331,6 +363,9 @@ Add these lines to `proxy.env`:
```bash
NB_PROXY_CROWDSEC_API_URL=http://crowdsec:8080
NB_PROXY_CROWDSEC_API_KEY=<bouncer-key-from-above>
NB_PROXY_FORWARDED_PROTO=https
NB_PROXY_PROXY_PROTOCOL=true
NB_PROXY_TRUSTED_PROXIES=172.30.0.10
Comment on lines +366 to +368

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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Hardcoded Traefik IP doesn't match the main migration flow.

Line 368 sets NB_PROXY_TRUSTED_PROXIES=172.30.0.10, but the main migration steps (Steps 1-7) never assign this static IP to Traefik. The IP 172.30.0.10 is only configured in the optional section "Connecting through Traefik instead of Docker network" (starting line 532), which is separate from the CrowdSec setup.

Without a matching static IP, the proxy won't trust Traefik's actual Docker IP when parsing client addresses from the proxy protocol headers, which will break CrowdSec's IP reputation enforcement.

Impact: CrowdSec will either fail to identify client IPs correctly or block legitimate traffic.

Consider one of these solutions:

Option 1 (recommended): Use subnet notation instead of a single IP to trust the entire Docker network:

-NB_PROXY_TRUSTED_PROXIES=172.30.0.10
+NB_PROXY_TRUSTED_PROXIES=172.30.0.0/24

Option 2: Add static IP configuration to Step 7a before the CrowdSec container instructions:

Expand to see proposed addition to Step 7a

Add this subsection before "Add the following service to your docker-compose.yml:" on line 271:

First, assign a static IP to Traefik so the proxy can trust it:

```yaml
networks:
  netbird:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/24
          gateway: 172.30.0.1

services:
  traefik:
    # ...existing traefik config...
    networks:
      netbird:
        ipv4_address: 172.30.0.10

This ensures NB_PROXY_TRUSTED_PROXIES (configured later) matches Traefik's IP.

</details>

**Option 3**: Add a note instructing users to determine their Traefik container IP:

```diff
 NB_PROXY_FORWARDED_PROTO=https
 NB_PROXY_PROXY_PROTOCOL=true
-NB_PROXY_TRUSTED_PROXIES=172.30.0.10
+NB_PROXY_TRUSTED_PROXIES=<traefik-container-ip>
<Note>
Replace `<traefik-container-ip>` with your Traefik container's IP address on the Docker network. Find it by running:
```bash
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <traefik-container-name>
```
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/selfhosted/migration/enable-reverse-proxy.mdx` around lines 366 -
368, The hardcoded NB_PROXY_TRUSTED_PROXIES=172.30.0.10 will not match the
Traefik IP from the main migration flow; update the docs so CrowdSec trusts the
correct proxy: either (1) change the example NB_PROXY_TRUSTED_PROXIES to a
subnet (e.g., 172.30.0.0/24) so the entire Docker network is trusted, (2) add
the suggested static IP assignment for Traefik in the Step 7a
docker-compose/networks section (netbird + ipv4_address) so Traefik actually
gets 172.30.0.10, or (3) add a short note instructing users to replace
172.30.0.10 with their Traefik container IP (with the docker inspect command)
before starting CrowdSec; refer to NB_PROXY_TRUSTED_PROXIES, the Traefik service
config in Step 7a, and the netbird network example when making the change.

```

Then restart the proxy:
Expand Down
Loading