Remote Access to Your Home Server

The Problem

You have a server at home running Jellyfin, Nextcloud, Home Assistant, or a dozen other self-hosted services. They work great on your local network. Then you leave the house, open your phone, and can’t reach any of them.

Remote access bridges that gap. The question isn’t whether you need it — you do, unless your server is only useful inside your house. The question is which method fits your situation: your ISP, your network, your threat model, and how much setup you’re willing to do.

This guide covers every practical approach, compares them, and tells you which one to pick.

Remote Access Methods Overview

There are five main ways to reach your home server from outside your network. Each makes different tradeoffs between ease of setup, security, performance, and flexibility.

FeatureTailscaleWireGuardCloudflare TunnelReverse Proxy + DDNSSSH Tunneling
Ease of setupVery easyMediumEasyMediumEasy (ad hoc)
CostFree (personal)FreeFreeFree (domain required)Free
PerformanceNear-directDirect+10-30ms latencyDirectModerate
Port forwarding neededNoYes (UDP 51820)NoYes (80, 443)Yes (SSH port)
EncryptionWireGuard (automatic)WireGuardTLS via CloudflareTLS (you manage)SSH
Public access to servicesNo (private only)No (private only)YesYesNo
Self-hosted optionHeadscaleNativeNoNativeNative
Mobile supportiOS, AndroidiOS, AndroidN/A (browser)N/A (browser)Limited
Docker supportSidecar containerContainer or hostOfficial containerNativeN/A
Works behind CGNATYesNoYesNoRequires outbound trick
Best forBeginners, personal useFull control, advanced usersPublic-facing servicesTraditional hostingQuick debugging

CGNAT note: If your ISP uses Carrier-Grade NAT (common with 5G/LTE home internet and some fiber providers), you don’t have a public IP. Tailscale and Cloudflare Tunnel are your only straightforward options. Check by comparing your router’s WAN IP to what curl ifconfig.me returns — if they differ, you’re behind CGNAT.

Tailscale / Headscale

Recommended for: Beginners and anyone who wants private remote access without fighting their network.

Tailscale builds a WireGuard-based mesh VPN between your devices. Install it on your server and your phone, and they can reach each other directly — regardless of firewalls, NAT, or CGNAT. Every device gets a stable 100.x.x.x IP address.

Why Tailscale Wins for Most People

  • Zero network configuration. No port forwarding, no DNS records, no firewall rules. Install, log in, done.
  • Works everywhere. Behind CGNAT, restrictive corporate networks, hotel Wi-Fi — Tailscale punches through.
  • Fast. Direct peer-to-peer connections using WireGuard. Traffic doesn’t route through a third party in most cases.
  • Free tier is generous. Up to 100 devices, 3 users. More than enough for personal self-hosting.

Quick Setup

Install on your server:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

Install the Tailscale app on your phone or laptop. Log in with the same account. Your server is now reachable at its Tailscale IP (e.g., 100.64.0.1).

Access any service using the Tailscale IP:

http://100.64.0.1:8096    # Jellyfin
http://100.64.0.1:8080    # Nextcloud
http://100.64.0.1:8123    # Home Assistant

Headscale: Self-Hosted Tailscale

If you don’t want to depend on Tailscale’s coordination servers, Headscale is an open-source, self-hosted implementation of the Tailscale control server. Your devices still run the official Tailscale client, but they coordinate through your own server instead of Tailscale’s infrastructure.

The tradeoff: significantly more setup and maintenance. You need a publicly reachable server to run Headscale (a small VPS works), and you manage user accounts and ACLs yourself.

Use Headscale when: You need more than the free tier allows, you want zero dependency on Tailscale Inc., or you have compliance requirements that prohibit third-party coordination servers.

For the full setup walkthrough, see Tailscale Setup for Self-Hosting.

WireGuard

Recommended for: Advanced users who want full control and don’t mind manual configuration.

WireGuard is a VPN protocol built into the Linux kernel. It’s the protocol Tailscale uses under the hood, but without the automatic management layer. You configure keys, endpoints, and routing yourself.

Why Choose Raw WireGuard

  • No third-party dependency. No accounts, no coordination servers, no companies involved.
  • Full control. You define every peer, every allowed IP, every routing rule.
  • Kernel-level performance. Faster than any userspace VPN. Negligible overhead.
  • Minimal attack surface. The entire codebase is around 4,000 lines of code.

The Tradeoff

  • Requires a public IP and port forwarding (UDP 51820 by default). Won’t work behind CGNAT.
  • Manual key management. You generate and distribute keys for every peer.
  • No automatic NAT traversal. If your IP changes, you update configs manually (or set up DDNS).

Quick Setup

Install WireGuard on your server:

sudo apt install wireguard

Generate server keys:

wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key

Create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server_private_key>

# Enable IP forwarding
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# Your phone/laptop
PublicKey = <client_public_key>
AllowedIPs = 10.0.0.2/32

Start WireGuard:

sudo systemctl enable --now wg-quick@wg0

Forward UDP port 51820 on your router to your server’s local IP. Set up Dynamic DNS if your ISP assigns a changing public IP.

For the full setup walkthrough, see WireGuard VPN Setup for Self-Hosting.

Cloudflare Tunnel

Recommended for: Services you want publicly accessible without opening ports.

Cloudflare Tunnel creates an outbound-only connection from your server to Cloudflare’s edge. External users hit Cloudflare, which proxies the request through the tunnel to your server. Your home IP stays hidden, no ports are opened, and you get free DDoS protection.

Why Choose Cloudflare Tunnel

  • No port forwarding. The tunnel is outbound-only. Your router doesn’t need any configuration.
  • Works behind CGNAT. Since the connection is outbound, your ISP’s NAT doesn’t matter.
  • Free SSL and DDoS protection. Cloudflare handles TLS termination and absorbs attacks.
  • Hides your home IP. DNS points to Cloudflare, not your house.

The Tradeoff

  • HTTP/HTTPS only for most use cases. Non-HTTP protocols (SSH, game servers, raw TCP) require Cloudflare WARP on the client side.
  • Adds latency. Every request routes through Cloudflare’s network — typically 10-30ms extra.
  • Dependency on Cloudflare. Your services go down if Cloudflare goes down or changes their free tier terms.
  • Not truly self-hosted. A third party sees all your traffic.

Quick Setup with Docker

Requires a Cloudflare account and a domain with DNS managed by Cloudflare.

services:
  cloudflared:
    image: cloudflare/cloudflared:2024.12.2
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel run
    environment:
      - TUNNEL_TOKEN=<your-tunnel-token>

Create a tunnel in the Cloudflare Zero Trust dashboard, grab the token, and map your services to subdomains (e.g., jellyfin.yourdomain.com -> http://jellyfin:8096).

For the full setup walkthrough, see Cloudflare Tunnel Setup Guide.

Reverse Proxy + DDNS

Recommended for: Traditional self-hosting setups where you want public access with a custom domain.

This is the classic approach: forward ports 80 and 443 from your router to a reverse proxy on your server. The reverse proxy routes requests to the correct service based on the domain name and handles SSL certificates via Let’s Encrypt. Dynamic DNS keeps your domain pointed at your home IP even when it changes.

Why Choose This Approach

  • No third-party dependency for traffic routing. Requests go directly from the internet to your server.
  • Best latency. No intermediary adding milliseconds.
  • Full protocol support. HTTP, TCP, UDP — anything you want to expose.
  • Battle-tested. This is how the internet works. Every tutorial and tool supports it.

The Tradeoff

  • Requires port forwarding on your router. Won’t work behind CGNAT.
  • Exposes your home IP. DNS records point directly to your public IP. Anyone can look it up.
  • You manage SSL. Let’s Encrypt makes this easy, but it’s still on you.
  • More attack surface. Open ports are visible to the internet. Bots will find them.

Stack Summary

  1. Reverse proxy: Nginx Proxy Manager, Traefik, or Caddy — see Reverse Proxy Setup for a full comparison
  2. Dynamic DNS: Cloudflare API, DuckDNS, or ddclient — see Dynamic DNS Setup
  3. Port forwarding: Ports 80 and 443 from your router to your server — see Port Forwarding
  4. Firewall: UFW or iptables to limit access — see Firewall Setup

For the full reverse proxy walkthrough, see Reverse Proxy Setup for Self-Hosting.

SSH Tunneling

Recommended for: Developers who need quick, temporary access to a specific service.

SSH tunneling forwards a port from your local machine through an SSH connection to your server. It’s not a permanent solution, but it’s the fastest way to access a service when you’re in a pinch — no setup beyond SSH access.

Quick Example

Access Portainer (port 9000) on your home server from your laptop:

ssh -L 9000:localhost:9000 user@your-server-ip

Now open http://localhost:9000 in your browser. Traffic is encrypted through the SSH tunnel.

When SSH Tunneling Makes Sense

  • Debugging a service that’s not exposed through your reverse proxy
  • Accessing admin panels temporarily without exposing them
  • Quick access from a machine where you can’t install Tailscale or WireGuard
  • One-off access to a database or internal API

When It Doesn’t

  • Permanent remote access (use Tailscale or WireGuard)
  • Mobile access (SSH clients on phones are clunky)
  • Sharing access with non-technical users

For the full setup walkthrough, see SSH Tunneling Guide.

VPN vs Reverse Proxy: When to Use Which

This is the most common decision point. The answer depends on whether your services need to be publicly accessible.

Use a VPN (Tailscale or WireGuard) When

  • Only you (and your household) need access. Jellyfin, Home Assistant, Nextcloud for personal use — a VPN keeps these invisible to the internet.
  • You’re behind CGNAT. Tailscale works regardless of your ISP’s NAT situation.
  • You want zero public attack surface. No open ports, no public DNS records pointing to your IP.
  • You access non-HTTP services. Game servers, SSH, database connections, SMB shares — VPNs tunnel any protocol.

Use a Reverse Proxy (or Cloudflare Tunnel) When

  • Other people need access. A friend wants to use your Jellyfin server. A client needs to reach your Gitea instance. You can’t install a VPN on their device.
  • You’re hosting a public service. A blog, a status page, an API — anything the internet at large should reach.
  • You want clean URLs. jellyfin.yourdomain.com is better than 100.64.0.1:8096 for services you use heavily.

Combine Them

Most serious self-hosters use both:

  • VPN for private services: admin panels, databases, monitoring dashboards, Home Assistant
  • Reverse proxy or Cloudflare Tunnel for public-facing services: media sharing, public APIs, blogs

This gives you the security of a VPN for sensitive services and the convenience of public access for everything else.

Security Considerations

Remote access means your server is reachable from outside your home network. That’s the point — but it also increases your attack surface. Follow these rules regardless of which method you choose.

Universal Rules

  1. Never expose admin panels publicly. Portainer, database admin tools, monitoring dashboards — these go behind a VPN only.
  2. Use strong, unique passwords on every service. A reverse proxy doesn’t help if Nextcloud has a weak admin password.
  3. Enable two-factor authentication on every service that supports it.
  4. Keep software updated. Docker images, reverse proxy, OS packages. Automated updates where possible — see Docker Automatic Updates.
  5. Monitor access logs. Know what’s hitting your server. See Container Logging and Monitoring Basics.

Method-Specific Security Notes

MethodKey RiskMitigation
TailscaleAccount compromiseUse SSO, enable MFA on your Tailscale account
WireGuardKey compromiseRotate keys periodically, use per-device keys
Cloudflare TunnelCloudflare sees your trafficDon’t tunnel sensitive data you wouldn’t want a third party to see
Reverse ProxyOpen ports attract botsUse fail2ban, rate limiting, geo-blocking
SSH TunnelingSSH brute forceKey-based auth only, change default port, use fail2ban

For a comprehensive checklist, see Server Security Hardening and Self-Hosting Security Checklist.

Which Should You Pick?

If you’re new to self-hosting: Start with Tailscale. Install it in five minutes, access your server from anywhere, and move on to the interesting part — running apps. You can always add a reverse proxy later when you need public access.

If you want full control and have a public IP: Set up WireGuard for private access and a reverse proxy for public services. This is the most flexible and self-reliant setup.

If you’re behind CGNAT and need public access: Cloudflare Tunnel is your best option. No port forwarding required, and the free tier covers most self-hosters.

If you just need to check something quickly: SSH tunnel. No setup, no commitment, just a single command.

Don’t overthink it. Pick one, set it up, and iterate. You can always change your approach later — none of these decisions are permanent.

Comments