fixing tailscaled routes

This commit is contained in:
juvdiaz 2026-05-24 08:15:10 -06:00
parent d5d94001e0
commit a9012d8777
3 changed files with 132 additions and 8 deletions

View File

@ -43,6 +43,25 @@ worker_nodes = {
Stateful apps currently pin retained local PVs to the `debian` node. Move or
duplicate those PV manifests when you want storage on another node.
The website NodePort is reachable from the OCI jump box through the Raspberry Pi
Tailscale interface. `bootstrap/cluster` installs a persistent
`homelab-tailscale-nodeport.service` on the configured worker to restore the
route, rp_filter settings, and iptables rules after reboot. Override the
defaults through `tailscale_nodeport_access` when the jump-box IP, Pi Tailscale
IP, pod CIDR, or NodePort changes:
```hcl
tailscale_nodeport_access = {
enabled = true
worker_key = "raspberrypi"
peer_ip = "100.118.255.19"
node_tailscale_ip = "100.77.80.72"
pod_cidr = "10.244.0.0/16"
node_port = 30080
target_port = 80
}
```
For `./lab.sh nuke`, set `WORKER_SSH_TARGETS` to a space-separated list of
remote SSH targets when more worker nodes exist. Set it to an empty string for a
single-node rebuild.

View File

@ -298,6 +298,13 @@ resource "null_resource" "kubeadm_worker" {
registry_config_version = "6"
node_dns_servers = join(" ", var.node_dns_servers)
persistent_volume_dirs = join(",", var.persistent_volume_dirs)
tailscale_nodeport_version = "1"
tailscale_nodeport_enabled = var.tailscale_nodeport_access.enabled && each.key == var.tailscale_nodeport_access.worker_key ? "true" : "false"
tailscale_nodeport_peer_ip = var.tailscale_nodeport_access.peer_ip
tailscale_nodeport_node_tailscale_ip = var.tailscale_nodeport_access.node_tailscale_ip
tailscale_nodeport_pod_cidr = var.tailscale_nodeport_access.pod_cidr
tailscale_nodeport_node_port = tostring(var.tailscale_nodeport_access.node_port)
tailscale_nodeport_target_port = tostring(var.tailscale_nodeport_access.target_port)
}
connection {
@ -518,6 +525,82 @@ if ! getent hosts "${self.triggers.node_name}" >/dev/null; then
printf '%s %s\n' "${self.triggers.host}" "${self.triggers.node_name}" | sudo tee -a /etc/hosts >/dev/null
fi
configure_tailscale_nodeport_access() {
local enabled="$1"
local peer_ip="$2"
local node_tailscale_ip="$3"
local pod_cidr="$4"
local node_port="$5"
local target_port="$6"
if [ "$enabled" != "true" ]; then
return 0
fi
sudo mkdir -p /usr/local/sbin /etc/sysctl.d
sudo tee /etc/sysctl.d/98-homelab-tailscale-nodeport.conf >/dev/null <<NODEPORT_SYSCTL_EOT
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.tailscale0.rp_filter = 0
NODEPORT_SYSCTL_EOT
sudo tee /usr/local/sbin/homelab-tailscale-nodeport.sh >/dev/null <<NODEPORT_SCRIPT_EOT
#!/bin/sh
set -eu
PEER_IP="$peer_ip"
NODE_TAILSCALE_IP="$node_tailscale_ip"
POD_CIDR="$pod_cidr"
NODE_PORT="$node_port"
TARGET_PORT="$target_port"
sysctl -w net.ipv4.conf.all.rp_filter=0 >/dev/null
sysctl -w net.ipv4.conf.tailscale0.rp_filter=0 >/dev/null 2>&1 || true
if ! ip link show tailscale0 >/dev/null 2>&1; then
echo "tailscale0 is not present; skipping Tailscale NodePort routing"
exit 0
fi
ip route replace "$PEER_IP/32" dev tailscale0 src "$NODE_TAILSCALE_IP"
iptables -C INPUT -i tailscale0 -p tcp --dport "$NODE_PORT" -j ACCEPT 2>/dev/null ||
iptables -I INPUT 1 -i tailscale0 -p tcp --dport "$NODE_PORT" -j ACCEPT
iptables -C FORWARD -i tailscale0 -d "$POD_CIDR" -p tcp --dport "$TARGET_PORT" -j ACCEPT 2>/dev/null ||
iptables -I FORWARD 1 -i tailscale0 -d "$POD_CIDR" -p tcp --dport "$TARGET_PORT" -j ACCEPT
iptables -C FORWARD -s "$POD_CIDR" -o tailscale0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null ||
iptables -I FORWARD 1 -s "$POD_CIDR" -o tailscale0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -C POSTROUTING -s 100.64.0.0/10 -d "$POD_CIDR" -p tcp --dport "$TARGET_PORT" -m comment --comment tailscale-nodeport-to-pods -j MASQUERADE 2>/dev/null ||
iptables -t nat -I POSTROUTING 1 -s 100.64.0.0/10 -d "$POD_CIDR" -p tcp --dport "$TARGET_PORT" -m comment --comment tailscale-nodeport-to-pods -j MASQUERADE
NODEPORT_SCRIPT_EOT
sudo chmod 0755 /usr/local/sbin/homelab-tailscale-nodeport.sh
sudo tee /etc/systemd/system/homelab-tailscale-nodeport.service >/dev/null <<'NODEPORT_SERVICE_EOT'
[Unit]
Description=Homelab Tailscale NodePort routing
After=network-online.target tailscaled.service kubelet.service
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/homelab-tailscale-nodeport.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
NODEPORT_SERVICE_EOT
sudo systemctl daemon-reload
sudo systemctl enable homelab-tailscale-nodeport.service >/dev/null
sudo systemctl restart homelab-tailscale-nodeport.service
}
configure_tailscale_nodeport_access \
"${self.triggers.tailscale_nodeport_enabled}" \
"${self.triggers.tailscale_nodeport_peer_ip}" \
"${self.triggers.tailscale_nodeport_node_tailscale_ip}" \
"${self.triggers.tailscale_nodeport_pod_cidr}" \
"${self.triggers.tailscale_nodeport_node_port}" \
"${self.triggers.tailscale_nodeport_target_port}"
configure_containerd_registry "${self.triggers.registry_endpoint}"
pv_dirs="${self.triggers.persistent_volume_dirs}"

View File

@ -61,3 +61,25 @@ variable "worker_nodes" {
}
}
}
variable "tailscale_nodeport_access" {
type = object({
enabled = bool
worker_key = string
peer_ip = string
node_tailscale_ip = string
pod_cidr = string
node_port = number
target_port = number
})
default = {
enabled = true
worker_key = "raspberrypi"
peer_ip = "100.118.255.19"
node_tailscale_ip = "100.77.80.72"
pod_cidr = "10.244.0.0/16"
node_port = 30080
target_port = 80
}
}