Add IPv6 and VLAN devices to the web UI and router-setup
The web UI lists physical and VLAN interfaces and takes a VLAN uplink as a device name (enp2s0.1001); it has IPv6 checkboxes for the WAN and each LAN. router-setup asks whether to create VLANs before WAN and LAN are picked, and whether to enable IPv6. --config-only writes the configuration without installing, which the setup test uses for a PPPoE uplink on a VLAN. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
+74
-19
@@ -39,15 +39,17 @@ let
|
||||
];
|
||||
text = ''
|
||||
usage() {
|
||||
echo "usage: router-setup [--local FILE]" >&2
|
||||
echo "usage: router-setup [--local FILE] [--config-only DIR]" >&2
|
||||
echo " Asks a few questions, then ERASES the chosen disk and installs the router." >&2
|
||||
echo " --local FILE extra NixOS module for this box (installed as config/local.nix)" >&2
|
||||
echo " --config-only DIR only write the settings and secrets to DIR; install nothing" >&2
|
||||
exit 2
|
||||
}
|
||||
local_nix=""
|
||||
local_nix="" config_only=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
--local) shift; [ $# -gt 0 ] || usage; local_nix=$1 ;;
|
||||
--config-only) shift; [ $# -gt 0 ] || usage; config_only=$1 ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
shift
|
||||
@@ -88,6 +90,17 @@ let
|
||||
echo " please pick one of the above" >&2
|
||||
done
|
||||
}
|
||||
yes_no() { # yes_no VAR PROMPT DEFAULT(y|n)
|
||||
local yn
|
||||
while :; do
|
||||
ask yn "$2 (y/n)" "$3"
|
||||
case $yn in
|
||||
y|Y|yes) printf -v "$1" '%s' y; return ;;
|
||||
n|N|no) printf -v "$1" '%s' n; return ;;
|
||||
esac
|
||||
echo " y or n" >&2
|
||||
done
|
||||
}
|
||||
ipv4_ok() {
|
||||
[[ $1 =~ ^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$ ]] || return 1
|
||||
for o in "''${BASH_REMATCH[@]:1}"; do [ "$o" -le 255 ] || return 1; done
|
||||
@@ -100,7 +113,7 @@ let
|
||||
}
|
||||
|
||||
# Set by ask/choose (printf -v).
|
||||
disk="" wan="" lan="" wan_type="" host="" lan_address="" ssh_key="" answer=""
|
||||
disk="" wan="" lan="" wan_type="" want_vlans="" want_v6="" vlan_parent="" vlan_id="" host="" lan_address="" ssh_key="" answer=""
|
||||
webui_password="" webui_password2="" reuse="" reuse_label="" new=""
|
||||
|
||||
work=$(mktemp -d /run/router-setup.XXXXXX)
|
||||
@@ -252,34 +265,65 @@ let
|
||||
fi
|
||||
else # a new router
|
||||
|
||||
# Devices WAN and LAN can be assigned to: the NICs, plus VLANs on them.
|
||||
devices=("''${nics[@]}")
|
||||
echo
|
||||
echo "VLANs are separate networks sharing one cable: some providers deliver the internet"
|
||||
echo "tagged with a VLAN ID, and one NIC can then also serve the LAN untagged."
|
||||
yes_no want_vlans "Create VLANs now?" n
|
||||
while [ "$want_vlans" = y ]; do
|
||||
choose vlan_parent "VLAN on which interface" "''${nics[@]}"
|
||||
while :; do
|
||||
ask vlan_id "VLAN ID (1-4094)"
|
||||
[[ $vlan_id =~ ^[0-9]+$ ]] && [ "$vlan_id" -ge 1 ] && [ "$vlan_id" -le 4094 ] && break
|
||||
echo " a number from 1 to 4094" >&2
|
||||
done
|
||||
devices+=("$vlan_parent.$vlan_id VLAN $vlan_id on $vlan_parent")
|
||||
yes_no want_vlans "Another VLAN?" n
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Interface towards the internet (WAN):"
|
||||
choose wan "WAN interface" "''${nics[@]}"
|
||||
choose wan "WAN interface" "''${devices[@]}"
|
||||
echo
|
||||
echo "Interface for the local network (LAN):"
|
||||
choose lan "LAN interface" "''${nics[@]}"
|
||||
choose lan "LAN interface" "''${devices[@]}"
|
||||
|
||||
# A VLAN device is its NIC plus an ID in the settings.
|
||||
wan_dev=''${wan%.*} wan_vlan=""
|
||||
[ "$wan_dev" = "$wan" ] || wan_vlan=''${wan##*.}
|
||||
lan_dev=''${lan%.*} lan_vlan=""
|
||||
[ "$lan_dev" = "$lan" ] || lan_vlan=''${lan##*.}
|
||||
if [ "$wan" = "$lan" ]; then
|
||||
echo "router-setup: WAN and LAN cannot be the same interface" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Internet connection:"
|
||||
choose wan_type "Connection" \
|
||||
"dhcp (behind a cable modem, an ONT or another router)" \
|
||||
"pppoe (DSL or fibre with a username and password)"
|
||||
pppoe_user="" pppoe_password="" pppoe_vlan=""
|
||||
pppoe_user="" pppoe_password=""
|
||||
if [ "$wan_type" = pppoe ]; then
|
||||
while [ -z "$pppoe_user" ]; do ask pppoe_user "PPPoE username"; done
|
||||
while [ -z "$pppoe_password" ]; do ask_secret pppoe_password "PPPoE password"; done
|
||||
while :; do
|
||||
ask pppoe_vlan "VLAN ID the provider requires (empty for none)" ""
|
||||
[ -z "$pppoe_vlan" ] && break
|
||||
[[ $pppoe_vlan =~ ^[0-9]+$ ]] && [ "$pppoe_vlan" -ge 1 ] && [ "$pppoe_vlan" -le 4094 ] && break
|
||||
echo " a number from 1 to 4094" >&2
|
||||
done
|
||||
fi
|
||||
if [ "$wan" = "$lan" ] && [ -z "$pppoe_vlan" ]; then
|
||||
echo "router-setup: WAN and LAN can only share an interface when PPPoE runs on a VLAN" >&2
|
||||
if [ -n "$wan_vlan" ] && [ "$wan_type" != pppoe ]; then
|
||||
echo "router-setup: an uplink on a VLAN is only supported with PPPoE" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$wan_dev" = "$lan_dev" ] && [ -z "$wan_vlan$lan_vlan" ]; then
|
||||
echo "router-setup: WAN and LAN cannot share an interface without a VLAN" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$wan_dev" = "$lan_dev" ] && [ -z "$wan_vlan" ]; then
|
||||
echo "router-setup: with WAN and LAN on one interface, the WAN must be the VLAN" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
yes_no want_v6 "Enable IPv6 (the provider delegates a prefix to the LAN)?" y
|
||||
echo
|
||||
ask host "Host name" "router"
|
||||
while :; do
|
||||
@@ -302,7 +346,7 @@ let
|
||||
echo
|
||||
echo "Summary"
|
||||
echo " disk: $disk (will be erased)"
|
||||
echo " WAN: $wan, $wan_type''${pppoe_user:+ as $pppoe_user}''${pppoe_vlan:+ on VLAN $pppoe_vlan}"
|
||||
echo " WAN: $wan, $wan_type''${pppoe_user:+ as $pppoe_user}, IPv6 $([ "$want_v6" = y ] && echo on || echo off)"
|
||||
echo " LAN: $lan, $lan_address/24, DHCP $net.100 - $net.200"
|
||||
echo " host name: $host"
|
||||
echo " web UI: https://$lan_address"
|
||||
@@ -320,21 +364,25 @@ let
|
||||
jq -n \
|
||||
--arg host "$host" --arg state "${cfg.stateVersion}" --argjson keys "$keys" \
|
||||
--argjson schema ${toString cfg.schemaVersion} \
|
||||
--arg wan "$wan" --arg type "$wan_type" --arg user "$pppoe_user" --arg vlan "$pppoe_vlan" \
|
||||
--arg lan "$lan" --arg addr "$lan_address" --arg net "$net" '
|
||||
--arg wan "$wan_dev" --arg type "$wan_type" --arg user "$pppoe_user" --arg vlan "$wan_vlan" \
|
||||
--arg lan "$lan_dev" --arg lanvlan "$lan_vlan" --arg v6 "$want_v6" \
|
||||
--arg addr "$lan_address" --arg net "$net" '
|
||||
{
|
||||
version: $schema,
|
||||
system: { hostName: $host, stateVersion: $state, sshKeys: $keys },
|
||||
router: {
|
||||
wan: ({ interface: $wan, ipv4: { type: $type } }
|
||||
| if $type == "pppoe" then .ipv4.pppoe = ({ username: $user, passwordFile: "/var/lib/router/pppoe-password" }
|
||||
+ (if $vlan == "" then {} else { vlan: ($vlan | tonumber) } end)) else . end),
|
||||
+ (if $vlan == "" then {} else { vlan: ($vlan | tonumber) } end)) else . end
|
||||
| if $v6 == "y" then .ipv6 = { enable: true, transport: (if $type == "pppoe" then "ppp" else "native" end) } else . end),
|
||||
lans: {
|
||||
lan: {
|
||||
lan: ({
|
||||
interface: $lan, internet: true,
|
||||
ipv4: { address: $addr },
|
||||
dhcp: { pool: { start: ($net + ".100"), end: ($net + ".200") } }
|
||||
}
|
||||
+ (if $lanvlan == "" then {} else { vlan: ($lanvlan | tonumber) } end)
|
||||
+ (if $v6 == "y" then { ipv6: { pd: true } } else {} end))
|
||||
}
|
||||
}
|
||||
}' > "$config/settings.json"
|
||||
@@ -346,6 +394,13 @@ let
|
||||
(umask 077; printf '%s\n' "$webui_password" | mkpasswd -s > "$work/secrets/root-password")
|
||||
fi # new router
|
||||
|
||||
if [ -n "$config_only" ]; then
|
||||
mkdir -p "$config_only"
|
||||
cp -a "$work/secrets/." "$config_only/"
|
||||
echo "router-setup: wrote the configuration to $config_only"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo
|
||||
echo ">> building the router system (no internet needed; takes a few minutes)"
|
||||
system=$(nix build --no-link --print-out-paths --out-link "$work/system" \
|
||||
|
||||
Reference in New Issue
Block a user