Add Hetzner VPS to Tailscale tailnet for private deployment access #141
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
The Gitea instance and act-runner live on the home LAN — not reachable from the public internet. The Hetzner VPS is on the public internet. For CI to deploy to the VPS, the two need a secure private channel.
Tailscale is already used on the home network. Adding the VPS to the same tailnet gives the act-runner a stable, authenticated route to the VPS over WireGuard — no open firewall ports, no VPN server to maintain, no dynamic IP problems.
This is a prerequisite for the CI deploy pipeline (#142 and #143).
What to do
1. Install Tailscale on the VPS
2. Authenticate and join the tailnet
Generate a reusable auth key in the Tailscale admin console (tailscale.com/admin/settings/keys):
tag:vps) so it gets the right ACL policy3. Verify connectivity from the act-runner host
From the home server where the act-runner runs:
Note the assigned Tailscale IP (
tailscale ip -4on the VPS).4. Lock down the VPS firewall
The VPS should only accept SSH over Tailscale, not from the public internet. Only ports 80 and 443 (Caddy) need to be publicly open.
This means
ssh user@<public-ip>stops working — SSH only works viassh user@<tailscale-ip>. That is intentional.5. Create a deploy user on the VPS
Avoid using root or your personal user for CI deploys. Create a dedicated
deployuser with Docker access:The deploy user's
authorized_keyswill be populated in #142 (SSH key setup).6. Store the Tailscale IP as a Gitea secret
In Gitea → repo settings → Secrets:
VPS_TAILSCALE_IP100.64.x.x)This secret is used by the deploy job in #142.
Acceptance criteria
tailscale ping familienarchiv-vpssucceeds from the home server.ssh deploy@<VPS_TAILSCALE_IP>works from the home server.ssh deploy@<VPS_PUBLIC_IP>is refused (firewall blocks public SSH).VPS_TAILSCALE_IPsecret exists in Gitea repo settings.