From 87ea66d190c4a2d73fef72413cfb6b52aa0e8f89 Mon Sep 17 00:00:00 2001 From: mmoulikk Date: Sun, 29 Mar 2026 16:34:37 +0530 Subject: [PATCH 1/5] fix: Save IPTable state after adding configuring --- v1/providers/nebius/instance.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/v1/providers/nebius/instance.go b/v1/providers/nebius/instance.go index 7b126ff..44527d0 100644 --- a/v1/providers/nebius/instance.go +++ b/v1/providers/nebius/instance.go @@ -1752,6 +1752,7 @@ func generateCloudInitUserData(publicKey string, firewallRules v1.FirewallRules) script := `#cloud-config packages: - ufw + - iptables-persistent ` // Add SSH key configuration if provided @@ -1770,6 +1771,13 @@ packages: // accessible from the internet by default. commands = append(commands, generateIPTablesCommands()...) + // Save the complete iptables state (UFW chains + DOCKER-USER rules) so it + // survives instance stop/start cycles. Cloud-init runcmd only executes on + // first boot; on subsequent boots netfilter-persistent restores this + // snapshot before ufw.service starts, ensuring port 22 stays open even if + // ufw.service fails to start cleanly after a reboot. + commands = append(commands, "netfilter-persistent save") + if len(commands) > 0 { // Use runcmd to execute firewall setup commands script += "\nruncmd:\n" From e152a97b8aedc3ad5611135c4cf3ecea10a5a369 Mon Sep 17 00:00:00 2001 From: mmoulikk Date: Mon, 30 Mar 2026 15:32:01 +0530 Subject: [PATCH 2/5] fix(nebius): persist firewall rules across instance stop/start cycles --- v1/providers/nebius/instance.go | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/v1/providers/nebius/instance.go b/v1/providers/nebius/instance.go index 44527d0..f9a9d3a 100644 --- a/v1/providers/nebius/instance.go +++ b/v1/providers/nebius/instance.go @@ -1763,8 +1763,23 @@ packages: } var commands []string + + // Fix a systemd race condition: ufw.service and netfilter-persistent.service + // both start in parallel (both are Before=network-pre.target with no mutual + // ordering). Both call iptables-restore concurrently, and with the iptables-nft + // backend the competing nftables transactions cause UFW to fail with + // "iptables-restore: line 4 failed". This drop-in forces UFW to wait for + // netfilter-persistent to finish first. + commands = append(commands, + "sudo mkdir -p /etc/systemd/system/ufw.service.d", + `sudo tee /etc/systemd/system/ufw.service.d/after-netfilter.conf > /dev/null << 'EOF' +[Unit] +After=netfilter-persistent.service +EOF`, + "sudo systemctl daemon-reload", + ) + // Generate UFW firewall commands (similar to Shadeform's approach) - // UFW (Uncomplicated Firewall) is available on Ubuntu/Debian instances commands = append(commands, generateUFWCommands(firewallRules)...) // Generate IPTables firewall commands to ensure docker ports are not made immediately @@ -1773,10 +1788,11 @@ packages: // Save the complete iptables state (UFW chains + DOCKER-USER rules) so it // survives instance stop/start cycles. Cloud-init runcmd only executes on - // first boot; on subsequent boots netfilter-persistent restores this - // snapshot before ufw.service starts, ensuring port 22 stays open even if - // ufw.service fails to start cleanly after a reboot. - commands = append(commands, "netfilter-persistent save") + // first boot; on subsequent boots netfilter-persistent restores this snapshot, + // then UFW starts after it (due to the drop-in above) and re-applies its rules. + // This provides defense-in-depth: even if UFW fails for any reason, the + // netfilter-persistent snapshot ensures port 22 and DOCKER-USER rules persist. + commands = append(commands, "sudo netfilter-persistent save") if len(commands) > 0 { // Use runcmd to execute firewall setup commands From 71a8a7322a87929aea040077b2a33b5621e9d2c9 Mon Sep 17 00:00:00 2001 From: mmoulikk Date: Mon, 30 Mar 2026 15:38:58 +0530 Subject: [PATCH 3/5] fix: add comment --- v1/providers/nebius/instance.go | 1 + 1 file changed, 1 insertion(+) diff --git a/v1/providers/nebius/instance.go b/v1/providers/nebius/instance.go index f9a9d3a..1943201 100644 --- a/v1/providers/nebius/instance.go +++ b/v1/providers/nebius/instance.go @@ -1780,6 +1780,7 @@ EOF`, ) // Generate UFW firewall commands (similar to Shadeform's approach) + // UFW (Uncomplicated Firewall) is available on Ubuntu/Debian instances commands = append(commands, generateUFWCommands(firewallRules)...) // Generate IPTables firewall commands to ensure docker ports are not made immediately From dd86cfe4c2da51bb9989ba8f5e888504bbb48297 Mon Sep 17 00:00:00 2001 From: mmoulikk Date: Mon, 30 Mar 2026 18:22:42 +0530 Subject: [PATCH 4/5] fix: fix YAML structure --- v1/providers/nebius/instance.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/v1/providers/nebius/instance.go b/v1/providers/nebius/instance.go index 1943201..15d719e 100644 --- a/v1/providers/nebius/instance.go +++ b/v1/providers/nebius/instance.go @@ -1772,10 +1772,7 @@ packages: // netfilter-persistent to finish first. commands = append(commands, "sudo mkdir -p /etc/systemd/system/ufw.service.d", - `sudo tee /etc/systemd/system/ufw.service.d/after-netfilter.conf > /dev/null << 'EOF' -[Unit] -After=netfilter-persistent.service -EOF`, + `printf '[Unit]\nAfter=netfilter-persistent.service\n' | sudo tee /etc/systemd/system/ufw.service.d/after-netfilter.conf > /dev/null`, "sudo systemctl daemon-reload", ) @@ -1796,10 +1793,11 @@ EOF`, commands = append(commands, "sudo netfilter-persistent save") if len(commands) > 0 { - // Use runcmd to execute firewall setup commands script += "\nruncmd:\n" for _, cmd := range commands { - script += fmt.Sprintf(" - %s\n", cmd) + escaped := strings.ReplaceAll(cmd, `\`, `\\`) + escaped = strings.ReplaceAll(escaped, `"`, `\"`) + script += fmt.Sprintf(" - \"%s\"\n", escaped) } } From d3fc279d6e064ef5b7c84b4209932fe7ecb8a4a3 Mon Sep 17 00:00:00 2001 From: mmoulikk Date: Mon, 30 Mar 2026 22:46:04 +0530 Subject: [PATCH 5/5] fix: add comment --- v1/providers/nebius/instance.go | 1 + 1 file changed, 1 insertion(+) diff --git a/v1/providers/nebius/instance.go b/v1/providers/nebius/instance.go index 15d719e..b474773 100644 --- a/v1/providers/nebius/instance.go +++ b/v1/providers/nebius/instance.go @@ -1793,6 +1793,7 @@ packages: commands = append(commands, "sudo netfilter-persistent save") if len(commands) > 0 { + // Use runcmd to execute firewall setup commands script += "\nruncmd:\n" for _, cmd := range commands { escaped := strings.ReplaceAll(cmd, `\`, `\\`)