diff --git a/setup-network.sh b/setup-network.sh new file mode 100644 index 0000000..f97f850 --- /dev/null +++ b/setup-network.sh @@ -0,0 +1,166 @@ +#!/usr/bin/env bash +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' + +info() { echo -e "${GREEN}[+]${NC} $*"; } +warn() { echo -e "${YELLOW}[!]${NC} $*"; } +die() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; } +header() { echo -e "\n${CYAN}══════════════════════════════════════════${NC}"; echo -e "${CYAN} $*${NC}"; echo -e "${CYAN}══════════════════════════════════════════${NC}"; } + +[ "$(id -u)" -eq 0 ] || die "Run as root" + +header "TinyBoard Network Setup" + +info "Available interfaces:" +ip -o link show | awk -F': ' 'NR>1 {print " " $2}' +echo "" + +read -rp "Enter interface name to configure (e.g. wlan0, eth0, end0): " IFACE +[ -n "$IFACE" ] || die "Interface name cannot be empty" +ip link show "$IFACE" >/dev/null 2>&1 || die "Interface $IFACE not found" + +IS_WIFI=false +if [[ "$IFACE" == wl* ]]; then + IS_WIFI=true + info "Wireless interface detected." +else + info "Wired interface detected — skipping WiFi credential setup." +fi + +CURRENT_IP=$(ip -o -4 addr show "$IFACE" 2>/dev/null | awk '{print $4}' | head -1) +CURRENT_GW=$(ip route show default 2>/dev/null | awk '/default/ {print $3}' | head -1) + +echo "" +info "Current IP: ${CURRENT_IP:-none}" +info "Current gateway: ${CURRENT_GW:-none}" +echo "" + +read -rp "Set a static IP for this spoke? [Y/n]: " SET_STATIC +SET_STATIC="${SET_STATIC:-y}" + +if [[ "${SET_STATIC,,}" != "y" ]]; then + info "Keeping DHCP. No changes made." + exit 0 +fi + +header "Static IP Configuration" + +read -rp "Enter static IP with prefix (e.g. 192.168.1.69/24): " STATIC_IP +[ -n "$STATIC_IP" ] || die "IP address cannot be empty" + +DEFAULT_GW="${CURRENT_GW:-192.168.1.1}" +read -rp "Gateway [${DEFAULT_GW}]: " GATEWAY +GATEWAY="${GATEWAY:-$DEFAULT_GW}" + +read -rp "DNS servers (comma-separated) [${GATEWAY},8.8.8.8]: " DNS_INPUT +DNS_INPUT="${DNS_INPUT:-${GATEWAY},8.8.8.8}" + +DNS_YAML="" +IFS=',' read -ra DNS_LIST <<< "$DNS_INPUT" +for DNS in "${DNS_LIST[@]}"; do + DNS=$(echo "$DNS" | tr -d ' ') + DNS_YAML="${DNS_YAML} - ${DNS}\n" +done + +info "Current netplan configs:" +ls /etc/netplan/ | sed 's/^/ /' +echo "" + +NETPLAN_FILE=$(ls /etc/netplan/*.yaml 2>/dev/null | head -1) +read -rp "Netplan file to update [${NETPLAN_FILE}]: " INPUT_FILE +NETPLAN_FILE="${INPUT_FILE:-$INPUT_FILE}" +NETPLAN_FILE="${NETPLAN_FILE:-$(ls /etc/netplan/*.yaml 2>/dev/null | head -1)}" +[ -n "$NETPLAN_FILE" ] || die "No netplan file specified" + +if $IS_WIFI; then + header "WiFi Credentials" + CURRENT_SSID="" + if [ -f "$NETPLAN_FILE" ]; then + CURRENT_SSID=$(grep -A1 'access-points:' "$NETPLAN_FILE" 2>/dev/null | tail -1 | tr -d ' "' | sed 's/:$//' || true) + fi + + KEEP_WIFI="n" + if [ -n "$CURRENT_SSID" ]; then + warn "Existing WiFi config found for: $CURRENT_SSID" + read -rp "Keep existing WiFi credentials? [Y/n]: " KEEP_WIFI + KEEP_WIFI="${KEEP_WIFI:-y}" + fi + + if [[ "${KEEP_WIFI,,}" != "y" ]]; then + read -rp "WiFi SSID: " WIFI_SSID + [ -n "$WIFI_SSID" ] || die "SSID cannot be empty" + read -rsp "WiFi password: " WIFI_PASS + echo "" + [ -n "$WIFI_PASS" ] || die "Password cannot be empty" + else + WIFI_SSID="$CURRENT_SSID" + WIFI_PASS=$(grep -A2 "\"${WIFI_SSID}\"" "$NETPLAN_FILE" 2>/dev/null | grep password | awk -F': ' '{print $2}' | tr -d '"' || true) + fi +fi + +header "Writing Netplan Config" +if [ -f "$NETPLAN_FILE" ]; then + cp "$NETPLAN_FILE" "${NETPLAN_FILE}.bak" + info "Backup saved to ${NETPLAN_FILE}.bak" +fi + +if $IS_WIFI; then + cat > "$NETPLAN_FILE" < "$NETPLAN_FILE" </dev/null; then + info "Netplan config applied successfully." +else + warn "netplan try timed out or failed — applying anyway..." + netplan apply +fi + +STATIC_ADDR="${STATIC_IP%%/*}" +echo "" +echo -e "${YELLOW}══════════════════════════════════════════${NC}" +echo -e "${YELLOW} Network reconfigured.${NC}" +echo -e "${YELLOW} If you are connected via SSH, your session${NC}" +echo -e "${YELLOW} may drop. Reconnect to: ${STATIC_ADDR}${NC}" +echo -e "${YELLOW} Then run: sudo ./setup-spoke.sh${NC}" +echo -e "${YELLOW}══════════════════════════════════════════${NC}" +echo "" diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000..af23b00 --- /dev/null +++ b/setup.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' + +info() { echo -e "${GREEN}[+]${NC} $*"; } +die() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; } +header() { echo -e "\n${CYAN}══════════════════════════════════════════${NC}"; echo -e "${CYAN} $*${NC}"; echo -e "${CYAN}══════════════════════════════════════════${NC}"; } + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +header "TinyBoard Setup" +echo "" +echo " 1) Set up this device as a new spoke" +echo " 2) Onboard a new spoke from the hub" +echo "" +read -rp "Choose [1/2]: " CHOICE + +case "$CHOICE" in +1) + [ "$(id -u)" -eq 0 ] || die "Spoke setup must be run as root" + info "Starting spoke setup..." + exec "$SCRIPT_DIR/spoke/setup-spoke.sh" + ;; +2) + info "Starting hub onboarding..." + exec "$SCRIPT_DIR/hub/onboard-spoke.sh" + ;; +*) + die "Invalid choice" + ;; +esac diff --git a/setup-spoke.sh b/spoke/setup-spoke.sh similarity index 100% rename from setup-spoke.sh rename to spoke/setup-spoke.sh