[ 'mode' => 'dhcp', 'modev6' => 'auto', 'network_primary_ip' => '', 'network_primary_gateway' => '', 'network_primary_vlan' => '', 'network_primary_dns1' => '', 'network_primary_dns2' => '', 'network_primary_ipv6' => '', 'network_primary_ipv6_prefix' => '', 'network_primary_ipv6_gateway' => '', 'network_primary_ipv6_vlan' => '', 'network_primary_ipv6_dns1' => '', 'network_primary_ipv6_dns2' => '', ], 'secondary' => [ 'mode' => 'disabled', 'modev6' => 'disabled', 'network_secondary_ip' => '', 'network_secondary_gateway' => '', 'network_secondary_vlan' => '', 'network_secondary_dns1' => '', 'network_secondary_dns2' => '', 'network_secondary_ipv6' => '', 'network_secondary_ipv6_prefix' => '', 'network_secondary_ipv6_gateway' => '', 'network_secondary_ipv6_vlan' => '', 'network_secondary_ipv6_dns1' => '', 'network_secondary_ipv6_dns2' => '', ], ]; if (file_exists($jsonFile)) { $raw = file_get_contents($jsonFile); $data = json_decode($raw, true); if (!is_array($data)) $data = $defaults; } else { $data = $defaults; } $errors = []; $success = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $get = function ($k) { return isset($_POST[$k]) ? trim((string)$_POST[$k]) : ''; }; $primary_mode = in_array($get('primary_mode'), ['dhcp', 'static', 'disabled']) ? $get('primary_mode') : 'dhcp'; $primary_modev6 = in_array($get('primary_mode'), ['auto', 'dhcpv6', 'static', 'disabled']) ? $get('primary_mode') : 'auto'; $secondary_mode = in_array($get('secondary_mode'), ['dhcp', 'static', 'disabled']) ? $get('secondary_mode') : 'dhcp'; $secondary_modev6 = in_array($get('secondary_mode'), ['auto', 'dhcpv6', 'static', 'disabled']) ? $get('secondary_mode') : 'auto'; $network_primary_ip = $get('network_primary_ip'); $network_primary_gateway = $get('network_primary_gateway'); $network_primary_vlan = $get('network_primary_vlan'); $network_primary_dns1 = $get('network_primary_dns1'); $network_primary_dns2 = $get('network_primary_dns2'); $network_primary_ipv6 = $get('network_primary_ipv6'); $network_primary_ipv6_prefix = $get('network_primary_ipv6_prefix'); $network_primary_ipv6_gateway = $get('network_primary_ipv6_gateway'); $network_primary_ipv6_vlan = $get('network_primary_ipv6_vlan'); $network_primary_ipv6_dns1 = $get('network_primary_ipv6_dns1'); $network_primary_ipv6_dns2 = $get('network_primary_ipv6_dns2'); $network_secondary_ip = $get('network_secondary_ip'); $network_secondary_subnet = $get('network_secondary_subnet'); $network_secondary_gateway = $get('network_secondary_gateway'); $network_secondary_vlan = $get('network_secondary_vlan'); $network_secondary_dns1 = $get('network_secondary_dns1'); $network_secondary_dns2 = $get('network_secondary_dns2'); $network_secondary_ipv6 = $get('network_secondary_ipv6'); $network_secondary_ipv6_prefix = $get('network_secondary_ipv6_prefix'); $network_secondary_ipv6_gateway = $get('network_secondary_ipv6_gateway'); $network_secondary_ipv6_vlan = $get('network_secondary_ipv6_vlan'); $network_secondary_ipv6_dns1 = $get('network_secondary_ipv6_dns1'); $network_secondary_ipv6_dns2 = $get('network_secondary_ipv6_dns2'); $new = [ 'primary' => [ 'mode' => 'dhcp', 'modev6' => 'auto', 'network_primary_ip' => $network_primary_ip, 'network_primary_gateway' => $network_primary_gateway, 'network_primary_vlan' => $network_primary_vlan, 'network_primary_dns1' => $network_primary_dns1, 'network_primary_dns2' => $network_primary_dns2, 'network_primary_ipv6' => $network_primary_ipv6, 'network_primary_ipv6_prefix' => $network_primary_ipv6_prefix, 'network_primary_ipv6_gateway' => $network_primary_ipv6_gateway, 'network_primary_ipv6_vlan' => $network_primary_ipv6_vlan, 'network_primary_ipv6_dns1' => $network_primary_ipv6_dns1, 'network_primary_ipv6_dns2' => $network_primary_ipv6_dns2 ], 'secondary' => [ 'mode' => 'disabled', 'modev6' => 'disabled', 'network_secondary_ip' => $network_secondary_ip, 'network_secondary_gateway' => $network_secondary_gateway, 'network_secondary_vlan' => $network_secondary_vlan, 'network_secondary_dns1' => $network_secondary_dns1, 'network_secondary_dns2' => $network_secondary_dns2, 'network_secondary_ipv6' => $network_secondary_ipv6, 'network_secondary_ipv6_prefix' => $network_secondary_ipv6_prefix, 'network_secondary_ipv6_gateway' => $network_secondary_ipv6_gateway, 'network_secondary_ipv6_vlan' => $network_secondary_ipv6_vlan, 'network_secondary_ipv6_dns1' => $network_secondary_ipv6_dns1, 'network_secondary_ipv6_dns2' => $network_secondary_ipv6_dns2 ], ]; $json = json_encode($new, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); if (file_put_contents($jsonFile, $json, LOCK_EX) === false) { $errors[] = "Failed to write {$jsonFile}. Check permissions."; } else { $data = $new; $success = 'Saved.'; $netplan = [ 'network' => [ 'version' => 2, 'renderer' => 'networkd', 'ethernets' => [ $iface => [] ], 'vlans' => [] ] ]; function build_interface(array $d, string $key): array { $cfg = []; $addresses = []; $routes = []; /* ================= IPv4 ================= */ switch ($d['mode'] ?? 'disabled') { case 'dhcp': $cfg['dhcp4'] = true; break; case 'static': if (!empty($d["network_{$key}_ip"]) && !empty($d["network_{$key}_subnet"])) { $addresses[] = $d["network_{$key}_ip"] . '/' . $d["network_{$key}_subnet"]; } if (!empty($d["network_{$key}_gateway"])) { $routes[] = [ 'to' => 'default', 'via' => $d["network_{$key}_gateway"] ]; } $cfg['dhcp4'] = false; break; case 'disabled': default: $cfg['dhcp4'] = false; break; } /* ================= IPv6 ================= */ switch ($d['modev6'] ?? 'disabled') { case 'auto': // SLAAC $cfg['accept-ra'] = true; $cfg['dhcp6'] = false; break; case 'dhcp6': $cfg['dhcp6'] = true; $cfg['accept-ra'] = false; break; case 'static': if (!empty($d["network_{$key}_ipv6"]) && !empty($d["network_{$key}_ipv6_prefix"])) { $addresses[] = $d["network_{$key}_ipv6"] . '/' . $d["network_{$key}_ipv6_prefix"]; } if (!empty($d["network_{$key}_ipv6_gateway"])) { $routes[] = [ 'to' => '::/0', 'via' => $d["network_{$key}_ipv6_gateway"] ]; } $cfg['dhcp6'] = false; $cfg['accept-ra'] = false; break; case 'disabled': default: $cfg['dhcp6'] = false; $cfg['accept-ra'] = false; break; } /* ================= Addresses ================= */ if ($addresses) { $cfg['addresses'] = $addresses; } /* ================= Routes ================= */ if ($routes) { $cfg['routes'] = $routes; } /* ================= DNS ================= */ $dns = array_values(array_filter([ $d["network_{$key}_dns1"] ?? '', $d["network_{$key}_dns2"] ?? '', $d["network_{$key}_ipv6_dns1"] ?? '', $d["network_{$key}_ipv6_dns2"] ?? '', ])); if ($dns) { $cfg['nameservers'] = [ 'addresses' => $dns ]; } return $cfg; } /* ---------- VLAN detection ---------- */ $primary_vlan = trim($data['primary']['network_primary_vlan'] ?? ''); $secondary_vlan = trim($data['secondary']['network_secondary_vlan'] ?? ''); $uses_vlan = ($primary_vlan !== '' || $secondary_vlan !== ''); /* ---------- No VLAN: apply primary only ---------- */ if (!$uses_vlan) { $netplan['network']['ethernets'][$iface] = build_interface($data['primary'], 'primary'); } /* ---------- VLAN mode ---------- */ else { // base iface must exist but empty $netplan['network']['ethernets'][$iface] = []; if ($primary_vlan !== '') { $vif = "{$iface}.{$primary_vlan}"; $netplan['network']['vlans'][$vif] = array_merge([ 'id' => (int)$primary_vlan, 'link' => $iface ], build_interface($data['primary'], 'primary')); } if ($secondary_vlan !== '') { $vif = "{$iface}.{$secondary_vlan}"; $netplan['network']['vlans'][$vif] = array_merge([ 'id' => (int)$secondary_vlan, 'link' => $iface ], build_interface($data['secondary'], 'secondary')); } } /* ---------- write ---------- */ $yaml = netplan_yaml($netplan); file_put_contents('/var/www/50-cloud-init.yaml', $yaml); } } ?>
'; foreach ($errors as $e) echo '