El homelab funciona con direcciones RFC1918 privadas detrás de un router doméstico. El VPS está en internet público con una IP estática. Conseguir que se comuniquen entre sí — de forma fiable, segura y sin exponer nada innecesariamente — es exactamente para lo que sirve una VPN site-to-site.
Uso WireGuard para esto. Es rápido, tiene una superficie de ataque mínima (aproximadamente 4.000 líneas de código frente a las ~100.000 de OpenVPN), y la configuración es lo suficientemente simple como para entenderla completamente. Sin autoridad certificadora, sin PKI compleja, solo pares de claves y rangos de IPs permitidas.
Con el túnel en funcionamiento:
flowchart TD
classDef internet fill:#f9f9f9,stroke:#333,stroke-width:2px;
classDef vps fill:#e1f5fe,stroke:#01579b,stroke-width:2px;
classDef homelab fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
classDef tunnel fill:#fff3e0,stroke:#ef6c00,stroke-width:2px;
Internet([Internet])
subgraph VPS [VPS — IP Pública]
VPS_WG["WireGuard\n10.10.0.1/24"]
VPS_NGINX["NGINX"]
VPS_App["App Rust\nPuerto 9080"]
end
subgraph Homelab [Homelab — LAN Privada]
HL_WG["WireGuard\n10.10.0.2/24"]
Forgejo["Forgejo\n192.168.10.x"]
Runner["Runner Forgejo"]
Staging["Contenedor Staging"]
end
Internet -->|HTTPS| VPS_NGINX
VPS_NGINX --> VPS_App
VPS_WG <-->|UDP cifrado 51820| HL_WG
Runner -->|despliegue vía túnel| VPS_App
Runner --> Staging
class Internet internet;
class VPS_WG,VPS_NGINX,VPS_App vps;
class HL_WG,Forgejo,Runner,Staging homelab;
En el VPS, WireGuard escucha en el puerto UDP 51820. El VPS tiene una IP pública estática, por lo que es el endpoint estable al que se conecta el homelab:
# /etc/wireguard/wg0.conf — VPS
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <clave-privada-vps>
# Peer homelab
[Peer]
PublicKey = <clave-publica-homelab>
AllowedIPs = 10.10.0.2/32, 192.168.10.0/24
AllowedIPs en el lado del VPS incluye la dirección WireGuard del homelab (10.10.0.2) y la subred LAN del homelab (192.168.10.0/24). Esto indica al kernel del VPS que enrute los paquetes destinados a la LAN del homelab a través del túnel.
Habilitar el reenvío de IP en el VPS para que el tráfico pueda enrutarse:
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && sysctl -p
El peer del homelab tiene una IP pública dinámica (conexión residencial), por lo que inicia la conexión al VPS y la mantiene con un keepalive:
# /etc/wireguard/wg0.conf — Homelab (pfSense o Linux)
[Interface]
Address = 10.10.0.2/24
PrivateKey = <clave-privada-homelab>
# Peer VPS
[Peer]
PublicKey = <clave-publica-vps>
Endpoint = <ip-publica-vps>:51820
AllowedIPs = 10.10.0.1/32
PersistentKeepalive = 25
PersistentKeepalive = 25 envía un paquete de handshake cada 25 segundos. Esto mantiene el túnel activo a través de NAT y routers domésticos que de otro modo descartarían las conexiones UDP inactivas.
Genera pares de claves en cada lado — nunca transfieras claves privadas por la red:
# En cada máquina
wg genkey | tee privatekey | wg pubkey > publickey
Intercambia solo las claves públicas. Cada lado conserva su clave privada localmente.
# En cualquier lado
wg show
# Comprobar conectividad
ping 10.10.0.1 # desde homelab → endpoint del túnel VPS
ping 192.168.10.5 # desde VPS → host del homelab
Un handshake exitoso muestra latest handshake en la salida de wg show. Si está ausente, verifica que el puerto UDP 51820 esté abierto en el firewall del VPS y que las claves públicas coincidan con lo configurado en cada peer.
El runner de Forgejo en el homelab despliega en el VPS a través del túnel. El script de despliegue se conecta via SSH a 10.10.0.1 (la dirección WireGuard del VPS) en lugar de la IP pública — el tráfico permanece dentro del túnel cifrado, y el puerto SSH del VPS no necesita ser públicamente accesible.
ssh -i /home/runner/.ssh/deploy_key [email protected] \
"podman pull registry.home.internal/app:latest && \
podman restart app"
WireGuard · pfSense · Linux · Podman · Forgejo CI