Networking · Self-hosting reference
Homelab External Access Guide for CGNAT
This guide is for accessing a homelab from outside the home network when your ISP is using CGNAT. In that situation, inbound port forwarding from the internet is usually not available, so the best options are ZeroTier, WireGuard via a VPS, or Cloudflare Tunnel.
Assumptions used in examples
- Your homelab is on a private LAN such as
192.168.1.0/24 - Your homelab host has a private address such as
192.168.1.50 - You have a VPS with a public IPv4 address
- You want to reach services such as SSH, Home Assistant, Plex, or a reverse proxy
| Method | Effort | Needs a VPS | Needs a domain | Best for |
|---|---|---|---|---|
| ZeroTier | Low | No | No | Fastest path to private access, no infrastructure |
| WireGuard via VPS | Medium | Yes | No | Full self-hosted control and flexibility |
| Cloudflare Tunnel | Medium | No | Yes | Public access to specific web services |
ZeroTier setup — recommended for simplicity
ZeroTier is the easiest way to get remote access when you are behind CGNAT. It creates a virtual private network over the internet without needing port forwarding.
Why ZeroTier fits CGNAT
- No public IP or inbound port forwarding needed
- Works from phones, laptops, and other devices
- Easy to set up and maintain
- Good for private access to your homelab and LAN services
Step 1 — Create a ZeroTier account
- Go to zerotier.com
- Create an account and sign in
- Create a new network
- Keep the network ID handy
Step 2 — Install ZeroTier on the homelab host
On a Linux server or VM, run:
curl -s https://install.zerotier.com | sudo bash
sudo zerotier-cli join <NETWORK_ID>
If you are using Docker or a different OS, use the ZeroTier package for that platform.
Step 3 — Approve the node in the ZeroTier UI
- Open the ZeroTier admin panel
- Select the network you created
- Find the new member entry for your homelab host
- Click Authorize
Step 4 — Assign a managed IP and test access
Once authorized, ZeroTier should assign the node a private virtual IP (for example 10.147.17.12). You can then connect to the host by that address.
ssh user@10.147.17.12
Step 5 — Install ZeroTier on your phone and laptop
- Install the ZeroTier app on your phone
- Join the same network
- Approve the device in the ZeroTier UI
- Test access to your homelab services
Step 6 — Route traffic for your home-lab LAN through ZeroTier
If you want to reach devices on your home LAN, such as 192.168.1.50 or an entire subnet like 192.168.1.0/24, you need to make the ZeroTier-connected device act as a gateway.
Easy to miss
Joining ZeroTier alone does not automatically forward LAN traffic — the gateway steps below are required.
A. Enable routing on the gateway device
Use the machine that is on your home LAN and also has ZeroTier installed as the gateway. On that Linux box, enable IP forwarding:
sudo sysctl -w net.ipv4.ip_forward=1
To make it persistent, add this line to /etc/sysctl.conf:
net.ipv4.ip_forward=1
Then allow forwarding between the ZeroTier interface and your LAN interface:
sudo iptables -A FORWARD -i zt0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o zt0 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
If your interface names differ, check them with:
ip -br addr
Replace zt0 and eth0 with the actual ZeroTier and LAN interface names.
B. Add a managed route in ZeroTier
In the ZeroTier admin panel:
- Open your network
- Go to Settings or Routes
- Add a managed route for your home subnet, for example
192.168.1.0/24 - Make sure the route is assigned to the gateway node that is running ZeroTier on your LAN
This tells other ZeroTier clients that traffic for your home subnet should be sent to that gateway node.
C. Optional — route a single host instead of the whole subnet
If you only need one device, such as 192.168.1.50, you can route just that host:
sudo ip route add 192.168.1.50/32 via <ZERO_TIER_GW_IP>
For most setups, routing the full subnet is easier.
D. Test it
From a device connected to ZeroTier, try:
ping 192.168.1.50
If that works, you can reach services like:
ssh user@192.168.1.50
Security tips
- Use strong device approval and network ACLs
- Disable unused services on the host
- Prefer SSH keys over passwords
- Keep ZeroTier updated
Cloudflare Tunnel — good for public web services
Cloudflare Tunnel is a strong option if you want to expose services like Home Assistant, Jellyfin, or a reverse proxy without opening inbound ports on your router.
Why this option is different
Unlike ZeroTier or WireGuard, Cloudflare Tunnel does not require you to expose your homelab directly to the internet. Instead, a lightweight Cloudflare connector runs inside your home network and creates an outbound-only tunnel to Cloudflare.
Important requirements
You will need:
- A domain name
- DNS managed in Cloudflare
- A Cloudflare account
- A tunnel connector installed on your homelab or a gateway machine
Important note about DNS
Cloudflare Tunnel requires a public DNS name that points to your Cloudflare-managed domain. For example: home.example.com, ha.example.com, media.example.com.
You must control the DNS records for the domain and either use Cloudflare DNS as the authoritative DNS provider, or delegate the relevant subdomains to Cloudflare.
Without this
Without a valid DNS name, the tunnel cannot be used cleanly for public access.
Basic flow
- Create a Cloudflare account
- Add your domain to Cloudflare
- Configure DNS records for the subdomains you want to expose
- Install the Cloudflare Tunnel connector on your homelab host or another machine on your LAN
- Create a tunnel and define ingress rules
- Route traffic from the public hostname to your internal service
Example setup
Suppose you want ha.example.com to reach your Home Assistant instance at http://192.168.1.50:8123. You would create a Cloudflare Tunnel public hostname for that domain and point it to the internal address.
Authentication and access control
Cloudflare Tunnel gives you several strong security options:
- Cloudflare Access — enforce login before someone can reach the service
- Zero Trust policies — restrict access by email, group, or device posture
- Local auth on the application — use your own login page or reverse proxy auth
- WAF and bot protection — protect your services at the edge
For most homelab setups, the safest approach is:
- Put the service behind a reverse proxy such as Nginx Proxy Manager or Caddy
- Require authentication at Cloudflare Access or at the reverse proxy
- Avoid exposing the service directly to the internet without any auth
Security recommendations
- Do not expose raw services like Home Assistant directly without auth
- Prefer a reverse proxy with TLS termination
- Use Cloudflare Access or another identity layer for sensitive services
- Keep the tunnel connector updated
- Restrict access to trusted users and devices
When Cloudflare Tunnel is a good fit
Use Cloudflare Tunnel when you want:
- Public access to a few web services
- No inbound port forwarding on your router
- Strong built-in security and access control
- A cleaner and more modern setup than raw port forwarding
When it is not the best fit
Cloudflare Tunnel is less ideal when you need:
- Full LAN-wide access to many devices
- Low-level VPN-style connectivity for arbitrary protocols
- A setup that does not depend on a domain and DNS
WireGuard via VPS — more self-hosted
WireGuard is a good alternative when you want more control, or when you prefer not to rely on a third-party overlay network.
Why this works behind CGNAT
Your homelab and your phone both create outbound connections to the VPS. Since the VPS has a public IP, the tunnel is established even though your home network is behind CGNAT.
Recommended layout
- VPS = hub
- Homelab = spoke 1
- Mobile phone = spoke 2
Example IP layout
- VPS private VPN address:
10.20.0.1 - Homelab VPN address:
10.20.0.2 - Phone VPN address:
10.20.0.3 - Home LAN:
192.168.1.0/24
VPS preparation
Requirements
- A VPS with a public IPv4 address
- Ubuntu or Debian installed
- SSH access
- Ability to open UDP port 51820
Install WireGuard on the VPS
sudo apt update
sudo apt install -y wireguard qrencode
Create server keys
sudo mkdir -p /etc/wireguard
cd /etc/wireguard
sudo umask 077
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key
Create the server config
Create /etc/wireguard/wg0.conf:
[Interface]
Address = 10.20.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -A FORWARD -o wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -D FORWARD -o wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Replace <SERVER_PRIVATE_KEY> with the contents of the private key file.
Enable IP forwarding
Edit /etc/sysctl.conf and add or uncomment:
net.ipv4.ip_forward=1
Then apply it:
sudo sysctl -p
Start the VPN service
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0
Open the firewall
If you are using UFW:
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
sudo ufw enable
If your cloud provider has firewall rules, allow UDP 51820 from the internet.
Configure the homelab host as a WireGuard client
On the homelab server, generate a client key pair:
sudo mkdir -p /etc/wireguard
cd /etc/wireguard
sudo umask 077
sudo wg genkey | sudo tee homelab_private.key | sudo wg pubkey | sudo tee homelab_public.key
Create the homelab client config
Create /etc/wireguard/wg0.conf on the homelab host:
[Interface]
Address = 10.20.0.2/24
PrivateKey = <HOMELAB_PRIVATE_KEY>
DNS = 10.20.0.1
[Peer]
PublicKey = <VPS_PUBLIC_KEY>
Endpoint = <VPS_PUBLIC_IP>:51820
AllowedIPs = 10.20.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25
Replace the placeholders with your actual values:
<HOMELAB_PRIVATE_KEY>fromhomelab_private.key<VPS_PUBLIC_KEY>from the VPSserver_public.keyfile<VPS_PUBLIC_IP>with the VPS public IP address
Add the client to the VPS config
On the VPS, edit /etc/wireguard/wg0.conf and add:
[Peer]
PublicKey = <HOMELAB_PUBLIC_KEY>
AllowedIPs = 10.20.0.2/32
Then reload the VPS WireGuard config:
sudo wg syncconf wg0 <(wg-quick strip wg0)
Start the homelab client
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0
Test the tunnel
From the homelab host:
wg
ping 10.20.0.1
From the VPS, check that the peer is connected:
sudo wg
Configure the mobile phone as a WireGuard client
Use the official WireGuard app on Android or iPhone.
Mobile client config example
[Interface]
Address = 10.20.0.3/24
PrivateKey = <PHONE_PRIVATE_KEY>
DNS = 10.20.0.1
[Peer]
PublicKey = <VPS_PUBLIC_KEY>
Endpoint = <VPS_PUBLIC_IP>:51820
AllowedIPs = 10.20.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25
Add the phone peer to the VPS config
On the VPS, add another peer:
[Peer]
PublicKey = <PHONE_PUBLIC_KEY>
AllowedIPs = 10.20.0.3/32
Then reload the VPN:
sudo wg syncconf wg0 <(wg-quick strip wg0)
Notes for mobile access
- If you want the phone to use the VPN for all traffic, use
AllowedIPs = 0.0.0.0/0instead of only the homelab network - If you only want to reach your homelab, keep the LAN subnet in
AllowedIPs
Accessing services after setup
Once the tunnel is up, you can reach your homelab services through the VPN.
- SSH:
ssh user@10.20.0.2 - Home Assistant:
http://10.20.0.2:8123 - Internal web app:
http://192.168.1.50
If you are connecting from the phone, the phone will use the VPN address for the host and the server will see the connection as coming from the VPS network.
Common troubleshooting
? I cannot connect to the VPS
- Make sure UDP 51820 is open on the VPS firewall and cloud provider firewall
- Confirm the VPS is listening with
sudo wg - Check that the endpoint is correct
? The homelab host cannot reach the VPS
- Verify the peer config is correct
- Confirm the WireGuard service is running on both sides
- Check that the private and public keys are matched
? The phone can connect but cannot reach LAN services
- Ensure the homelab host is routing traffic correctly
- Confirm the VPS has IP forwarding enabled
- Make sure the firewall allows forwarding traffic
- Check that
AllowedIPsincludes your LAN subnet such as192.168.1.0/24
? ZeroTier shows connected but cannot reach services
- Confirm the device is authorized in the ZeroTier network
- Check whether the host or router is actually routing traffic to the LAN
- Make sure the service is listening on the correct interface and port
Recommendation
If you want the least effort, use ZeroTier. If you want the most control and a fully self-hosted setup, use WireGuard with a VPS.
For most people, the recommended order is:
- Start with ZeroTier for quick access
- Move to WireGuard if you want stronger self-hosting and flexibility
Useful security notes
Keep in mind across all methods
- Prefer SSH keys over passwords
- Use MFA wherever possible
- Restrict access to only the devices you need
- Keep your OS, Docker containers, and reverse proxy updated
- Do not expose admin panels directly to the internet without a VPN or auth layer