#!/bin/bash # Copyright (C) 2018 Ian Kelling # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. x="$(readlink -f "$BASH_SOURCE")"; source "${x%/*}/bash-trace" [[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@" usage() { cat <<'EOF' usage: ${0##*/} [-h|--help] [BASE_CODENAME] [ARCH] install fai-server on the current machine Initial setup of a fai server. works on localhost. Set's the current ip as the tftp server. I vaguely remember that using a hostname does not work. Separate from running this, faiserver needs to be setup in dns to point to whatever host this is run on. Default BASE_CODENAME is bookworm. Default ARCH is 64. The script expects corresponding $BASEFILE_DIR/${UPCASED_BASE_CODENAME}${ARCH}.tar.(zst|xz) to exist, and it must have been generated around the same time as the nfsroot, at least so it has the same kernel version. for copying and running this on a remote server, scp -tPrl fai SERVER: scp $(readlink -f ~/.ssh/home.pub) SERVER:.ssh scp /a/bin/cedit/cedit SERVER:/usr/local/bin # todo: make the above key be an option Note: there is a bug in 5.9.4, fixed by adding sleep 2 Note: in t9, there is a bug in recent fai packages (eg 2021+), where unshare uses a too new argument. I was able to fix it by just going to the site of the error and changing unshare to chroot like it used to be, but I'm not bothering to make any persistent fix, since I'm now on t10. If it ever came up again, using an old fai package would also work. /usr/sbin/fai-make-nfsroot:503, before apt-get update EOF exit $1 } case $1 in -h|--help) usage ;; esac e() { echo "+ $@"; "$@"; } base=${1:-bookworm} arch=${2:-64} if [[ $base == [[:upper:]] ]]; then echo $0: error: use lowercase base exit 1 fi basefile=($BASEFILE_DIR/${base^^}${arch^^}.tar.zst) sed="sed -ri --follow-symlinks" if [[ ! -e $basefile ]]; then printf "%s\n" "$0: error basefile=$basefile does not exist" >&2 exit 1 fi if [[ ! -d $BASEFILE_DIR ]]; then printf "%s\n" "$0: error BASEFILE_DIR=$BASEFILE_DIR does not exist" >&2 exit 1 fi if ! type -p wget &>/dev/null; then apt-get install -y wget fi armhf() { [[ $(dpkg --print-architecture) == armhf ]] } # fai on ubuntu only has official support using the universe repo, but newer # tends to have less bugs. wget -O - https://fai-project.org/download/fai-project.gpg | sudo dd of=/etc/apt/trusted.gpg.d/fai-project.gpg update=false case $base in stretch|buster|bullseye|bookworm) if ! grep -qFx "deb https://fai-project.org/download $base koeln" /etc/apt/sources.list.d/fai.list; then update=true fi cat >/etc/apt/sources.list.d/fai.list <&2 exit 1 ;; esac f=/var/cache/apt/pkgcache.bin; if [[ -r $f ]]; then cachetime=$(stat -c %Y $f ); now=$(date +%s) limittime=$(( now - 60*60*2 )) if (( cachetime > limittime )); then update=true fi fi if $update; then apt-get update fi # Relevant packages from fai-quickstart depends and fai-server recommends. # I especially do not wait isc-dhcp-server or an inetd. Also excludes # nfs-kernel-server. On an android chroot, we don\'t have nfs in the # kernel, or the ability to install it. # xorriso is for running fai-cd -a, not strictly need for fai-server # perl-tk is for fai-monitor-gui # mtools is for fai-cd pkgs=(fai-doc tftpd-hpa tar reprepro squashfs-tools binutils xorriso perl-tk mtools) if modprobe nfsd &>/dev/null; then pkgs+=(nfs-kernel-server) else pkgs+=(apache2) fi e apt-get install -y ${pkgs[@]} # confnew since we edit /etc/fai/NFSROOT in an automated way # fai-client is already a fai-server dependency, but make sure it gets upgraded e apt-get install --no-install-recommends -y -o Dpkg::Options::=--no-force-confdef -o Dpkg::Options::=--force-confnew fai-server fai-client r=http://http.us.debian.org/debian # like default, but scrap httpredir, and nonfree. # All my systems should be able to get along without nonfree # for a base working system afaik. cat >/etc/fai/apt/sources.list <>/etc/fai/apt/sources.list <>/etc/fai/apt/sources.list <>/etc/fai/apt/sources.list <>/etc/fai/apt/sources.list <<'EOF' # deb http://ftp.debian.org/debian buster-backports main # EOF # # note, fai doesn\'t look at /etc/fai/apt/preferences.d # cat >/etc/fai/apt/preferences <<'EOF' # Package: linux-* firmware-linux-free btrfs-progs # Pin: release a=buster-backports # Pin-Priority: 500 # EOF # fi if [[ -s /q/root/shadow/standard ]]; then $sed -f - /etc/fai/nfsroot.conf <>/etc/fai/fai.conf # note if this isnt set, the user isnt created echo "LOGUSER=fai" >>/etc/fai/fai.conf # from man fai-make-nfsroot, # figured out after partitioning ignored my crypt partition cedit /etc/fai/NFSROOT <<'EOF' || [[ $? == 1 ]] # inserted by faserver-setup PACKAGES install cryptsetup # default one is linux-image-server, doesnt exist anymore linux-image-amd64 # default is btrfs-tools which doesnt exist anymore btrfs-progs iw # got an error in error.log about not having gpg. # system seemed to still install ok, so i havent tested if this fixes it. gpg EOF if armhf; then cd /srv/fai e rm -rf nfsroot e tar Jxf $basefile # background: Can't build the nfsroot on my arm system now. First, # fai-make-nfsroot won't work out of the box. One idea to make it work # is by installing qemu-user-static, then copying qemu-x86_64-static # into the nfsroot, and prepending it to chroot commands in # fai-make-nfsroot, but that fails in odd ways. ls has permissions # problems on reading directories, various programs segfault # immediately, cat can't open a file, etc. NFSROOT=/srv/fai/nfsroot TFTPROOT=/srv/tftp/fai # test if our copy of setup_tftp has changed in fai-make-nfsroot, # and if not, run it. setup_tftp(){ # tftp environment local pxebin # jessie+ path pxebin=$NFSROOT/usr/lib/syslinux/pxelinux.0 rm -f $NFSROOT/boot/*.bak mkdir -p $TFTPROOT/pxelinux.cfg if ! chmod a+r $NFSROOT/boot/initrd.img-*; then echo "$0: error: No initrd was created. Check the package name of the linux-image package in /etc/fai/NFSROOT." exit 1 fi cp -p $v $NFSROOT/boot/vmlinu?-* $NFSROOT/boot/initrd.img-* $TFTPROOT cp -u $pxebin $TFTPROOT if [ -f $NFSROOT/usr/lib/syslinux/modules/bios/ldlinux.c32 ]; then cp -u $NFSROOT/usr/lib/syslinux/modules/bios/ldlinux.c32 $TFTPROOT fi if [ X$verbose = X1 ]; then echo "TFTP environment prepared. Enable DHCP and start the TFTP daemon on root $TFTPROOT." fi } diff -u <(type setup_tftp) <(cat <(sed -n '/^setup_tftp(){/,/^}/p' $(which fai-make-nfsroot) ) - <<'EOF' |bash type setup_tftp EOF ) e setup_tftp # -g causes skipping set_root_pw() in fai-make-nfsroot, -ag # is the only way to make it run without chrooting. the options # seem contradictory, but it works. e fai-setup -evag else # not armhf # note, this copies the -B arg to # /srv/fai/nfsroot/var/tmp/base.tar.xz e fai-setup -evf -B $basefile # fai-setup expert mode avoids writing to /var/log/fai/variables # at least config_src is needed for autodiscover # lld /var/log/fai/remote-logs: # d 750 fai nogroup 100 08-07 08:51 pm /var/log/fai/remote-logs # We could change the group or something, but why not just give me more permissions :) e usermod -a -G nogroup iank $sed '/^FAI_CONFIGDIR|^FAI_CONFIG_SRC|^LOGUSER/d' /var/log/fai/variables tee -a /var/log/fai/variables <<'EOF' LOGUSER=fai FAI_CONFIGDIR=/srv/fai/config FAI_CONFIG_SRC=nfs://faiserver/srv/fai/config EOF # make the faiserver also the apt proxy server # apt-get -y install apt-cacher-ng fi rm -f /srv/fai/nfsroot/root/.ssh/known_hosts if [[ $HOSTNAME == kd ]]; then keyscan_arg="-p 8989" fi key=$(ssh-keyscan $keyscan_arg localhost |& grep -o "ecdsa-sha2-nistp256.*") for ip in faiserver $(ip addr show up| grep -w '^ *inet' | awk '{print $2}'| cut -d / -f 1 | grep -vF 127.0.0.1); do echo "$ip $key" >>/srv/fai/nfsroot/root/.ssh/known_hosts done # make it the root because pxe-kexec only looks there. # It wouldn't be too hard to change if we needed. # We could also just dump things in /srv/tftp, but fai # has some defaults, which I don't even use, which expect # the other directory, so it's kind of a tossup, whatever. # This means fai's example isc-dhcp-server filename directory should remove the fai/ prefix. sed -ri 's,^ *(TFTP_DIRECTORY=).*,\1"/srv/tftp/fai",' /etc/default/tftpd-hpa systemctl restart tftpd-hpa # serial console # mainly from # https://wiki.archlinux.org/index.php/working_with_the_serial_console # at runtime, running this from ssh worked: # https://unix.stackexchange.com/questions/242778/what-is-the-easiest-way-to-configure-serial-port-on-linux # stty -F /dev/ttyS0 115200 cs8 -cstopb -parenb # /sbin/agetty 115200 ttyS0 linux # dated info, but validation that this might work on debian: # https://help.ubuntu.com/community/SerialConsoleHowto # note in the nfsroot, systemd is not running. echo "c0:2345:respawn:/sbin/agetty 115200 ttyS0 linux" >>/srv/fai/nfsroot/etc/inittab # initially did the basic fai-chboot -Iv $std_arg default # but found in console that it wanted to mount nfsroot # to be the same as my dhcp server. # Figured out to change the root= parameter from googling, # and seeing fai-chboot -L # using hostname failed. # for -f, combined the 2 defaults so it will reboot and print to screen. # Add debug to -f flag for more verbose output. # background on choosing apt-cacher-ng: # googling around a bit finds 2 main solutions: # http://askubuntu.com/questions/3503/best-way-to-cache-apt-downloads-on-a-lan # apt-cacher-ng doesn\'t have zeroconf. # It touts having minimal dependencies, but I don\'t care. # The downside to squid-deb-proxy is that it\'s config is for specific repos, # you have to add all the repos you use. # That is the main reason I use apt-cacher-ng. # It has a web portal, at http://faiserver:3142/acng-report.html # random fai note: as far as I can tell, profiles are just for putting # in a selectable boot menu, which I don\'t want. # the logsave prompted because the hostname faiserver was uknown. # Here it was faiserver.lan when running from a faiserver vm. # When running from a normal host with faiserver alias, it was the normal hosts name. $sed 's/(^[^,]+,)\S+/\1faiserver/' /srv/fai/nfsroot/root/.ssh/known_hosts # ditch the logo banner up top which screws with less. touch /srv/fai/nfsroot/.nocolorlogo