User:Jchdel: Difference between revisions

From Alpine Linux
m (how to select fastest uplink on a router (optimization))
mNo edit summary
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:
to be run periodically (I do it every minutes for a 3 ISP setup)
My current home/lab setup is
 
* An Alpine router x86_64 running https://github.com/jchdel/select-fastest-gateway connected to two or three different uplinks
* a switch
* a R-Pi 4 (used as usual desktop) also in 64 bits
* a tower (16 cores x86_64, 128GB RAM) running Alpine, [[openVSwitch]] and [[qemu]]-kvm
* dual 43" 4K (DP to desktop, HDMI to R-Pi 4)
 
I plan to run a Xorg desktop headless in some KVM and remotely connect to it from the R-Pi as X station...
And to drive other dev and build boxes as KVM.
 
What about https://github.com/e1z0/Framebuffer-browser on Alpine? I plan to give a try and maybe package it...
 
<pre>
<pre>
#!/bin/bash
#!/bin/sh
# This script configure the router to use fastest available gateway
set -x
# as default one. It uses some bashism...
# This script is intended to transform an Alpine Linux USB key running in
[ -f /tmp/router.order ] && logger "Already running" && exit 1
# diskless mode into a PXE boot server.
NICS=($(ip -br link|awk '{print $1}')) # index 0 is loopback (lo)
# It will run with a fixed IP 10.33.0.1 on eth0 acting as primary DHCP
NNICS=$((${#NICS[@]}-1))
# server.
GWS=()
# Only packages present in the local boot media will be available for
IPS=()
# booted boxes.
iptables -t mangle -F
 
iptables -t nat -F
set -e
# Did we lost all of our gateways?
 
ip route | grep -q default || \
mount -o remount,rw /media/usb
for ((i=1; i<=$NNICS; i++))
 
do  
# Let's do all downloads first!
ifdown ${NICS[$i]}
sed -i -e '/community/s/^#//' -e '/edge/d' /etc/apk/repositories
ifup ${NICS[$i]} && \
apk update
logger "${NICS[$i]} restarted." || \
apk add darkhttpd nfs-utils dnsmasq syslinux
logger "Unable to restart ${NICS[$i]}."
 
ALPINE=alpine-netboot-3.17.3-x86_64.tar.gz
[ -f $ALPINE ] || \
while true;do  
wget -c https://dl-cdn.alpinelinux.org/alpine/v3.17/releases/x86_64/$ALPINE \
&& break
done
done
# Prepare routing tables for each gateway
 
for ((i=1; i<=$NNICS; i++))
mkdir -p /media/usb/tftpboot/pxelinux/pxelinux.cfg
do
 
IPS[$i]="$(ip a s ${NICS[$i]}|awk '/inet/{print $2}'|cut -d/ -f1)"
# populate TFTP server
[ -z "${IPS[$i]}" ] && GWS[$i]="" && continue
rm -fr /tmp/boot
# disable kernel filtering of "unwanted" packets
tar xf alpine-netboot-3.17.3-x86_64.tar.gz -C /tmp
echo 0 > /proc/sys/net/ipv4/conf/${NICS[$i]}/rp_filter
cp -r /tmp/boot/* /media/usb/tftpboot/pxelinux/
GWS[$i]="$(ip r | grep default | grep -v dead | grep ${NICS[$i]} | cut -d\  -f3)"
 
[ -z "${GWS[$i]}" ] && continue
# populate HTTP server
# duplicate main routing table for each live default gateway
#cd /media/usb
ip route flush table $i
# add default apkovl.tar.gz here
ip route show table main | grep -Ev ^default | while read ROUTE ; do
 
ip route add table $i $ROUTE
# configure darkhttpd
done
sed -i -e 's+/var/www/localhost/htdocs+/media/usb+' /etc/init.d/darkhttpd
# add default gateway
lbu add /etc/init.d/darkhttpd
ip route add table $i default via ${GWS[$i]} dev ${NICS[$i]}
 
# mark packets from localhost
# populate NFS server
iptables -t mangle -A OUTPUT -s ${IPS[$i]} -j MARK --set-mark $i
## implicit as we publish /media/usb
# activate alternate routing
 
while $(ip rule del fwmark $i table $i);do .;done 2>/dev/null
# configure NFS for PXE boot
ip rule add fwmark $i table $i prio ${i}0
cat << EOF > /etc/exports
# MASQUERADE or SNAT ?
# /etc/exports
iptables -t nat -I POSTROUTING -o ${NICS[$i]} -j MASQUERADE #SNAT --to-source ${IPS[$i]}
#
done
# See exports(5) for a description.
# activate changes in policy routing
 
ip route flush cache
# use exportfs -arv to reread
# ping same target via each gateway
/media/usb *(ro,no_root_squash,no_subtree_check)
for ((i=1; i<=$NNICS; i++))
EOF
do
 
[ -z "${GWS[$i]}" ] && continue
# configure dnsmasq for PXE boot
( ping -n -c 5 -q -I ${IPS[$i]} 1.1 >/dev/null \
cat << EOF > /etc/dnsmasq.d/stamp.conf
&& logger "1.1 responded for ${IPS[$i]} dev ${NICS[$i]}" \
# DNS related options
|| logger "No response from 1.1 for ${IPS[$i]} dev ${NICS[$i]}" ; \
interface=eth0
echo $i >> /tmp/router.order ) &
listen-address=10.33.0.1
done
listen-address=127.0.0.1
wait -n # first gateway to complete
## uplink resolver
# meanwhile, main routing table is still active
server=1.1.1.1
INDEX=$(head -1 /tmp/router.order)
# DHCP related options
METRIC=1
dhcp-range=10.33.0.1,10.33.1.254,12h
for ((i=1; i<=$NNICS; i++))
## push router
do
dhcp-option=option:router,10.33.0.1
[ -z "${GWS[$i]}" ] && continue
## push resolver
ip route del default via ${GWS[$i]} dev ${NICS[$i]}
dhcp-option=6,10.33.0.1
done
# PXE (TFTP) related options
ip route add default via ${GWS[$INDEX]} dev ${NICS[$INDEX]} metric $METRIC
enable-tftp
echo 1 > /proc/sys/net/ipv4/ip_forward
dhcp-boot=pxelinux/pxelinux.0
logger "Default route set via ${GWS[$INDEX]} dev ${NICS[$INDEX]}."
tftp-root=/media/usb/tftpboot
wait # other gateways
EOF
cat /tmp/router.order | while read i
cp /usr/share/syslinux/pxelinux.0 /media/usb/tftpboot/pxelinux/
do
cp /usr/share/syslinux/ldlinux.c32 /media/usb/tftpboot/pxelinux/
[ $i -eq $INDEX ] && continue
cat << EOF > /media/usb/tftpboot/pxelinux/pxelinux.cfg/default
METRIC=$(($METRIC+1))
PROMPT 0
ip r a default via ${GWS[$i]} dev ${NICS[$i]} metric $METRIC
TIMEOUT 3
done
default alpine
rm -f /tmp/router.order
LABEL alpine
exit 0
LINUX vmlinuz-lts
INITRD pxerd
APPEND ip=dhcp alpine_dev=nfs:10.33.0.1:/media/usb/boot modloop=http://10.33.0.1/boot/modloop-lts nomodeset apkovl=http://10.33.0.1/stamp/default.apkovl.tar.gz alpine_repo=http://10.33.0.1/apks
EOF
# generate initramfs for PXE
if [ ! -f /media/usb/tftpboot/pxelinux/pxerd ];then
  cd /etc/mkinitfs/features.d/
  echo "kernel/drivers/net/virtio_net.ko" >> network.modules
  echo "kernel/drivers/net/ethernet/e1000/*.ko" >> network.modules
  echo "/usr/share/udhcpc/default.script" > dhcp.files
  echo "kernel/net/packet/af_packet.ko" > dhcp.modules
  echo "kernel/fs/nfs/*" > nfs.modules
  cd /etc/mkinitfs/
  echo 'features="ata base bootchart cdrom cramfs ext2 ext3 ext4 xfs floppy keymap kms raid scsi usb virtio squashfs network dhcp nfs"' > mkinitfs.conf
  mkinitfs -o /media/usb/tftpboot/pxelinux/pxerd
fi
 
# console welcome message
cat << EOF > /etc/motd
 
This a PXE server intended to deploy a fleet of diskless Alpine Linux.
 
EOF
 
cat << EOF > /etc/network/interfaces
auto lo
iface lo inet loopback
 
auto eth0
iface eth0 inet static
address 10.33.0.1
netmask 255.255.0.0
EOF
 
# force install from cache at reboot
cat << EOF > /etc/local.d/fix.start
#!/bin/sh
apk add darkhttpd
service darkhttpd start
EOF
chmod +x /etc/local.d/fix.start
 
# enable services at reboot
rc-update add local
rc-update add darkhttpd
rc-update add nfs
rc-update add dnsmasq
 
# persist changes
sync
apk cache -v sync
mount -o remount,ro /media/usb
lbu ci
 
echo "Press 'Enter' to reboot and act as PXE boot server"
echo "or 'ctrl-c' to go back to the terminal..."
read
 
reboot
</pre>
</pre>

Latest revision as of 12:39, 30 May 2023

My current home/lab setup is

I plan to run a Xorg desktop headless in some KVM and remotely connect to it from the R-Pi as X station... And to drive other dev and build boxes as KVM.

What about https://github.com/e1z0/Framebuffer-browser on Alpine? I plan to give a try and maybe package it...

#!/bin/sh
set -x
# This script is intended to transform an Alpine Linux USB key running in 
# diskless mode into a PXE boot server.
# It will run with a fixed IP 10.33.0.1 on eth0 acting as primary DHCP
# server.
# Only packages present in the local boot media will be available for 
# booted boxes.

set -e

mount -o remount,rw /media/usb

# Let's do all downloads first!
sed -i -e '/community/s/^#//' -e '/edge/d' /etc/apk/repositories
apk update
apk add darkhttpd nfs-utils dnsmasq syslinux 

ALPINE=alpine-netboot-3.17.3-x86_64.tar.gz
[ -f $ALPINE ] || \
while true;do 
	wget -c https://dl-cdn.alpinelinux.org/alpine/v3.17/releases/x86_64/$ALPINE \
		&& break
done

mkdir -p /media/usb/tftpboot/pxelinux/pxelinux.cfg

# populate TFTP server
rm -fr /tmp/boot
tar xf alpine-netboot-3.17.3-x86_64.tar.gz -C /tmp
cp -r /tmp/boot/* /media/usb/tftpboot/pxelinux/

# populate HTTP server
#cd /media/usb
# add default apkovl.tar.gz here

# configure darkhttpd
sed -i -e 's+/var/www/localhost/htdocs+/media/usb+' /etc/init.d/darkhttpd
lbu add /etc/init.d/darkhttpd

# populate NFS server
## implicit as we publish /media/usb

# configure NFS for PXE boot
cat << EOF > /etc/exports
# /etc/exports
#
# See exports(5) for a description.

# use exportfs -arv to reread
/media/usb	*(ro,no_root_squash,no_subtree_check)
EOF

# configure dnsmasq for PXE boot
cat << EOF > /etc/dnsmasq.d/stamp.conf
# DNS related options
interface=eth0
listen-address=10.33.0.1
listen-address=127.0.0.1
## uplink resolver
server=1.1.1.1
# DHCP related options
dhcp-range=10.33.0.1,10.33.1.254,12h
## push router
dhcp-option=option:router,10.33.0.1
## push resolver
dhcp-option=6,10.33.0.1
# PXE (TFTP) related options
enable-tftp
dhcp-boot=pxelinux/pxelinux.0
tftp-root=/media/usb/tftpboot
EOF
cp /usr/share/syslinux/pxelinux.0 /media/usb/tftpboot/pxelinux/
cp /usr/share/syslinux/ldlinux.c32 /media/usb/tftpboot/pxelinux/
cat << EOF > /media/usb/tftpboot/pxelinux/pxelinux.cfg/default
PROMPT 0
TIMEOUT 3
default alpine
LABEL alpine
LINUX vmlinuz-lts
INITRD pxerd
APPEND ip=dhcp alpine_dev=nfs:10.33.0.1:/media/usb/boot modloop=http://10.33.0.1/boot/modloop-lts nomodeset apkovl=http://10.33.0.1/stamp/default.apkovl.tar.gz alpine_repo=http://10.33.0.1/apks
EOF
# generate initramfs for PXE
if [ ! -f /media/usb/tftpboot/pxelinux/pxerd ];then
  cd /etc/mkinitfs/features.d/
  echo "kernel/drivers/net/virtio_net.ko" >> network.modules
  echo "kernel/drivers/net/ethernet/e1000/*.ko" >> network.modules
  echo "/usr/share/udhcpc/default.script" > dhcp.files
  echo "kernel/net/packet/af_packet.ko" > dhcp.modules
  echo "kernel/fs/nfs/*" > nfs.modules
  cd /etc/mkinitfs/
  echo 'features="ata base bootchart cdrom cramfs ext2 ext3 ext4 xfs floppy keymap kms raid scsi usb virtio squashfs network dhcp nfs"' > mkinitfs.conf
  mkinitfs -o /media/usb/tftpboot/pxelinux/pxerd
fi

# console welcome message
cat << EOF > /etc/motd

This a PXE server intended to deploy a fleet of diskless Alpine Linux.

EOF

cat << EOF > /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
	address 10.33.0.1
	netmask 255.255.0.0
EOF

# force install from cache at reboot
cat << EOF > /etc/local.d/fix.start
#!/bin/sh
apk add darkhttpd
service darkhttpd start
EOF
chmod +x /etc/local.d/fix.start

# enable services at reboot
rc-update add local
rc-update add darkhttpd
rc-update add nfs
rc-update add dnsmasq

# persist changes
sync
apk cache -v sync
mount -o remount,ro /media/usb
lbu ci

echo "Press 'Enter' to reboot and act as PXE boot server"
echo "or 'ctrl-c' to go back to the terminal..."
read

reboot