Seamless Site-to-Site Networking - How I Linked Two Homes Without Installing Tailscale Everywhere
Moving out of your parents' home is a big milestone, but for a self-hosted enthusiast, it presents a unique challenge: how do you keep your homelab services accessible across two different locations?
In my case, I left my UNRAID server (Server A) at my parents' place so they could keep using Nextcloud and Immich with minimal latency. Meanwhile, at my new apartment, I set up a Raspberry Pi (Server B) running Jellyfin.
I wanted a way for my parents to watch Jellyfin on their smart TV and for me to access my UNRAID files without the headache of installing Tailscale on every single device. Here is how I built a "bridge" between two homes using Tailscale and Caddy.
🚀 The Problem: The "Tailscale on Everything" Fatigue
Tailscale is incredible for secure remote access, as it creates a peer-to-peer mesh network with stable IPs and no port forwarding required. However, it has limitations in a family setting:
- Smart TVs and Appliances: Many devices don't support the Tailscale app.
- Maintenance Overhead: I didn’t want to manage Tailscale logins for my parents' phones or tablets.
- The Goal: I wanted remote services to feel local. If I’m at my new home, I want to hit a local IP and see my parents' UNRAID server.
✅ What You'll Need
- Server A (Parents' Home - UNRAID): Tailscale IP
100.a.b.c. Running Nextcloud (Port 8001) and Immich (Port 8002). - Server B (New Home - Raspberry Pi): Tailscale IP
100.x.y.z. Running Jellyfin (Port 5000). - Tailscale: Both servers authenticated on the same Tailnet.
- Docker & Docker Compose: Installed on both machines.
🛠️ The Architecture: The Tailscale-Caddy Bridge
The secret sauce is using Caddy as a reverse proxy to map remote Tailscale IPs to local ports. This is a clean, modern solution that avoids public exposure.
- Tailscale Connects the Servers: The UNRAID and Pi "see" each other via their private Tailscale IPs.
- Caddy Maps the Services: A Caddy container on each side takes the remote Tailscale IP and presents it on a local LAN port.
- Local Access: Any device on the local network can access the remote services by hitting the local server’s IP and assigned port.
📝 Step-by-Step: Docker Compose and Port Mapping
To make this work, the Docker Compose file must explicitly open the ports that will be used for the "bridged" services. Mapping host directories to the container ensures you retain your settings across restarts.
On Server A (Parents' Home)
This server needs to "host" the Jellyfin service coming from your new home.
- Port to Open:
5000
services:
caddy:
image: caddy:latest
restart: unless-stopped
ports:
- "5000:5000" # Local entry point for Remote Jellyfin
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
On Server B (New Home)
This server needs to "host" the Nextcloud and Immich services coming from your parents' home.
- Ports to Open:
8001and8002
services:
caddy:
image: caddy:latest
restart: unless-stopped
ports:
- "8001:8001" # Local entry point for Remote Nextcloud
- "8002:8002" # Local entry point for Remote Immich
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
📂 Configuring the Caddyfiles
The Caddyfile tells the container exactly where to proxy the traffic once it hits those open ports.
Server A Caddyfile (Parents' Home):
# Map remote Jellyfin (running on Server B) to local port 5000
:5000 {
reverse_proxy 100.x.y.z:5000
}
Server B Caddyfile (New Home):
# Map remote Nextcloud (running on Server A) to local port 8001
:8001 {
reverse_proxy 100.a.b.c:8001
}
# Map remote Immich (running on Server A) to local port 8002
:8002 {
reverse_proxy 100.a.b.c:8002
}
📡 How to Connect to Your Services
Once the stacks are "Up", connecting to your services is as simple as using your local LAN IP.
| Service | Access From Parents' Home (Server A) | Access From New Home (Server B) |
|---|---|---|
| Nextcloud | http://<Server_A_Local_IP>:8001 |
http://<Server_B_Local_IP>:8001 |
| Immich | http://<Server_A_Local_IP>:8002 |
http://<Server_B_Local_IP>:8002 |
| Jellyfin | http://<Server_A_Local_IP>:5000 |
http://<Server_B_Local_IP>:5000 |
- For your parents: They just point their Smart TV or browser to their own server's IP on port 5000. No Tailscale login required!
- For you: You access your parents' Nextcloud and Immich by hitting your Raspberry Pi's local IP on ports 8001 and 8002.
🧠 Why This Works So Well
This setup follows a "clean" philosophy:
- ✅ No Client Setup: No need to install Tailscale on every phone, laptop, or TV.
- ✅ Secure & Private: All traffic between homes stays within the Tailscale mesh with end-to-end encryption.
- ✅ Persistent: By mapping volumes, your configuration remains intact after updates.
- ✅ Low Overhead: Caddy is extremely efficient, making it perfect for the Raspberry Pi.
🎉 Final Thoughts
By using one server at each location as a "gateway," you've effectively merged two separate networks into one cohesive homelab. It’s private, secure, and passes the "parent test" for ease of use.
Table of Contents