Remote Access¶
Remote access to the homelab is built around three seats — three independent places to work from, so losing any one of them never means losing access. The OpenVPN endpoint described on the rest of this page belongs to the first seat.
Three Seats¶
| Seat | Where | Role |
|---|---|---|
mbptillo |
Workstation | Build/fix seat — full toolchain for development and repair work; hosts the sslh endpoint (OpenVPN / SSH / mosh sharing vpn.home.tillo.ch:443, external VIP 31.3.128.58) |
| Jump pod | In-cluster, jump namespace, LoadBalancer 192.168.1.62 |
Recurrent/mobile seat — ssh -p443 plus mosh + byobu for day-to-day and on-the-go sessions; automation state lives on its PVC, independent of the workstation |
| bpi-r4 jumpfail | Edge router | Emergency seat — a self-contained failover work environment baked into the router firmware, restorable from the NAS; see BPI-R4 → Jumpfail Seat |
The seats degrade gracefully: everyday sessions land on the jump pod, heavier work happens on mbptillo, and if both the workstation and the cluster are down, the router still provides a working seat.
OpenVPN¶
mbptillo runs an OpenVPN server that authenticates users against OpenLDAP, providing secure remote access to the homelab network. It shares port 443 with SSH and mosh via sslh, so no extra firewall rules are needed.
Traffic Flow¶
flowchart TD
client["OpenVPN client\nvpn.home.tillo.ch:443\n(external VIP 31.3.128.58)"]
subgraph bpir4["BPI-R4"]
dnat[":443 DNAT\n→ mbptillo:4443"]
end
subgraph mbptillo["mbptillo"]
sslh["sslh :4443\nprotocol demux"]
openvpn["OpenVPN\n127.0.0.1:9443\nTCP mode"]
sssd["sssd + PAM\nLDAP auth"]
tun["tun10\n10.8.10.0/24"]
end
subgraph k8s["mdapi-prod"]
ldap["OpenLDAP\n192.168.1.52"]
services["K8s services\n192.168.1.x"]
end
client --> dnat --> sslh
sslh -->|"OpenVPN detected"| openvpn
openvpn --> sssd --> ldap
openvpn --> tun --> services
Components¶
| Component | Location | Notes |
|---|---|---|
| sslh | mbptillo :4443 | Protocol demux for vpn.home.tillo.ch:443; routes OpenVPN to :9443 and SSH (plus mosh sessions bootstrapped over it) to :22 |
| OpenVPN server | mbptillo :9443 (TCP) | Subnet 10.8.10.0/24 via tun10 |
| sssd | mbptillo | PAM auth → OpenLDAP at 192.168.1.52; cache_credentials=true |
| EasyRSA PKI | /etc/openvpn/easyrsa/pki-root |
EC/prime256v1 CA; ta.key for tls-auth |
| vpn-nat.service | mbptillo systemd | iptables MASQUERADE for 10.8.10.0/24 |
Authentication¶
OpenVPN uses PAM for user authentication, which chains through sssd → OpenLDAP. This means VPN access is controlled by the same LDAP directory as mail and other services — no separate user database to maintain. Certificates act as a second factor (tls-auth with ta.key); username/password provides the identity.
cache_credentials=true in sssd ensures users can authenticate even if the cluster is temporarily unreachable (e.g. during a maintenance window).
Why sslh instead of a dedicated port?¶
Exposing port 443 externally is reliably unblocked on all networks — hotels, corporate firewalls, mobile carriers. A dedicated VPN port (1194, 1194/UDP, etc.) is frequently blocked. sslh lets OpenVPN, SSH, and mosh coexist on 443, so the endpoint is reachable regardless of network restrictions. The jump pod applies the same trick on its own address — ssh -p443 against 192.168.1.62.