misc new stuff
[automated-distro-installer] / faiserver-setup
1 #!/bin/bash
2 # Copyright (C) 2018 Ian Kelling
3
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 x="$(readlink -f "$BASH_SOURCE")"; source "${x%/*}/bash-trace"
19
20 [[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
21
22 LC_USEBASHRC=t; . ~/.bashrc
23
24 usage() {
25 cat <<EOF
26 usage: ${0##*/} [-h|--help] [BASE_CODENAME] [ARCH]
27 install fai-server on the current machine
28
29 Initial setup of a fai server. works on localhost. Set's the current ip
30 as the tftp server. I vaguely remember that using a hostname does not
31 work. Separate from running this, faiserver needs to be setup in dns to
32 point to whatever host this is run on.
33
34 Default BASE_CODENAME is bullseye. Default ARCH is 64. The script expects corresponding
35 $BASEFILE_DIR/${UPCASED_BASE_CODENAME}${ARCH}.tar.(gz|xz) to exist, and it must have been
36 generated around the same time as the nfsroot, at least so it has the
37 same kernel version.
38
39
40 Note: there is a bug in 5.9.4, fixed by adding
41 sleep 2
42
43 Note: in t9, there is a bug in recent fai packages (eg 2021+), where
44 unshare uses a too new argument. I was able to fix it by
45 just going to the site of the error and changing unshare to
46 chroot like it used to be, but I'm not bothering to make
47 any persistent fix, since I'm now on t10. If it ever came
48 up again, using an old fai package would also work.
49
50 /usr/sbin/fai-make-nfsroot:503, before apt-get update
51
52
53 EOF
54 exit $1
55 }
56 case $1 in
57 -h|--help) usage ;;
58 esac
59
60
61 e() { echo "+ $@"; "$@"; }
62
63
64 base=${1:-bullseye}
65 arch=${2:-64}
66
67 if [[ $base == [[:upper:]] ]]; then
68 echo $0: error: use lowercase base
69 exit 1
70 fi
71
72 basefile=($BASEFILE_DIR/${base^^}${arch^^}.tar.gz)
73 sed="sed -ri --follow-symlinks"
74
75 if [[ ! -e $basefile ]]; then
76 printf "%s\n" "$0: error basefile=$basefile does not exist" >&2
77 exit 1
78 fi
79
80 if [[ ! -d $BASEFILE_DIR ]]; then
81 printf "%s\n" "$0: error BASEFILE_DIR=$BASEFILE_DIR does not exist" >&2
82 exit 1
83 fi
84
85
86 if ! type -p wget &>/dev/null; then
87 apt-get install -y wget
88 fi
89
90 armhf() {
91 [[ $(dpkg --print-architecture) == armhf ]]
92 }
93
94 # fai on ubuntu only has official support using the universe repo, but newer
95 # tends to have less bugs.
96 wget -O - https://fai-project.org/download/2BF8D9FE074BCDE4.asc | apt-key add -
97
98 update=false
99 case $base in
100 stretch|bullseye|bullseye)
101 if ! grep -qFx "deb https://fai-project.org/download $base koeln" /etc/apt/sources.list.d/fai.list; then
102 update=true
103 fi
104 cat >/etc/apt/sources.list.d/fai.list <<EOF
105 deb https://fai-project.org/download $base koeln
106 EOF
107 ;;
108 *)
109 echo "$0: error: script needs updating for new base" >&2
110 exit 1
111 ;;
112 esac
113
114 f=/var/cache/apt/pkgcache.bin;
115 if [[ -r $f ]]; then
116 cachetime=$(stat -c %Y $f );
117 now=$(date +%s)
118 limittime=$(( now - 60*60*2 ))
119 if (( cachtime > limittime )); then
120 update=true
121 fi
122 fi
123
124 if $update; then
125 apt-get update
126 fi
127
128 # Relevant packages from fai-quickstart depends and fai-server recommends.
129 # I especially do not wait isc-dhcp-server or an inetd. Also excludes
130 # nfs-kernel-server. On an android chroot, we don\'t have nfs in the
131 # kernel, or the ability to install it.
132 # xorriso is for running fai-cd -a, not strictly need for fai-server
133 # perl-tk is for fai-monitor-gui
134 # mtools is for fai-cd
135 pkgs=(fai-doc tftpd-hpa tar reprepro squashfs-tools binutils xorriso perl-tk mtools)
136 if modprobe nfsd &>/dev/null; then
137 pkgs+=(nfs-kernel-server)
138 else
139 pkgs+=(apache2)
140 fi
141
142
143 e apt-get install -y ${pkgs[@]}
144 # confnew since we edit /etc/fai/NFSROOT in an automated way
145 # fai-client is already a fai-server dependency, but make sure it gets upgraded
146 e apt-get install --no-install-recommends -y -o Dpkg::Options::=--no-force-confdef -o Dpkg::Options::=--force-confnew fai-server fai-client
147
148 r=http://http.us.debian.org/debian
149 # like default, but scrap httpredir, and nonfree.
150 # All my systems should be able to get along without nonfree
151 # for a base working system afaik.
152
153 cat >/etc/fai/apt/sources.list <<EOF
154 deb $r $base main contrib
155 EOF
156
157 ### begin setup security repo ###
158 case $base in
159 stretch|buster)
160 cat >>/etc/fai/apt/sources.list <<EOF
161 deb http://security.debian.org/debian-security $base/updates main contrib
162 EOF
163 ;;
164 *)
165 # new naming convention
166 cat >>/etc/fai/apt/sources.list <<EOF
167 deb http://security.debian.org/debian-security $base-security main contrib
168 EOF
169 esac
170 ### end setup security repo ###
171
172
173 cat >>/etc/fai/apt/sources.list <<EOF
174 # use fai repo. it's commented in the defaults. it's got bug fixes.
175 # and may contain newer packages.
176 deb http://fai-project.org/download $base koeln
177 EOF
178
179 ## Get latest kernel and btrfs for dealing with btrfs issues.
180 # if [[ $base == buster ]]; then
181 # cat >>/etc/fai/apt/sources.list <<'EOF'
182 # deb http://ftp.debian.org/debian buster-backports main
183 # EOF
184 # # note, fai doesn\'t look at /etc/fai/apt/preferences.d
185 # cat >/etc/fai/apt/preferences <<'EOF'
186 # Package: linux-* firmware-linux-free btrfs-progs
187 # Pin: release a=buster-backports
188 # Pin-Priority: 500
189 # EOF
190 # fi
191
192
193 $sed -f - /etc/fai/nfsroot.conf <<EOF
194 $ a FAI_ROOTPW='$(</q/root/shadow/standard)'
195 /^\s*FAI_ROOTPW/d
196 $ a SSH_IDENTITY=/root/.ssh/home.pub
197 /^\s*SSH_IDENTITY/d
198 s,^( *FAI_DEBOOTSTRAP=).*,\1"$base $r",
199 # add --arch amd64. this is needed on arm system which is
200 # used to install amd64 clients. On amd64 servers, it's redundant.
201 # disabled for now, since creating fai nfsroot on my arm machine
202 # is not working
203 #/--arch amd64/!s/^(\s*FAI_DEBOOTSTRAP_OPTS=")/\1--arch amd64 /
204 EOF
205
206 $sed 's/#LOGUSER/LOGUSER/' /etc/fai/fai.conf
207 $sed -i '/^LOGUSER=/d' /etc/fai/fai.conf
208 $sed -i '/^FAI_FLAGS=/d' /etc/fai/fai.conf
209 echo "FAI_FLAGS=verbose" >>/etc/fai/fai.conf
210 # note if this isnt set, the user isnt created
211 echo "LOGUSER=fai" >>/etc/fai/fai.conf
212
213 # from man fai-make-nfsroot,
214 # figured out after partitioning ignored my crypt partition
215
216
217 cedit /etc/fai/NFSROOT <<'EOF' || [[ $? == 1 ]]
218 # inserted by faserver-setup
219 PACKAGES install
220 cryptsetup
221 # default one is linux-image-server, doesnt exist anymore
222 linux-image-amd64
223 # default is btrfs-tools which doesnt exist anymore
224 btrfs-progs
225 iw
226 # got an error in error.log about not having gpg.
227 # system seemed to still install ok, so i havent tested if this fixes it.
228 gpg
229 EOF
230
231 if armhf; then
232 cd /srv/fai
233 e rm -rf nfsroot
234 e tar Jxf $basefile
235 # background: Can't build the nfsroot on my arm system now. First,
236 # fai-make-nfsroot won't work out of the box. One idea to make it work
237 # is by installing qemu-user-static, then copying qemu-x86_64-static
238 # into the nfsroot, and prepending it to chroot commands in
239 # fai-make-nfsroot, but that fails in odd ways. ls has permissions
240 # problems on reading directories, various programs segfault
241 # immediately, cat can't open a file, etc.
242
243 NFSROOT=/srv/fai/nfsroot
244 TFTPROOT=/srv/tftp/fai
245
246 # test if our copy of setup_tftp has changed in fai-make-nfsroot,
247 # and if not, run it.
248 setup_tftp(){
249
250 # tftp environment
251 local pxebin
252
253 # jessie+ path
254 pxebin=$NFSROOT/usr/lib/syslinux/pxelinux.0
255
256 rm -f $NFSROOT/boot/*.bak
257 mkdir -p $TFTPROOT/pxelinux.cfg
258 if ! chmod a+r $NFSROOT/boot/initrd.img-*; then
259 echo "$0: error: No initrd was created. Check the package name of the linux-image package in /etc/fai/NFSROOT."
260 exit 1
261 fi
262 cp -p $v $NFSROOT/boot/vmlinu?-* $NFSROOT/boot/initrd.img-* $TFTPROOT
263 cp -u $pxebin $TFTPROOT
264 if [ -f $NFSROOT/usr/lib/syslinux/modules/bios/ldlinux.c32 ]; then
265 cp -u $NFSROOT/usr/lib/syslinux/modules/bios/ldlinux.c32 $TFTPROOT
266 fi
267 if [ X$verbose = X1 ]; then
268 echo "TFTP environment prepared. Enable DHCP and start the TFTP daemon on root $TFTPROOT."
269 fi
270 }
271 diff -u <(type setup_tftp) <(cat <(sed -n '/^setup_tftp(){/,/^}/p' $(which fai-make-nfsroot) ) - <<'EOF' |bash
272 type setup_tftp
273 EOF
274 )
275 e setup_tftp
276
277 # -g causes skipping set_root_pw() in fai-make-nfsroot, -ag
278 # is the only way to make it run without chrooting. the options
279 # seem contradictory, but it works.
280 e fai-setup -evag
281
282 else # not armhf
283 # note, this copies the -B arg to
284 # /srv/fai/nfsroot/var/tmp/base.tar.xz
285 e fai-setup -evf -B $basefile
286 # fai-setup expert mode avoids writing to /var/log/fai/variables
287 # at least config_src is needed for autodiscover
288 $sed '/^FAI_CONFIGDIR|^FAI_CONFIG_SRC|^LOGUSER/d' /var/log/fai/variables
289 tee -a /var/log/fai/variables <<'EOF'
290 LOGUSER=fai
291 FAI_CONFIGDIR=/srv/fai/config
292 FAI_CONFIG_SRC=nfs://faiserver/srv/fai/config
293 EOF
294 # make the faiserver also the apt proxy server
295 apt-get -y install apt-cacher-ng
296 fi
297
298 rm -f /srv/fai/nfsroot/root/.ssh/known_hosts
299 if [[ $HOSTNAME == kd ]]; then
300 keyscan_arg="-p 8989"
301 fi
302 key=$(ssh-keyscan $keyscan_arg localhost |& grep -o "ecdsa-sha2-nistp256.*")
303 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
304 echo "$ip $key" >>/srv/fai/nfsroot/root/.ssh/known_hosts
305 done
306
307 # make it the root because pxe-kexec only looks there.
308 # It wouldn't be too hard to change if we needed.
309 # We could also just dump things in /srv/tftp, but fai
310 # has some defaults, which I don't even use, which expect
311 # the other directory, so it's kind of a tossup, whatever.
312 sed -ri 's,^ *(TFTP_DIRECTORY=).*,\1"/srv/tftp/fai",' /etc/default/tftpd-hpa
313 systemctl restart tftpd-hpa
314
315
316 # serial console
317 # mainly from
318 # https://wiki.archlinux.org/index.php/working_with_the_serial_console
319 # at runtime, running this from ssh worked:
320 # https://unix.stackexchange.com/questions/242778/what-is-the-easiest-way-to-configure-serial-port-on-linux
321 # stty -F /dev/ttyS0 115200 cs8 -cstopb -parenb
322 # /sbin/agetty 115200 ttyS0 linux
323 # dated info, but validation that this might work on debian:
324 # https://help.ubuntu.com/community/SerialConsoleHowto
325 # note in the nfsroot, systemd is not running.
326 echo "c0:2345:respawn:/sbin/agetty 115200 ttyS0 linux" >>/srv/fai/nfsroot/etc/inittab
327
328 # initially did the basic fai-chboot -Iv $std_arg default
329 # but found in console that it wanted to mount nfsroot
330 # to be the same as my dhcp server.
331 # Figured out to change the root= parameter from googling,
332 # and seeing fai-chboot -L
333 # using hostname failed.
334 # for -f, combined the 2 defaults so it will reboot and print to screen.
335
336 # Add debug to -f flag for more verbose output.
337
338
339 # background on choosing apt-cacher-ng:
340 # googling around a bit finds 2 main solutions:
341 # http://askubuntu.com/questions/3503/best-way-to-cache-apt-downloads-on-a-lan
342 # apt-cacher-ng doesn\'t have zeroconf.
343 # It touts having minimal dependencies, but I don\'t care.
344 # The downside to squid-deb-proxy is that it\'s config is for specific repos,
345 # you have to add all the repos you use.
346 # That is the main reason I use apt-cacher-ng.
347 # It has a web portal, at http://faiserver:3142/acng-report.html
348
349
350 # random fai note: as far as I can tell, profiles are just for putting
351 # in a selectable boot menu, which I don\'t want.
352
353 # the logsave prompted because the hostname faiserver was uknown.
354 # Here it was faiserver.lan when running from a faiserver vm.
355 # When running from a normal host with faiserver alias, it was the normal hosts name.
356 $sed 's/(^[^,]+,)\S+/\1faiserver/' /srv/fai/nfsroot/root/.ssh/known_hosts
357 # ditch the logo banner up top which screws with less.
358 touch /srv/fai/nfsroot/.nocolorlogo