User:Jchdel: Difference between revisions

From Alpine Linux
(how to select fastest uplink on a router)
mNo edit summary
 
(13 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
iptables -F INPUT
 
iptables -F OUTPUT
mount -o remount,rw /media/usb
# Did we lost all of our gateways?
 
ip route | grep -q default || \
# Let's do all downloads first!
for ((i=1; i<=$NNICS; i++))
sed -i -e '/community/s/^#//' -e '/edge/d' /etc/apk/repositories
do
apk update
ifdown ${NICS[$i]}
apk add darkhttpd nfs-utils dnsmasq syslinux
ifup ${NICS[$i]} && \
 
logger "${NICS[$i]} restarted." || \
ALPINE=alpine-netboot-3.17.3-x86_64.tar.gz
logger "Unable to restart ${NICS[$i]}."
[ -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
GWS[$i]="$(ip r | grep default | grep -v dead | grep ${NICS[$i]} | cut -d\  -f3)"
tar xf alpine-netboot-3.17.3-x86_64.tar.gz -C /tmp
[ -z "${GWS[$i]}" ] && continue
cp -r /tmp/boot/* /media/usb/tftpboot/pxelinux/
# duplicate main routing table for each live default gateway
 
ip route flush table $i
# populate HTTP server
ip route show table main | grep -Ev ^default | while read ROUTE ; do
#cd /media/usb
ip route add table $i $ROUTE
# add default apkovl.tar.gz here
done
 
# add default gateway
# configure darkhttpd
ip route add table $i default via ${GWS[$i]} dev ${NICS[$i]}
sed -i -e 's+/var/www/localhost/htdocs+/media/usb+' /etc/init.d/darkhttpd
# mark packets from localhost
lbu add /etc/init.d/darkhttpd
iptables -t mangle -A OUTPUT -s ${IPS[$i]} -j MARK --set-mark $i
 
# activate alternate routing
# populate NFS server
while $(ip rule del fwmark $i table $i);do .;done 2>/dev/null
## implicit as we publish /media/usb
ip rule add fwmark $i table $i prio ${i}0
 
# disable kernel filtering of "unwanted" packets
# configure NFS for PXE boot
echo 0 > /proc/sys/net/ipv4/conf/${NICS[$i]}/rp_filter
cat << EOF > /etc/exports
done
# /etc/exports
# activate changes in policy routing
#
ip route flush cache
# See exports(5) for a description.
# ping same target via each gateway
 
for ((i=1; i<=$NNICS; i++))
# use exportfs -arv to reread
do
/media/usb *(ro,no_root_squash,no_subtree_check)
[ -z "${GWS[$i]}" ] && continue
EOF
( ping -n -c 5 -q -I ${IPS[$i]} 1.1 >/dev/null \
 
&& logger "1.1 responded for ${IPS[$i]} dev ${NICS[$i]}" \
# configure dnsmasq for PXE boot
|| logger "No response from 1.1 for ${IPS[$i]} dev ${NICS[$i]}" ; \
cat << EOF > /etc/dnsmasq.d/stamp.conf
echo $i >> /tmp/router.order ) &
# DNS related options
done
interface=eth0
wait -n # first gateway to complete
listen-address=10.33.0.1
INDEX=$(head -1 /tmp/router.order)
listen-address=127.0.0.1
# set default router for FORWARDED packets
## uplink resolver
iptables -t mangle -A FORWARD -j MARK --set-mark $INDEX
server=1.1.1.1
# MASQUERADE or SNAT ?
# DHCP related options
iptables -t nat -I POSTROUTING -o ${NICS[$INDEX]} -j MASQUERADE #SNAT --to-source ${IPS[$INDEX]}
dhcp-range=10.33.0.1,10.33.1.254,12h
ip route flush cache # not sure this one is needed?
## push router
logger "Default route set via ${GWS[$INDEX]} dev ${NICS[$INDEX]}."
dhcp-option=option:router,10.33.0.1
wait # other gateways to complete
## push resolver
rm -f /tmp/router.order
dhcp-option=6,10.33.0.1
exit 0
# 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
</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