Homelab
Talos Migration
Migrating Your Talos Cluster to an Isolated Lab VLAN
Overview
This article migrates the Talos cluster from the Network VLAN (192.168.1.x) to the isolated Lab VLAN (192.168.10.x). The migration maintains etcd quorum throughout by configuring dual-subnet communication before moving nodes.
| Tip: | Having trouble? See v1.1.0 for what your setup should look like after completing this article. |
Before You Begin
Prerequisites
- Firewall Rules completed
- Access to UniFi console
Temporary Firewall Rules Required
During migration, nodes are split across VLANs - some on Lab, others on Network (Core zone). etcd peers must communicate on port 2380 across zones.
The existing firewall rules don't cover this:
- Core → Lab: Only allows Admin Devices (Talos nodes aren't Admin Devices)
- Lab → Core: No rules exist
You'll create temporary rules allowing etcd traffic between zones, then remove them post-migration.
What Changes
| Component | Before | After |
|---|---|---|
| Node IPs | 192.168.1.30-32 | 192.168.10.30-32 |
| Gateway | 192.168.1.1 | 192.168.10.1 |
| API endpoint | 192.168.1.30:6443 | 192.168.10.30:6443 |
Why Dual-Subnet etcd Configuration
etcd stores peer URLs in its internal database. When node IPs change, etcd members can't find each other at the old addresses and quorum is lost1. The fix is to configure etcd to advertise on both subnets before we start moving nodes2.
With dual-subnet configuration:
- Node 1 migrates → still reaches nodes 2+3 on old subnet (quorum: 2/3)
- Node 2 migrates → reaches node 1 on new subnet, node 3 on old (quorum: 2/3)
- Node 3 migrates → all nodes on new subnet (quorum: 3/3)
Quorum is never lost because etcd peers communicate across both subnets during the transition.
How the Migration Works
- Configure etcd to advertise on both subnets
- Apply dual-subnet config and reboot all nodes
- Migrate nodes one at a time (apply new IP config → change VLAN)
- Remove old subnet from etcd config
Configure Dual-Subnet etcd
Before changing any IPs, configure etcd to communicate on both the old and new subnets.
Add Temporary Firewall Rules
During migration, nodes will be split across VLANs. etcd peers must communicate across zones.
In UniFi: Settings → Policy Engine → Zones → Create Policy
| Order | Zone Source | Zone Dest | Name | Src Filter | Action | Dst Filter | Dst Port | Protocol |
|---|---|---|---|---|---|---|---|---|
| 1 | Lab | Core | Temp: Lab to Network | Any | Allow | Any | Any | All |
| 1 | Core | Lab | Temp: Network to Lab | Any | Allow | Any | Any | All |
| Warning: | Remove these rules after migration completes (Post-Migration). |
Add etcd Advertised Subnets
talos/talconfig.yaml:
cniConfig:
name: flannel
cluster: # ADD this section
etcd:
advertisedSubnets:
- 192.168.1.0/24 # Current Network VLAN
- 192.168.10.0/24 # Target Lab VLAN
controlPlane:
patches: | Warning: | This change requires a node reboot to take effect3. Plan for brief cluster disruption. |
Git: Commit Dual-Subnet Config
git add talos/talconfig.yaml
git commit -m "feat(talos): add dual-subnet etcd for VLAN migration" Regenerate and Apply
cd <homelab>/talos
SOPS_AGE_KEY_FILE=<(op document get "sops-key | homelab") \
talhelper genconfig Apply to all nodes:
talosctl apply-config \
--nodes 192.168.1.30 \
--endpoints 192.168.1.30 \
--file clusterconfig/homelab-cluster-talos-node-1.yaml \
--mode=reboot
talosctl apply-config \
--nodes 192.168.1.31 \
--endpoints 192.168.1.31 \
--file clusterconfig/homelab-cluster-talos-node-2.yaml \
--mode=reboot
talosctl apply-config \
--nodes 192.168.1.32 \
--endpoints 192.168.1.32 \
--file clusterconfig/homelab-cluster-talos-node-3.yaml \
--mode=reboot Verify: Post-Reboot Health
Wait for all nodes to reboot:
talosctl health --nodes 192.168.1.30 Expected: All checks pass. etcd is now configured to communicate on both subnets.
Update Talos Configuration
Update IPs
Update all IP references from Network VLAN to Lab VLAN.
talos/talconfig.yaml:
endpoint: https://192.168.10.30:6443 # Was 192.168.1.30
nodes:
- hostname: talos-node-1
ipAddress: 192.168.10.30 # Was 192.168.1.30
controlPlane: true
networkInterfaces:
- interface: enp172s0
addresses:
- 192.168.10.30/24 # Was 192.168.1.30/24
routes:
- network: 0.0.0.0/0
gateway: 192.168.10.1 # Was 192.168.1.1
- hostname: talos-node-2
ipAddress: 192.168.10.31 # Was 192.168.1.31
controlPlane: true
networkInterfaces:
- interface: enp172s0
addresses:
- 192.168.10.31/24
routes:
- network: 0.0.0.0/0
gateway: 192.168.10.1
- hostname: talos-node-3
ipAddress: 192.168.10.32 # Was 192.168.1.32
controlPlane: true
networkInterfaces:
- interface: enp172s0
addresses:
- 192.168.10.32/24
routes:
- network: 0.0.0.0/0
gateway: 192.168.10.1 | Tip: | In vim: :%s/192\.168\.1\./192.168.10./gc to confirm each replacement. Skip the advertisedSubnets line - keep the old subnet until post-migration. |
Git: Commit IP Changes
git add talos/talconfig.yaml
git commit -m "feat(talos): migrate cluster to Lab VLAN" Regenerate Configs
cd <homelab>/talos
SOPS_AGE_KEY_FILE=<(op document get "sops-key | homelab") \
talhelper genconfig Migrate Node 1
| Warning: | This causes brief cluster disruption. Migrate one node at a time. |
Verify: Node 1 Before
talosctl version --nodes 192.168.1.30 --endpoints 192.168.1.30 Talosctl: Apply Node 1 Config
talosctl apply-config \
--nodes 192.168.1.30 \
--endpoints 192.168.1.30 \
--file clusterconfig/homelab-cluster-talos-node-1.yaml \
--mode=reboot Node reboots with the new IP. It's now unreachable because it has a 192.168.10.x IP but is still on the Network VLAN.
UniFi: Change Node 1 to Lab
In UniFi: Devices → [Switch] → Ports → [Node 1 port] → Port Profile → Lab
Verify: Node 1 After
talosctl version --nodes 192.168.10.30 --endpoints 192.168.10.30 Verify: etcd After Node 1
talosctl health --nodes 192.168.10.30 --endpoints 192.168.10.30 Expected: All checks pass. etcd maintains quorum with nodes 2+3 on the old subnet.
Migrate Node 2
Verify: Node 2 Before
talosctl version --nodes 192.168.1.31 --endpoints 192.168.1.31 Talosctl: Apply Node 2 Config
talosctl apply-config \
--nodes 192.168.1.31 \
--endpoints 192.168.1.31 \
--file clusterconfig/homelab-cluster-talos-node-2.yaml \
--mode=reboot UniFi: Change Node 2 to Lab
In UniFi: Set node 2's port to Lab profile.
Verify: Node 2 After
talosctl version --nodes 192.168.10.31 --endpoints 192.168.10.31 Verify: etcd After Node 2
talosctl health --nodes 192.168.10.30 --endpoints 192.168.10.30 Expected: All checks pass. etcd maintains quorum across both subnets.
Migrate Node 3
Verify: Node 3 Before
talosctl version --nodes 192.168.1.32 --endpoints 192.168.1.32 Talosctl: Apply Node 3 Config
talosctl apply-config \
--nodes 192.168.1.32 \
--endpoints 192.168.1.32 \
--file clusterconfig/homelab-cluster-talos-node-3.yaml \
--mode=reboot UniFi: Change Node 3 to Lab
In UniFi: Set node 3's port to Lab profile.
Verify: Node 3 After
talosctl version --nodes 192.168.10.32 --endpoints 192.168.10.32 Verify: etcd After Node 3
talosctl health --nodes 192.168.10.30 --endpoints 192.168.10.30 Expected: All checks pass. All nodes are now on Lab VLAN.
Complete Post-Migration Steps
Update kubeconfig
talosctl kubeconfig --nodes 192.168.10.30 ~/.kube/config Verify: Cluster Health
talosctl health --nodes 192.168.10.30
kubectl get nodes -o wide Expected: All nodes Ready with 192.168.10.x IPs.
Remove Temporary Firewall Rules
In UniFi: Settings → Policy Engine → Zones
Delete both temporary rules created earlier - they're no longer needed since all nodes are on the same VLAN:
| Zone Source | Zone Dest | Name | Action |
|---|---|---|---|
| Lab | Core | Temp: Lab to Network | Delete |
| Core | Lab | Temp: Network to Lab | Delete |
Remove Old Subnet
Now that all nodes are on the new subnet, remove the old subnet from etcd configuration.
talos/talconfig.yaml:
cniConfig:
name: flannel
cluster:
etcd:
advertisedSubnets:
- 192.168.10.0/24 # Only new subnet (remove old)
controlPlane:
patches: Commit, regenerate, and apply:
git add talos/talconfig.yaml
git commit -m "feat(talos): remove old subnet from etcd config" SOPS_AGE_KEY_FILE=<(op document get "sops-key | homelab") \
talhelper genconfig
talosctl apply-config \
--nodes 192.168.10.30 \
--file clusterconfig/homelab-cluster-talos-node-1.yaml \
--mode=reboot
talosctl apply-config \
--nodes 192.168.10.31 \
--file clusterconfig/homelab-cluster-talos-node-2.yaml \
--mode=reboot
talosctl apply-config \
--nodes 192.168.10.32 \
--file clusterconfig/homelab-cluster-talos-node-3.yaml \
--mode=reboot Final Verification
talosctl health --nodes 192.168.10.30
talosctl etcd members --nodes 192.168.10.30 Expected: All etcd members show 192.168.10.x peer URLs.
Next Steps
Nodes are on the isolated Lab VLAN, but both remote and local access need updates. Tailscale routes still advertise the old Network VLAN, so you can't reach the new node IPs remotely. For local services, MetalLB still assigns IPs from the Network VLAN and L2 ARP can't cross VLANs, so Plex may fall back to relay mode (480p).
Update Tailscale first to restore remote cluster management, then MetalLB for local service access.
See: Tailscale Migration
Resources
Footnotes
etcd.io, "Runtime reconfiguration," etcd.io. Accessed: Feb. 22, 2026. [Online]. Available: https://etcd.io/docs/v3.3/op-guide/runtime-configuration/ ↩
Sidero Labs, "Production Clusters," talos.dev. Accessed: Feb. 22, 2026. [Online]. Available: https://www.talos.dev/v1.9/introduction/prodnotes/ ↩
Sidero Labs, "Changing machine.etcd.advertisedSubnets should work without reboot," GitHub. Accessed: Feb. 22, 2026. [Online]. Available: https://github.com/siderolabs/talos/issues/9605 ↩