<message>Modify the first-boot.sh script to include an additional step for managing screen brightness during the provisioning process. Update user-data.bootstrap to improve DNS configuration by ensuring NetworkManager manages /etc/resolv.conf correctly, and remove obsolete scripts related to systemd-resolved. Enhance documentation to reflect these changes and clarify the setup process for users, improving overall network boot functionality and user experience.
205 lines
9.9 KiB
Bash
Executable File
205 lines
9.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Setup provisioning LXC: DHCP + DNS on eth1, extra LAN IPs, VLAN eth1.40, NAT so LAN uses eth0 for internet.
|
|
# Network boot (TFTP, PXE, initrd) sections are commented out; uncomment if you need PXE/netboot.
|
|
# Run inside the LXC (as root), or from your machine: ./setup-network-boot-on-lxc.sh root@10.130.60.141 [SUBNET]
|
|
# SUBNET optional: A.B.C.D/PREFIX (e.g. 10.100.1.1/24). When run with ssh target, writes lan-subnet.conf on LXC if SUBNET given.
|
|
# When run with ssh target, rsyncs lxc/ and runs this script inside the container. Subnet is read from /opt/cm4-provisioning/lan-subnet.conf.
|
|
|
|
set -e
|
|
TARGET="${1:-}"
|
|
SUBNET_ARG="${2:-}"
|
|
|
|
if [[ -n "$TARGET" ]]; then
|
|
# Run remotely: sync lxc/ and script, then execute inside LXC
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
|
echo "Syncing lxc config and script to $TARGET ..."
|
|
rsync -a "$REPO_DIR/lxc/" "$TARGET:/tmp/cm4-network-boot-lxc/" --exclude='.git'
|
|
# Network boot: copy initrd.img for TFTP
|
|
# if [[ -f "$REPO_DIR/network-boot-initramfs/initrd.img" ]]; then
|
|
# echo "Copying initrd.img to $TARGET ..."
|
|
# scp "$REPO_DIR/network-boot-initramfs/initrd.img" "$TARGET:/tmp/cm4-network-boot-lxc/initrd.img"
|
|
# else
|
|
# echo "Note: network-boot-initramfs/initrd.img not found (run build.sh first); skipping."
|
|
# fi
|
|
scp "$SCRIPT_DIR/setup-network-boot-on-lxc.sh" "$TARGET:/tmp/cm4-network-boot-lxc/setup.sh"
|
|
# If SUBNET_ARG given, write lan-subnet.conf on LXC so inner script uses the set subnet
|
|
if [[ -n "$SUBNET_ARG" ]]; then
|
|
if [[ "$SUBNET_ARG" =~ ^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/([0-9]+)$ ]]; then
|
|
LAN_GW="${BASH_REMATCH[1]}"
|
|
PREFIX="${BASH_REMATCH[2]}"
|
|
BASE_3="${LAN_GW%.*}"
|
|
LAN_CIDR="${BASE_3}.0/${PREFIX}"
|
|
DHCP_RANGE_START="${BASE_3}.100"
|
|
DHCP_RANGE_END="${BASE_3}.200"
|
|
ssh "$TARGET" "mkdir -p /opt/cm4-provisioning && echo 'LAN_GW=$LAN_GW' > /opt/cm4-provisioning/lan-subnet.conf && echo 'LAN_CIDR=$LAN_CIDR' >> /opt/cm4-provisioning/lan-subnet.conf && echo 'DHCP_RANGE_START=$DHCP_RANGE_START' >> /opt/cm4-provisioning/lan-subnet.conf && echo 'DHCP_RANGE_END=$DHCP_RANGE_END' >> /opt/cm4-provisioning/lan-subnet.conf"
|
|
echo "Wrote lan-subnet.conf on LXC (LAN_GW=$LAN_GW, DHCP ${DHCP_RANGE_START}-${DHCP_RANGE_END})."
|
|
else
|
|
echo "Warning: SUBNET must be A.B.C.D/PREFIX (e.g. 10.100.1.1/24); ignoring '$SUBNET_ARG'."
|
|
fi
|
|
fi
|
|
ssh "$TARGET" "bash /tmp/cm4-network-boot-lxc/setup.sh"
|
|
echo "Done."
|
|
exit 0
|
|
fi
|
|
|
|
# --- Running inside the LXC from here ---
|
|
# LAN subnet: use /opt/cm4-provisioning/lan-subnet.conf (written by deploy-to-proxmox.sh or passed as SUBNET when running remotely)
|
|
# Optional first arg when running locally: A.B.C.D/PREFIX to set/write lan-subnet.conf
|
|
LAN_CONF="/opt/cm4-provisioning/lan-subnet.conf"
|
|
if [[ "$1" =~ ^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/([0-9]+)$ ]]; then
|
|
LAN_GW="${BASH_REMATCH[1]}"
|
|
PREFIX="${BASH_REMATCH[2]}"
|
|
BASE_3="${LAN_GW%.*}"
|
|
LAN_CIDR="${BASE_3}.0/${PREFIX}"
|
|
DHCP_RANGE_START="${BASE_3}.100"
|
|
DHCP_RANGE_END="${BASE_3}.200"
|
|
mkdir -p /opt/cm4-provisioning
|
|
echo "LAN_GW=$LAN_GW" > "$LAN_CONF"
|
|
echo "LAN_CIDR=$LAN_CIDR" >> "$LAN_CONF"
|
|
echo "DHCP_RANGE_START=$DHCP_RANGE_START" >> "$LAN_CONF"
|
|
echo "DHCP_RANGE_END=$DHCP_RANGE_END" >> "$LAN_CONF"
|
|
echo "Using set subnet: $LAN_CIDR (gateway $LAN_GW), DHCP ${DHCP_RANGE_START}-${DHCP_RANGE_END}."
|
|
elif [[ -f "$LAN_CONF" ]]; then
|
|
source "$LAN_CONF"
|
|
else
|
|
LAN_GW="10.20.50.1"
|
|
LAN_CIDR="10.20.50.0/24"
|
|
DHCP_RANGE_START="10.20.50.100"
|
|
DHCP_RANGE_END="10.20.50.200"
|
|
echo "No lan-subnet.conf and no SUBNET argument; using defaults: $LAN_CIDR."
|
|
fi
|
|
echo "Configuring LAN (DHCP + DNS on eth1, NAT via eth0) — LAN $LAN_CIDR (gateway $LAN_GW), DHCP ${DHCP_RANGE_START}-${DHCP_RANGE_END} ..."
|
|
|
|
# 1) Install dnsmasq and vlan (for eth1.40)
|
|
if ! command -v dnsmasq >/dev/null 2>&1; then
|
|
apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq dnsmasq
|
|
fi
|
|
if ! command -v vconfig >/dev/null 2>&1; then
|
|
apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq vlan
|
|
fi
|
|
|
|
# 2) dnsmasq config: DHCP on eth1 only; DNS on all interfaces (no bind-interfaces/listen-address).
|
|
# PXE/TFTP in network-boot-pxe.conf when needed (toggle-network-boot-dhcp.sh)
|
|
mkdir -p /etc/dnsmasq.d
|
|
cat > /etc/dnsmasq.d/network-boot.conf << DNSMASQ
|
|
# DHCP on eth1 only; DNS on all interfaces (eth0, eth1, eth1.40, etc.)
|
|
interface=eth1
|
|
dhcp-range=${DHCP_RANGE_START},${DHCP_RANGE_END},12h
|
|
# DNS: file.server resolves to this host (eth1) so scripts can use http://file.server/...
|
|
address=/file.server/${LAN_GW}
|
|
# Explicitly send this host as DNS server to DHCP clients (option 6) so they use LXC DNS and resolve file.server
|
|
dhcp-option=6,${LAN_GW}
|
|
# Other DNS queries forwarded via LXC's resolv.conf
|
|
log-dhcp
|
|
log-queries
|
|
DNSMASQ
|
|
mkdir -p /opt/cm4-provisioning
|
|
# Network boot: install toggle script and enable PXE/TFTP
|
|
# if [ -f /tmp/cm4-network-boot-lxc/toggle-network-boot-dhcp.sh ]; then
|
|
# cp /tmp/cm4-network-boot-lxc/toggle-network-boot-dhcp.sh /opt/cm4-provisioning/
|
|
# chmod +x /opt/cm4-provisioning/toggle-network-boot-dhcp.sh
|
|
# /opt/cm4-provisioning/toggle-network-boot-dhcp.sh enable
|
|
# fi
|
|
|
|
# 3) Network boot: TFTP root — fetch Raspberry Pi 4 boot files from GitHub if missing
|
|
# mkdir -p /srv/tftpboot
|
|
# if [[ ! -f /srv/tftpboot/start4cd.elf ]]; then
|
|
# echo "Fetching Raspberry Pi firmware boot files from GitHub ..."
|
|
# if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1; then
|
|
# apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq curl
|
|
# fi
|
|
# tmpdir=$(mktemp -d)
|
|
# trap "rm -rf $tmpdir" EXIT
|
|
# if command -v curl >/dev/null 2>&1; then
|
|
# curl -sL "https://github.com/raspberrypi/firmware/archive/refs/heads/master.tar.gz" -o "$tmpdir/firmware.tar.gz"
|
|
# else
|
|
# wget -q -O "$tmpdir/firmware.tar.gz" "https://github.com/raspberrypi/firmware/archive/refs/heads/master.tar.gz"
|
|
# fi
|
|
# tar xzf "$tmpdir/firmware.tar.gz" -C "$tmpdir"
|
|
# cp -a "$tmpdir/firmware-master/boot/." /srv/tftpboot/
|
|
# rm -rf "$tmpdir"
|
|
# echo "Copied RPi boot files to /srv/tftpboot"
|
|
# else
|
|
# echo "TFTP root already has boot files (start4cd.elf present), skipping fetch."
|
|
# fi
|
|
|
|
# 3b) Network boot: copy provisioning initrd.img to TFTP root if provided
|
|
# if [[ -f /tmp/cm4-network-boot-lxc/initrd.img ]]; then
|
|
# cp /tmp/cm4-network-boot-lxc/initrd.img /srv/tftpboot/initrd.img
|
|
# echo "Copied initrd.img to /srv/tftpboot"
|
|
# if [[ -f /srv/tftpboot/config.txt ]] && ! grep -q 'initramfs initrd.img' /srv/tftpboot/config.txt 2>/dev/null; then
|
|
# echo "" >> /srv/tftpboot/config.txt
|
|
# echo "# Provisioning initramfs (network-boot-initramfs)" >> /srv/tftpboot/config.txt
|
|
# echo "initramfs initrd.img followkernel" >> /srv/tftpboot/config.txt
|
|
# echo "Added initramfs line to config.txt"
|
|
# fi
|
|
# fi
|
|
|
|
# 4) Extra LAN IPs on eth1 (192.168.30.1, 192.168.127.1) and VLAN eth1.40 (192.168.0.1/24)
|
|
EXTRA_LAN_CONF="/etc/network/interfaces.d/70-cm4-extra-lan"
|
|
if [[ -f /tmp/cm4-network-boot-lxc/70-cm4-extra-lan ]]; then
|
|
mkdir -p /etc/network/interfaces.d
|
|
cp /tmp/cm4-network-boot-lxc/70-cm4-extra-lan "$EXTRA_LAN_CONF"
|
|
# Ensure main interfaces includes interfaces.d (Debian)
|
|
if [[ -f /etc/network/interfaces ]] && ! grep -q 'interfaces.d' /etc/network/interfaces 2>/dev/null; then
|
|
echo 'source /etc/network/interfaces.d/*' >> /etc/network/interfaces
|
|
fi
|
|
# Apply immediately: secondary IPs on eth1
|
|
ip addr add 192.168.30.1/24 dev eth1 2>/dev/null || true
|
|
ip addr add 192.168.127.1/24 dev eth1 2>/dev/null || true
|
|
# Create and bring up eth1.40 (VLAN 40)
|
|
ip link add link eth1 name eth1.40 type vlan id 40 2>/dev/null || true
|
|
ip addr add 192.168.0.1/24 dev eth1.40 2>/dev/null || true
|
|
ip link set eth1.40 up 2>/dev/null || true
|
|
echo "Extra LAN: eth1 + 192.168.30.1/24, 192.168.127.1/24; eth1.40 192.168.0.1/24 (persisted in $EXTRA_LAN_CONF)"
|
|
fi
|
|
|
|
# 5) IP forwarding (LAN clients use WAN)
|
|
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-cm4-network-boot.conf
|
|
sysctl -p /etc/sysctl.d/99-cm4-network-boot.conf 2>/dev/null || sysctl -w net.ipv4.ip_forward=1
|
|
|
|
# 6) NAT: primary LAN + extra LAN subnets + VLAN 40 -> eth0 (masquerade)
|
|
# Subnets: primary (from lan-subnet.conf), 192.168.30.0/24, 192.168.127.0/24, 192.168.0.0/24 (eth1.40)
|
|
if command -v nft >/dev/null 2>&1; then
|
|
mkdir -p /etc/nftables.d
|
|
cat > /etc/nftables.d/nat-lan.conf << NFT
|
|
table ip nat {
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip saddr ${LAN_CIDR} oifname "eth0" masquerade
|
|
ip saddr 192.168.30.0/24 oifname "eth0" masquerade
|
|
ip saddr 192.168.127.0/24 oifname "eth0" masquerade
|
|
ip saddr 192.168.0.0/24 oifname "eth0" masquerade
|
|
}
|
|
}
|
|
NFT
|
|
if ! nft list table ip nat 2>/dev/null | grep -q postrouting; then
|
|
nft -f /etc/nftables.d/nat-lan.conf
|
|
else
|
|
nft -f /etc/nftables.d/nat-lan.conf
|
|
fi
|
|
# Ensure main config includes our drop-in (Debian)
|
|
if [[ -f /etc/nftables.conf ]] && ! grep -q 'nftables.d/nat-lan' /etc/nftables.conf 2>/dev/null; then
|
|
echo 'include "/etc/nftables.d/nat-lan.conf"' >> /etc/nftables.conf
|
|
fi
|
|
echo "NAT rules added (nftables): ${LAN_CIDR}, 192.168.30.0/24, 192.168.127.0/24, 192.168.0.0/24 -> eth0"
|
|
else
|
|
# Fallback iptables
|
|
for cidr in "${LAN_CIDR}" 192.168.30.0/24 192.168.127.0/24 192.168.0.0/24; do
|
|
iptables -t nat -C POSTROUTING -s "$cidr" -o eth0 -j MASQUERADE 2>/dev/null || \
|
|
iptables -t nat -A POSTROUTING -s "$cidr" -o eth0 -j MASQUERADE
|
|
done
|
|
echo "NAT rules added (iptables) for primary LAN and extra subnets."
|
|
fi
|
|
|
|
# 7) Enable and start dnsmasq
|
|
systemctl enable dnsmasq
|
|
systemctl restart dnsmasq
|
|
|
|
echo "Setup done."
|
|
echo " - DHCP + DNS on eth1 ($LAN_GW), range ${DHCP_RANGE_START}-${DHCP_RANGE_END}"
|
|
echo " - NAT: ${LAN_CIDR}, 192.168.30.0/24, 192.168.127.0/24, 192.168.0.0/24 -> eth0 (internet)"
|
|
echo " - Extra LAN: eth1 also 192.168.30.1, 192.168.127.1; eth1.40 192.168.0.1/24 (VLAN 40)"
|
|
# echo " - TFTP root: /srv/tftpboot (RPi boot files; initrd.img if provided)" # when network boot enabled
|