#!/usr/bin/env bash set -euo pipefail NETPLAN_DIR="/etc/netplan" OUT_FILE="${NETPLAN_DIR}/99-static-ip.yaml" if [[ $EUID -ne 0 ]]; then echo "Please run as root: sudo $0" exit 1 fi echo "Detected network interfaces (excluding lo):" ip -o link show | awk -F': ' '{print $2}' | grep -v '^lo$' || true echo read -rp "Interface name (e.g., enp0s3): " IFACE if ! ip link show "$IFACE" >/dev/null 2>&1; then echo "Interface '$IFACE' not found." exit 1 fi read -rp "Static IP with CIDR (e.g., 192.168.1.50/24): " STATIC_CIDR read -rp "Gateway IPv4 (e.g., 192.168.1.1): " GATEWAY4 read -rp "DNS servers (comma-separated, e.g., 1.1.1.1,8.8.8.8): " DNS_CSV read -rp "DNS search domains (optional, comma-separated, e.g., example.com,corp.local) [enter to skip]: " SEARCH_CSV # Basic validation (lightweight) if [[ ! "$STATIC_CIDR" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$ ]]; then echo "Static IP must look like x.x.x.x/yy" exit 1 fi if [[ ! "$GATEWAY4" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then echo "Gateway must look like x.x.x.x" exit 1 fi # Convert CSV -> YAML list: "1.1.1.1,8.8.8.8" -> ["1.1.1.1", "8.8.8.8"] to_yaml_list () { local csv="$1" # trim spaces, split on commas, rejoin csv="$(echo "$csv" | tr -d '[:space:]')" IFS=',' read -r -a arr <<< "$csv" local out="[" local first=1 for item in "${arr[@]}"; do [[ -z "$item" ]] && continue if [[ $first -eq 1 ]]; then out="${out}\"${item}\"" first=0 else out="${out}, \"${item}\"" fi done out="${out}]" echo "$out" } DNS_LIST="$(to_yaml_list "$DNS_CSV")" SEARCH_LIST="" if [[ -n "${SEARCH_CSV// /}" ]]; then SEARCH_LIST="$(to_yaml_list "$SEARCH_CSV")" fi mkdir -p "$NETPLAN_DIR" if [[ -f "$OUT_FILE" ]]; then TS="$(date +%Y%m%d-%H%M%S)" cp -a "$OUT_FILE" "${OUT_FILE}.bak.${TS}" echo "Backed up existing ${OUT_FILE} -> ${OUT_FILE}.bak.${TS}" fi cat > "$OUT_FILE" <> "$OUT_FILE" <