Reference Architecture: Starlink, Netgate 2100, and Raspberry Pi 5
This reference design publishes one deliberately public web service without relying on an inbound port forward. Starlink’s default IPv4 service may use CGNAT, so the path is Starlink → Netgate 2100 → an isolated LAN4 DMZ → Raspberry Pi 5. The Pi is 192.168.60.10, Nginx listens only on 127.0.0.1:8080, and cloudflared makes outbound tunnel connections from that same Pi. Tailscale is reserved for private administration later.
Define the assumptions
- Starlink is the internet service and its router is in bypass mode if the Netgate is the edge router. Bypass mode removes a local routing layer; it does not remove Starlink CGNAT.
- The Netgate 2100 runs a current, supported pfSense release. LAN4 is an isolated, untagged access port for
192.168.60.0/24, with the firewall at192.168.60.1. - The Pi runs a maintained 64-bit Raspberry Pi OS or Debian Bookworm installation. Its fixed address is
192.168.60.10/24, gateway192.168.60.1. - Nginx serves the origin only on loopback at
127.0.0.1:8080. Cloudflare Tunnel is the only intended public path. - DNS, time, package updates, and tunnel egress are allowed only as documented by the DMZ policy. Tailscale, when added, is for private administration and is not a substitute for host hardening.
Choose the boundaries before implementation
| Path | Starting policy | Reason |
|---|---|---|
| WAN → DMZ | Block; no port forward. | The connector initiates outbound sessions. |
| DMZ → trusted LAN or firewall management | Block and log. | A compromised public host must not pivot inward. |
| DMZ → DNS, NTP, updates, Cloudflare | Allow only required destinations and ports. | Support operation without “DMZ to any.” |
| Trusted admin host → Pi | Allow only later-approved administration, such as Tailscale or SSH. | Keep management private and auditable. |
| IPv6 | Explicitly disable while this lab is IPv4-only, or build equivalent IPv6 policy first. | IPv4 rules and NAT do not protect routed IPv6. |
Prerequisites and recovery plan
Export a known-good Netgate configuration, confirm local console access, and record the current LAN4 switch membership before changing it. Keep a separate trusted-LAN connection available; never perform the LAN4 conversion while connected through LAN4. Back up the Pi’s application content and configuration, and keep a tested local console or keyboard/display recovery path. Record the domain, Cloudflare account owner, intended hostname, and the exact origin URL without placing tokens in notes or screenshots.
Confirm that the Pi’s storage, power supply, cooling, and network cable are suitable for continuous service. Verify the software versions before following package instructions:
cat /etc/os-release
uname -m
uname -r
ip -br address
ip route
nginx -v 2>&1 || true
cloudflared --version 2>/dev/null || true
Bookworm package names and Cloudflare installation procedures can change. Stop if the release is not supported by the current Raspberry Pi OS, Debian, Nginx, or Cloudflare documentation; do not blindly apply an older command to a different release.
Build in four deliberate stages
- Configure and validate the isolated Netgate LAN4 DMZ, including default-deny inter-network policy. Use Prepare Raspberry Pi 5 as a DMZ Web Server.
- Install Nginx, bind it to loopback, and validate the local origin before any public route exists. Use Configure Nginx on Raspberry Pi 5.
- Install the connector from Cloudflare’s official repository or package instructions, create the named tunnel, and map one hostname to
http://127.0.0.1:8080. Use Install Cloudflared and Create the Tunnel. - Add private administration separately with Tailscale and its own identity, ACL, update, and recovery review. Do not expose SSH or pfSense management through the public hostname.
Validation and rollback gates
At each stage, record the expected result before proceeding. A DMZ host must receive only the intended IPv4 configuration, reach the specifically approved resolver and update services, and fail to reach trusted clients, storage, hypervisors, pfSense WebConfigurator, or SSH on the firewall. Nginx must answer on loopback while ss -lntp shows no listener on the Pi’s DMZ address. The tunnel must report healthy, and an external test must reach only the intended hostname. Test that an unrelated hostname, the old public IP, and direct access to 192.168.60.10:8080 from another network do not publish the origin.
Rollback in reverse order: remove or disable the tunnel route and connector service, remove the public DNS or hostname mapping, disable the Nginx site and restore the saved origin configuration, then disconnect the Pi. If the Netgate change caused loss of access, restore the configuration exported before the switch change through the trusted LAN or console. Remove temporary DMZ rules only after confirming the original policy and counters. A reboot is not a rollback.
dispelled