dnsmasq (on a openwrt machine) for dhcp instead of the isc
dhcp. fai-wrapper is a small script to use basic fai classes outside of
fai. It does not use the fai partitioning tool, but the script is
-inspired from it and works outside of fai.
+inspired from it and works outside of fai. It supports running a fai
+server on debian within android via Maru.
It also automates configuration of an openwrt router after manual
initial installation.
faiserver-revm # using pxe & preseed, create a vm which is a fai server
faiserver-uninstall # uninstall fai-server
faiserver-setup # install fai-server on the current machine
-myfai-chboot # setup fai server for kexec, for use instead of "pxe-server"
-pxe-server # disable/enable fai or arch pxe boot server
+myfai-chboot # setup fai tftp and nfs. useful with pxe-kexec
+pxe-server # disable/enable pxe dhcp, tfp, and nfs
wrt-setup-remote # setup my router in general: dhcp, dns, etc.
(( $# >= 1 )) || { echo "$0: error: need 1 or 2 arguments"; exit 1; }
-mv /root/devbyid /usr/bin
-
rm -f /etc/pacman.d/mirrorlist
# https://wiki.archlinux.org/index.php/Mirrors#Sorting_mirrors
pacstrap /mnt base
cp /tmp/fai/{fstab,crypttab} /mnt/etc
cp /a/bin/fai/encrypt /mnt/usr/lib/initcpio/hooks
-# not needed anymore
-#cp /usr/bin/devbyid /mnt/root
cp -r /root/.ssh /mnt/root
rsync -rlpthvi --relative /a/bin/fai/ root@$host:/
rsync /a/bin/fai/ root@$host:/a/bin/fai/
-sudo scp -r /a/bin/fai/devbyid /q/root/luks /q/root/shadow root@$host:
+sudo scp -r /q/root/luks /q/root/shadow root@$host:
# creating shadow file string:
# on debian, you can use mkpasswd -m sha-512 to generate a pass.
# arch doesn't have this program. instead, you can do passwd,
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
host=$1
-addr=$(host $host | sed -rn 's/^.*has address (.*)/\1/p;T;q')
+addr=$(host $host | sed -rn 's/^\S+ has address //p;T;q')
h=$(host $addr)
h=${h##* }
echo ${h%%.*}
+++ /dev/null
-#!/bin/bash
-
-# input eg: /dev/sda1 or /dev/sda
-# output: /dev/disk/by-id/model+serial, or if no link exists, the same as input
-
-short_dev=$1
-
-# devices are identified by model+serial num,
-# and wwn. model+serial gives me more info, so use that.
-shopt -s extglob
-for id in /dev/disk/by-id/!(wwn*); do
- [[ -e $id ]] || break # if we matched nothing
- if [[ $(readlink -f $id) == "$short_dev" ]]; then
- printf '%s\n' "$id"
- exit
- fi
-done
-# a vm may not have a by-id link.
-printf '%s\n' "$short_dev"
--- /dev/null
+fai/config/distro-install-common/devbyid
\ No newline at end of file
usage() {
cat <<EOF
-usage: ${0##*/} [-h|--help]
-Deploy fai configuration to host "faiserver"
+usage: ${0##*/} [-h|--help] [HOST]
+Deploy fai config (the one in nfs) to HOST or default faiserver
EOF
exit $1
}
-h|--help) usage ;;
esac
+host=${1:-faiserver}
+
# i use faiserver as a dns alias, but ssh key is associated with
# a canonical hostname and we will have ssh warning spam unless we
# use it, so look it up just to avoid the warning spam.
-faiserver_host=$(chost faiserver) || faiserver_host=faiserver
+faiserver_host=$(chost $host) || faiserver_host=$host
-shopt -s extglob
-ssh root@$faiserver_host rm -rf /srv/fai/config/!(basefiles)
-scp -qr fai/config root@$faiserver_host:/srv/fai
+rsync -rl --delete --relative --exclude /fai/config/basefiles/ fai/config root@$faiserver_host:/srv
scp -q ~/.ssh/id_rsa.pub \
# should tar ssh all the files, but these ones really justified it
tar -cz /p/c/machine_specific/*/filesystem/etc/ssh | \
ssh root@$faiserver_host tar -xz -C /srv/fai/config/distro-install-common
-scp -q /a/bin/fai/devbyid root@$faiserver_host:/srv/fai/nfsroot/usr/local/bin
# built BELANOS basefile with mk-basefile -J BELENOS64. it's stored in
sums[$file]=$sum
done < <(cat /a/bin/fai-basefiles/md5sums.txt)
-curl -s http://fai-project.org/download/basefiles/md5sums.txt |
+{ timeout 2 curl -s http://fai-project.org/download/basefiles/md5sums.txt ||:; } |
while read -r sum file; do
if [[ ${sums[$file]} && ${sums[$file]} != $sum ]]; then
echo "${0##*/}: WARNING!!!!!!!!! NEW UPSTREAM BASEFILE: $file"
fi
done
-scp -q /a/bin/fai-basefiles/*.tar.xz root@$faiserver_host:/srv/fai/config/basefiles
+rsync -r --delete /a/bin/fai-basefiles/basefiles root@$faiserver_host:/srv/fai/config
ssh root@$faiserver_host bash <<'EOF'
set -eE -o pipefail
set -x
#cd /srv/fai/config/basefiles
#u=http://fai-project.org/download/basefiles/XENIAL64.tar.xz
#wget -nv -N $u
-EOF
+changed=false
+f=/srv/fai/nfsroot/root/.ssh/known_hosts
+# the known hosts entries that fai already sets up are like
+# IP,HOSTNAME key_info...
+# we are skipping the ip, because it doesn't block ssh
+# with a prompt as long as you have the user supplied hostname,
+# and i don't want to deal with getting it, it's not adding
+# any important security in this case.
+if ! grep -xFq "$line" $f; then
+ changed=true
+ printf "%s\n" "$line" >>$f
+fi
+
+if ! modprobe nfsd &>/dev/null; then
+ # no apt-cache on maru debian, because we are low on space already
+ sed -i '/^ *APTPROXY=/d' /srv/fai/config/class/DEBIAN.var
+ # maru debian doesn't have loopback devs created
+ if ! losetup -f; then
+ shopt -s nullglob
+ x=(/dev/loop*)
+ minor=0
+ if (( ${#x[@]} )); then
+ minor=$(( ${x[-1]#/dev/loop} + 1 ))
+ fi
+ mknod -m660 /dev/loop$minor b 7 $minor
+ losetup -f
+ fi
+ # -B boo only iso, no nfsroot, no paritial miorr, no config space.
+ # -f = force, for overwriting
+ # -S = make squash image for http booting
+ # -d config space url, instead of putting it in the squash.img,
+ # this just makes it so that we don't have to regenerate the img
+ # when the config changes.
+ cd /srv/fai/config
+ tar czf /var/www/faiserver/html/config.tar.gz .
+ if $changed || [[ ! -e /var/www/faiserver/html/squash.img ]]; then
+ # note, on maru, selinux needs to be disabled in android before
+ # this will work.
+ mount
+ export debug=true
+ fai-cd -d http://faiserver:8080/config.tar.gz -f -M -S /var/www/faiserver/html/squash.img
+ mount
+ fi
+fi
+EOF
fails. Just run again if that happens.
-r Do not boot after install is complete
--n Create new qcow2(s) for vm
+-n Create new qcow2(s) for vm. Good for testing partitioning
+ script, to ensure a blank disk.
-h|--help Print help and exit.
Note: Uses GNU getopt options parsing style
FAI_RAMDISKS="$target/var/lib/dpkg $target/var/cache"
# if you want to use the faiserver as APT proxy
-# uncommented from upstream
+# ian: uncommented
APTPROXY=http://faiserver:3142
# remotely.
LOGUSER=fai
+
+# when downloading from https intead of nfs, this is not set,
+# it is used as the default for LOGSERVER, and for calling chboot.
+# My faiserver's hostname is always faiserver, so just hardcoding it.
+SERVER=faiserver
\ No newline at end of file
--- /dev/null
+#!/bin/bash
+
+# input eg: /dev/sda1 or /dev/sda
+# output: /dev/disk/by-id/model+serial, or if no link exists, the same as input
+
+short_dev=$1
+
+# devices are identified by model+serial num,
+# and wwn. model+serial gives me more info, so use that.
+shopt -s extglob
+for id in /dev/disk/by-id/!(wwn*); do
+ [[ -e $id ]] || break # if we matched nothing
+ if [[ $(readlink -f $id) == "$short_dev" ]]; then
+ printf '%s\n' "$id"
+ exit
+ fi
+done
+# a vm may not have a by-id link.
+printf '%s\n' "$short_dev"
# because it will wait for too long when we don't have a network
# connection. So, we wait for 10 seconds.
# ref: https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
- try-kexec
+ try-kexec ||:
else
return 0
fi
swap-cryptdev() { crypt-dev $(swapdev $@); }
root-cryptname() { crypt-name $(rootdev $@); }
swap-cryptname() { crypt-name $(swapdev $@); }
+devbyid() {
+ local f
+ for f in $FAI/distro-install-common/devbyid \
+ /a/bin/fai/fai/config/distro-install-common/devbyid; do
+ if [[ -e $f ]]; then $f "$@"; fi
+ done
+}
##### end function defs
usage 1
fi
-ssh root@$(chost faiserver) "sed -ri --follow-symlinks '\%^/srv/fai/d' /etc/exports; exportfs -ra"
+ssh root@$(chost faiserver) bash <<'EOF'
+if modprobe nfsd &>/dev/null; then
+ sed -ri --follow-symlinks '\%^/srv/fai/d' /etc/exports
+ exportfs -ra
+else
+ rm -f /etc/apache2/sites-enabled/faiserver.conf
+ systemctl reload apache2
+fi
+EOF
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.
+
+For running on arm, it expects Ian's fai-basefiles repository at
+/a/bin/fai-basefiles
+
EOF
exit $1
}
e() { echo "$@"; "$@"; }
# When stretch becomes stable, change this to stretch.
-# I've tested this with stretch, it works, but notably,
+# I\'ve tested this with stretch, it works, but notably,
# the automatic basefile getting will be for stretch
# instead of jessie, so if you install jessie, you need
-# to setup the basefile and it's corresponding class.
+# to setup the basefile and it\'s corresponding class.
base=jessie
sed="sed -ri --follow-symlinks"
+if ! type -p wget &>/dev/null; then
+ apt-get install -y wget
+fi
+
+armhf() {
+ [[ $(dpkg --print-architecture) == armhf ]]
+}
+
if grep -xFq 'VERSION="9 (stretch)"' /etc/os-release; then
# if we use stretch, no need for fai-project repo.
# this will need to be updated when there is a codename
# for stretch+1
rm -f /etc/apt/sources.list.d/fai.list
+elif armhf; then
+ if apt-cache policy | grep o=Debian,a=testing,n=stretch &>/dev/null; then
+ cat >/etc/apt/sources.list.d/testing.list <<'EOF'
+deb http://http.us.debian.org/debian testing main contrib non-free
+deb-src http://http.us.debian.org/debian testing main contrib non-free
+
+deb http://security.debian.org/ testing/updates main contrib non-free
+deb-src http://security.debian.org/ testing/updates main contrib non-free
+
+deb http://http.us.debian.org/debian testing-updates main contrib non-free
+deb-src http://http.us.debian.org/debian testing-updates main contrib non-free
+EOF
+
+ cat >/etc/apt/preferences.d/fai <<'EOF'
+Package: fai-server fai-client fai-doc
+Pin: release a=testing
+Pin-Priority: 500
+
+Package: *
+Pin: release a=testing
+Pin-Priority: -10
+EOF
+ fi
else
wget -O - http://fai-project.org/download/074BCDE4.asc | apt-key add -
cat >/etc/apt/sources.list.d/fai.list <<'EOF'
apt-get update
# Relevant packages from fai-quickstart depends and fai-server recommends.
-# I especially do not wait isc-dhcp-server or an inetd
-apt-get install -y fai-doc nfs-kernel-server tftpd-hpa tar reprepro squashfs-tools binutils
+# 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.
+pkgs=(fai-doc tftpd-hpa tar reprepro squashfs-tools binutils)
+if modprobe nfsd &>/dev/null; then
+ pkgs+=(nfs-kernel-server)
+else
+ pkgs+=(apache2)
+fi
+
+
+apt-get install -y ${pkgs[@]}
apt-get install --no-install-recommends -y fai-server
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.
-dd of=/etc/fai/apt/sources.list <<EOF
+cat >/etc/fai/apt/sources.list <<EOF
deb $r $base main contrib
deb http://security.debian.org/debian-security $base/updates main contrib
EOF
if [[ $base == jessie ]]; then
- tee -a /etc/fai/apt/sources.list <<'EOF'
+ cat >>/etc/fai/apt/sources.list <<'EOF'
# uncommenting this from the defaults. it's got bug fixes.
# repository that may contain newer fai packages for jessie
deb http://fai-project.org/download jessie koeln
deb http://ftp.debian.org/debian jessie-backports main
EOF
- # note, fai doesn't look at /etc/fai/apt/preferences.d
+ # note, fai doesn\'t look at /etc/fai/apt/preferences.d
cat >/etc/fai/apt/preferences <<'EOF'
Package: tar
Pin: release a=jessie-backports
# tried out a stretch base, doesn't work yet.
+#
$sed -f - /etc/fai/nfsroot.conf <<EOF
s,^( *FAI_DEBOOTSTRAP=).*,\1"$base $r",
+# add --arch amd64. this is needed on arm system which is
+# used to install amd64 clients. On amd64 servers, it's redundant.
+# disabled for now, since creating fai nfsroot on my arm machine
+# is not working
+#/--arch amd64/!s/^(\s*FAI_DEBOOTSTRAP_OPTS=")/\1--arch amd64 /
EOF
$sed 's/#LOGUSER/LOGUSER/' /etc/fai/fai.conf
if ! grep cryptsetup /etc/fai/NFSROOT &>/dev/null; then
$sed '/^PACKAGES install$/a cryptsetup' /etc/fai/NFSROOT
fi
-e fai-setup -e -vf
+
+if armhf; then
+ cd /srv/fai
+ rm -rf nfsroot
+ tar Jxf /a/bin/fai-basefiles/base.tar.xz
+ # 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
+
+ # wheezy path
+ if [ -f $NFSROOT/usr/lib/PXELINUX/pxelinux.0 ]; then
+ pxebin=$NFSROOT/usr/lib/PXELINUX/pxelinux.0
+ else
+ # jessie/stretch path
+ pxebin=$NFSROOT/usr/lib/syslinux/pxelinux.0
+ fi
+
+ rm -f $NFSROOT/boot/*.bak
+ mkdir -p $TFTPROOT/pxelinux.cfg
+ chmod a+r $NFSROOT/boot/initrd.img-* || die 9 "No initrd was created. Check the package name of the linux-image package in /etc/fai/NFSROOT."
+ 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
+)
+ 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.
+ fai-setup -evag
+
+else
+ e fai-setup -e -vf
+ # make the faiserver also the apt proxy server
+ apt-get -y install apt-cacher-ng
+fi
+
{ head -n 1 /srv/fai/nfsroot/root/.ssh/known_hosts | awk '{print $1}' \
- | tr '\n' ' '; ssh-keyscan localhost | grep -o "ecdsa-sha2-nistp256.*"; \
+ | tr '\n' ' '; ssh-keyscan localhost |& grep -o "ecdsa-sha2-nistp256.*"; \
} >>/srv/fai/nfsroot/root/.ssh/known_hosts
# initially did the basic fai-chboot -Iv $std_arg default
# Add debug to -f flag for more verbose output.
-# make the faiserver also the apt proxy server
-apt-get -y install apt-cacher-ng
# 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,
+# 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.
+# 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.
cat <<EOF
usage: ${0##*/} [-h|--help] [hostname|ip]
-Sets up tftp pxe config and nfs config on host "faiserver". Argument
-sets the host to enable it for. No argument disables pxe config for all
-hosts, but leaves nfs server alone. Use faiserver-disable to disable
-the nfs server.
+Sets up tftp pxe config and nfs server on host "faiserver".
+
+If our kernel has no nfs support, uses apache, and depends on another
+repo of Ian Kelling, basic-https-conf, where the file is at
+/a/exe/apache-site.
+
+Usng this, you can boot into fai with pxe-kexec without changing
+the dhcp server.
+
+Argument sets the host to enable it for. No argument disables pxe
+config for all hosts, but leaves nfs server alone. Use faiserver-disable
+to disable the nfs server.
+
EOF
exit $1
}
e() { echo "$@"; "$@"; }
-
-rm -f /srv/tftp/fai/pxelinux.cfg/*
-if [[ ! $1 ]]; then
- exit 0
-fi
-
host=$1
-ip=$(getent hosts $host | awk '{print $1}')
-std_arg="-u nfs://faiserver/srv/fai/config"
-e fai-chboot -Iv $std_arg default # set it to default to get a val out of it next
-kernel=$(fai-chboot -L '^default$' | awk '{print $3}')
-# man page doesn't explain this, but this deletes & thus disables
-# all chboot systems.
type -t host &>/dev/null || apt-get -y install dnsutils
+ip=$(host $host | sed -rn 's/^\S+ has address //p;T;q')
gateway_ip=$(route -n | sed -rn 's/^0\.0\.0\.0\s+(\S+).*/\1/p')
-my_ip=$(host faiserver $gateway_ip | sed -rn 's/^\S+ has address //p')
-k_args=$(fai-chboot -L '^default$' | \
- sed -r "s/^(\S+\s+){3}(.*root=)(.*)/\2$my_ip:\3/")
-rm -f /srv/tftp/fai/pxelinux.cfg/*
-e fai-chboot -k "$k_args" -v -f verbose,sshd,createvt,reboot $std_arg $kernel "$host"
+my_ip=$(host faiserver $gateway_ip | sed -rn 's/^\S+ has address //p;T;q')
-# fai-setup without -e sets the ip to the local_ip/local_network, eg 192.168.1.3/24
-# I restrict it to one ip as simple but imperfect access control.
-sed -ri --follow-symlinks '\%^/srv/fai/%d' /etc/exports
-cat >>/etc/exports <<EOF
+if modprobe nfsd &>/dev/null; then
+ std_arg="-u nfs://faiserver/srv/fai/config"
+ root_arg="$my_ip:/srv/fai/nfsroot"
+ # fai-setup without -e sets the ip to the local_ip/local_network, eg 192.168.1.3/24
+ # I restrict it to one ip as simple but imperfect access control.
+ sed -ri --follow-symlinks '\%^/srv/fai/%d' /etc/exports
+ cat >>/etc/exports <<EOF
/srv/fai/config $ip/32(async,ro,no_subtree_check)
/srv/fai/nfsroot $ip/32(async,ro,no_subtree_check,no_root_squash)
EOF
-exportfs -ra
+ exportfs -ra
+else
+ std_arg="-u http://faiserver:8080/config.tar.gz"
+ root_arg="live:http://faiserver:8080/squash.img"
+ /a/exe/apache-site -i -p 8080 - faiserver <<EOF
+<Location />
+ Deny from all
+ Allow from $ip
+</Location>
+EOF
+fi
+
+rm -f /srv/tftp/fai/pxelinux.cfg/*
+if [[ ! $1 ]]; then
+ exit 0
+fi
-# todo, remove the nopxe script. adjust fai-check to reboot if it fails on the kexec.
+# man page doesn't explain this, but this deletes & thus disables
+# all chboot systems.
+e fai-chboot -Iv $std_arg default # set it to default to get a val out of it next
+kernel=$(fai-chboot -L '^default$' | awk '{print $3}')
+default_k_args=$(fai-chboot -L '^default$' | \
+ sed -r "s/^(\S+\s+){3}(.*)/\2/")
+# example of default_k_args
+# initrd=initrd.img-3.16.0-4-amd64 ip=dhcp root=192.168.1.3:/srv/fai/nfsroot aufs FAI_CONFIG_SRC=nfs://faiserver/srv/fai/config FAI_ACTION=install
+
+k_args=()
+for arg in $default_k_args; do
+ case $arg in
+ # default root arg is /srv/fai/nfsroot
+ root=*) k_args+=(root=$root_arg) ;;
+ *) k_args+=($arg) ;;
+ esac
+done
+rm -f /srv/tftp/fai/pxelinux.cfg/*
+e fai-chboot -k "${k_args[*]}" -v -f verbose,sshd,createvt,reboot $std_arg $kernel "$host"