#!/bin/bash # Simple netplan static IP setup script # Helper functions have() { command -v "$1" >/dev/null 2>&1; } as_root() { if [ "$(id -u)" -eq 0 ]; then sh -c "$*" elif have sudo; then sudo sh -c "$*" else echo "ERROR: need root or sudo: $*" >&2 exit 1 fi } # Validate IPv4 address validate_ip() { echo "$1" | grep -qE '^([0-9]{1,3}\.){3}[0-9]{1,3}$' || return 1 echo "$1" | IFS='.' read -ra octets for octet in "${octets[@]}"; do [ "$octet" -le 255 ] || return 1 done } # Auto-detect network settings detect_network() { echo "Detecting network settings..." # Detect interface PRIMARY_INTERFACE=$(ip route show default 2>/dev/null | awk '/default/ {print $5; exit}') [ -z "$PRIMARY_INTERFACE" ] && PRIMARY_INTERFACE=$(ip -br link show type ethernet 2>/dev/null | head -1 | cut -d' ' -f1) [ -z "$PRIMARY_INTERFACE" ] && PRIMARY_INTERFACE=$(ip link show 2>/dev/null | grep -v "lo:" | head -1 | cut -d: -f2 | tr -d ' ') # Detect gateway GATEWAY=$(ip route show default 2>/dev/null | awk '/default/ {print $3; exit}') # Detect current IP and subnet - get the main/primary IP only CURRENT_IP_CIDR=$(ip -4 addr show "$PRIMARY_INTERFACE" 2>/dev/null | grep -E "^\s*inet\s+" | head -1 | awk '{print $2}') if [ -n "$CURRENT_IP_CIDR" ]; then CURRENT_IP=$(echo "$CURRENT_IP_CIDR" | cut -d'/' -f1 | tr -d '[:space:]') SUBNET=$(echo "$CURRENT_IP_CIDR" | cut -d'/' -f2 | tr -d '[:space:]') # Ensure subnet has a value [ -z "$SUBNET" ] && SUBNET="24" else CURRENT_IP="192.168.1.100" SUBNET="24" fi DNS="1.1.1.1,9.9.9.9" echo "Interface: $PRIMARY_INTERFACE" echo "Current IP: $CURRENT_IP_CIDR" echo "Gateway: $GATEWAY" echo "Default DNS: $DNS" # Debug variables to identify contamination echo "DEBUG: CURRENT_IP='$CURRENT_IP'" echo "DEBUG: SUBNET='$SUBNET'" } # Get user input get_config() { echo echo "=== Network Configuration ===" echo -n "Static IP address [$CURRENT_IP]: " read -r input STATIC_IP="${input:-$CURRENT_IP}" while ! validate_ip "$STATIC_IP"; do echo "Invalid IP. Try again:" read -r STATIC_IP done # Sanitize user input - ensure only one clean IP STATIC_IP=$(echo "$STATIC_IP" | tr -d '[:space:]') echo -n "Delete existing netplan files? [y/N]: " read -r cleanup CLEANUP_NETPLAN="${cleanup,,}" } # Create netplan config create_config() { echo "Creating netplan configuration..." config="/etc/netplan/20-static-ip.yaml" # Delete existing netplan files if requested if [ "$CLEANUP_NETPLAN" = "y" ]; then echo "Deleting existing netplan files..." as_root "rm -f /etc/netplan/*.yaml" 2>/dev/null || true fi # Backup existing [ -f "$config" ] && as_root "cp '$config' '$config.backup.$(date +%s)'" # Format DNS and sanitize DNS_ADDRESSES=$(echo "$DNS" | sed 's/,/, /g' | tr -d '[:space:]') # Build clean address string - ensure only one IP with subnet STATIC_IP_CLEAN=$(echo "$STATIC_IP" | tr -d '[:space:]') SUBNET_CLEAN=$(echo "$SUBNET" | tr -d '[:space:]') FULL_ADDRESS="${STATIC_IP_CLEAN}/${SUBNET_CLEAN}" # Create new config cat > /tmp/netplan-config.yaml << EOF network: version: 2 renderer: networkd ethernets: $PRIMARY_INTERFACE: dhcp4: no dhcp6: no addresses: - ${FULL_ADDRESS} routes: - to: default via: $GATEWAY nameservers: addresses: [${DNS_ADDRESSES}] EOF # Copy to system location as_root "cp /tmp/netplan-config.yaml '$config'" as_root "chmod 600 '$config'" rm -f /tmp/netplan-config.yaml echo "Configuration created: $config" } # Apply configuration apply_config() { echo "Applying configuration..." as_root "netplan apply" echo "Configuration applied successfully!" # Reset networking echo "Resetting networking..." as_root "ip addr flush dev $PRIMARY_INTERFACE" 2>/dev/null || true as_root "netplan generate" as_root "netplan apply" as_root "systemctl restart systemd-networkd" 2>/dev/null || true as_root "systemctl restart NetworkManager" 2>/dev/null || true sleep 5 # Verify - get the first IP address only, exclude secondary/old IPs local assigned_ip=$(ip -4 addr show "$PRIMARY_INTERFACE" 2>/dev/null | awk '/inet / {print $2; exit}' | cut -d'/' -f1) echo "Assigned IP: $assigned_ip" # Test gateway reachability without ping if timeout 5 bash -c "/dev/null; then echo "✓ Gateway reachable" else echo "⚠ Cannot reach gateway" fi echo "Testing internet connectivity..." if timeout 10 curl -s ip.sgc.ai >/dev/null 2>&1; then local wan_ip=$(timeout 10 curl -s ip.sgc.ai 2>/dev/null) if [ -n "$wan_ip" ]; then echo "✓ SUCCESS: Internet connectivity confirmed" echo "Current WAN IP: $wan_ip" else echo "✗ SUCCESS: Internet connectivity confirmed" fi else echo "✗ FAILED: Cannot reach internet" fi } # Main execution main() { echo "=== Netplan Static IP Setup ===" [ "$(id -u)" -ne 0 ] && { echo "This script requires root privileges. Using sudo..." exec sudo bash "$0" "$@" } have netplan || { echo "ERROR: netplan is not installed"; exit 1; } [ -d /etc/netplan ] || { echo "ERROR: /etc/netplan directory not found"; exit 1; } detect_network get_config # Build clean address string for display - ensure only one IP with subnet STATIC_IP_DISPLAY=$(echo "$STATIC_IP" | tr -d '[:space:]') SUBNET_DISPLAY=$(echo "$SUBNET" | tr -d '[:space:]') DISPLAY_ADDRESS="${STATIC_IP_DISPLAY}/${SUBNET_DISPLAY}" echo echo "=== Configuration Summary ===" echo "Interface: $PRIMARY_INTERFACE" echo "Static IP: ${DISPLAY_ADDRESS}" echo "Gateway: $GATEWAY (auto-detected)" echo "DNS: $DNS" echo echo -n "Apply this configuration? [y/N]: " read -r confirm [ "${confirm,,}" = "y" ] || { echo "Cancelled."; exit 0; } create_config apply_config echo echo "✓ Static IP configuration completed!" echo "Edit future changes: /etc/netplan/20-static-ip.yaml" } main "$@"