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