various fixes and initial focal support
authorIan Kelling <iank@fsf.org>
Thu, 14 May 2020 22:34:38 +0000 (18:34 -0400)
committerIan Kelling <iank@fsf.org>
Thu, 14 May 2020 22:34:38 +0000 (18:34 -0400)
14 files changed:
README
fai/config/class/50-host-classes
fai/config/distro-install-common/end
fai/config/files/boot/chboot/DEFAULT
fai/config/files/etc/apt/preferences.d/etiona-bionic/ETIONA
fai/config/files/etc/apt/preferences.d/etiona-focal/ETIONA [new file with mode: 0644]
fai/config/files/etc/apt/sources.list.d/focal.list/ETIONA [new file with mode: 0644]
fai/config/hooks/instsoft.DEFAULT
fai/config/hooks/partition.DEFAULT
fai/config/scripts/GRUB_PC/11-iank
mymk-basefile
pxe-server
wrt-setup
wrt-setup-local

diff --git a/README b/README
index 5aa71ee3087031afa502928481507b9e8f2f3b13..5dd5d3df4bae069724be8c98f2469fcc2897e999 100644 (file)
--- a/README
+++ b/README
@@ -203,6 +203,50 @@ Operation failed: No such file or directory
   settings.
 
 
+# ubuntu notes
+
+For someone who really needed ubuntu on host tp, otherwise they would
+end up on a non-gnu os, and I didn't want to figure out how to get all
+the default software installed, I did the following:
+
+# On remote host:
+# install etiona
+cd /b/fai
+# set 51-multi-boot to set classes outside of fai-wrapper conditional, including NOWIPE
+. fai-wrapper
+./fai/config/hooks/partition.DEFAULT
+
+# on local host
+# install ubuntu 20.04 using virt-install
+s virt-install --os-variant=ubuntu16.04 --cdrom ubuntu-20.04-desktop-amd64.iso --disk path=u2004.qcow2 -r 2048 --vcpus 1 -n u2004
+sudo qemu-img create -o preallocation=metadata -f qcow2 u2004.qcow2 15G
+modprobe nbd
+qemu-nbd --connect=/dev/nbd0 u2004.qcow2 -f qcow2
+s mount /dev/nbd0p5 /mnt/1
+s rsync -avhSAXP --numeric-ids /mnt/1/ root@tp:/mnt/root/root_ubuntubionic
+
+# on remote host:
+# mount boot and root to /mnt/1
+sudo -i
+cd /mnt/1
+cp /tmp/fai/crypttab etc
+cp /tmp/fstab etc
+chrbind
+chroot .
+# install programs from /a/bin/fai/fai/config/package_config/STANDARD:
+apt install openssh-client openssh-server cryptsetup keyutils btrfs-progs console-setup kbd pciutils usbutils unattended-upgrades initramfs-tools-core dropbear-initramfs
+exit
+# install authorized keys in dropbear and .ssh folder
+chroot .
+grub-install --no-floppy $(grub-probe -tdrive -d /dev/sda3)
+update-grub
+grub-bios-setup -d /boot/grub/i386-pc -s /dev/sda
+exit
+umount proc
+umount dev
+umount sys
+reboot
+
 
 # TODO
 Change arch to archlike and to support arch and parabola
index ef0c7815477961582cc7ad29f31d870916c461c1..9f4f8a6b85142eef2d23e6236659dbbd52e8fcf4 100755 (executable)
@@ -23,7 +23,7 @@
 # Debian stable basefile gets built by faisetup and gets used otherwise.
 # With X suffix, means it has gone through the dirinstall process and has eXtra
 # things installed, to speed up installation.
-# STRETCH64, BUSTER64, XENIAL64, FLIDAS64, FLIDAS64BIG, ETIONA64
+# STRETCH64, BUSTER64, XENIAL64, FLIDAS64, FLIDAS64BIG, ETIONA64, BIONIC64, FOCAL64
 #
 # The distro subvol name, we can add as many of these as we want:
 # VOL_TESTING, VOL_STRETCH, VOL_BUSTER, VOL_XENIAL, VOL_FLIDAS,
@@ -32,7 +32,7 @@
 #
 # The apt sources files we want, STRETCH_FREE, STRETCH_NONFREE,
 # BUSTER_FREE, BUSTER_NONFREE, TESTING_FREE, TESTING_NONFREE,
-# XENIAL_FREE, FLIDAS, ETIONA, STRETCH_LINODE.
+# XENIAL_FREE, BIONIC, FOCAL, FLIDAS, ETIONA, STRETCH_LINODE.
 #
 # It's all a little redundant in some cases, but it keeps things
 # simpler.
@@ -88,6 +88,10 @@ if [[ ! -e /a/bin/fai/fai-wrapper || $FAI_ACTION == dirinstall ]]; then
         _) echo DEBIAN STRETCH64 VOL_TESTING TESTING_FREE ;;
         # xenial
         _) echo UBUNTU XENIAL64 VOL_XENIAL XENIAL_FREE ;;
+        # bionic
+        _) echo UBUNTU BIONIC64 VOL_BIONIC BIONIC ;;
+        # focal
+        _) echo UBUNTU FOCAL64 VOL_FOCAL FOCAL ;;
     esac
 fi
 ###### end Template for 51-multi-boot ######
index 1fd8ca6a778cfcba6bb13c0d3ffc9ceba67be740..e764c32ea67367e21a887e518926694071f999d3 100755 (executable)
@@ -19,14 +19,10 @@ if [[ -e $src && -e $dst ]]; then
 fi
 
 USER2PW=/q/root/shadow/user2
-if ifclass ziva; then
-  ROOTPW=/q/root/shadow/ziva
-else
-  # if doesn't exist, we dont set one
-  ROOTPW=/q/root/shadow/standard
-  if [[ ! -e $ROOTPW ]]; then
-    ROOTPW=/q/root/shadow/$HOSTNAME
-  fi
+# if doesn't exist, we dont set one
+ROOTPW=/q/root/shadow/standard
+if [[ ! -e $ROOTPW ]]; then
+  ROOTPW=/q/root/shadow/$HOSTNAME
 fi
 
 chpw() {
index 7800764614737e4e871caca7d3f23a1514e4f6b9..7c89c471ea4c220927db3158a7dd7fa14a00c25e 100755 (executable)
@@ -110,7 +110,7 @@ fi
 
 e() { echo "$@"; "$@"; }
 
-for boot_dev in $(btrfs fil show $mnt | sed -nr 's#.*path\s+(\S+)$#\1#p'); do
+for boot_dev in $(btrfs fil show $mnt | sed -nr 's#.*path\s+(\S+)$#\1#p'); do
 
   mount_point=$(mktemp -d)
 
@@ -129,7 +129,6 @@ e mount $boot_disk$grub_extn $mount_point
 e grub-editenv $mount_point/grubenv set last_boot=/$distro
 e grub-editenv $mount_point/grubenv set did_fai_check=true
 e umount $mount_point
-y
 if $reboot; then
   touch /tmp/keyscript-off
   reboot now
index 02d579b4a4ef5e4200c90d380ba8e2c0dd53fe3f..4790bbe37b74f15c31d34c4cc03c48b508ec8ab8 100644 (file)
@@ -1,3 +1,3 @@
 Package: *
-Pin: release n=bionic
+Pin: release n=bionic,o=Ubuntu
 Pin-Priority: -100
diff --git a/fai/config/files/etc/apt/preferences.d/etiona-focal/ETIONA b/fai/config/files/etc/apt/preferences.d/etiona-focal/ETIONA
new file mode 100644 (file)
index 0000000..1e6fc34
--- /dev/null
@@ -0,0 +1,3 @@
+Package: *
+Pin: release n=focal,o=Ubuntu
+Pin-Priority: -100
diff --git a/fai/config/files/etc/apt/sources.list.d/focal.list/ETIONA b/fai/config/files/etc/apt/sources.list.d/focal.list/ETIONA
new file mode 100644 (file)
index 0000000..a4d6395
--- /dev/null
@@ -0,0 +1,6 @@
+deb http://us.archive.ubuntu.com/ubuntu/ focal main universe
+deb http://us.archive.ubuntu.com/ubuntu/ focal-updates main universe
+deb http://us.archive.ubuntu.com/ubuntu/ focal-security main universe
+deb-src http://us.archive.ubuntu.com/ubuntu/ focal main universe
+deb-src http://us.archive.ubuntu.com/ubuntu/ focal-updates main universe
+deb-src http://us.archive.ubuntu.com/ubuntu/ focal-security main universe
index bdcaab13fe2b39ee1831c1b72dd2991dbbddff9e..8e9c7e579a915d9d59958cf5e49efe4d6ac18d4c 100755 (executable)
@@ -23,7 +23,7 @@ chmod 700 $f
 if ifclass demohost; then
   files=(/var/lib/fai/config/distro-install-common/luks/host-demohost)
 elif ifclass tp; then
-  files=(/var/lib/fai/config/distro-install-common/luks/host-{tp,demohost})
+  files=(/var/lib/fai/config/distro-install-common/luks/host-tp)
 fi
 if [[ ${files[0]}  ]]; then
   d=$target/q/root/luks
index b961e62ed2d7f98055204bfd1b0bd42066960fa8..0a0c2ad69946535a624c74d0ce3f7443ad69671c 100755 (executable)
@@ -44,6 +44,8 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 # REPARTITION: forces repartitioning even if we detect the proper amount
 # of partitions already exist.
 #
+# NOWIPE: use existing subvolumes if they exist
+#
 # ROTATIONAL: forces to install onto hdds instead of sdds. normally sdds
 # are chosen if they exist.
 #
@@ -134,11 +136,16 @@ swap-cryptname() { crypt-name $(swapdev $@); }
 
 ##### end function defs
 
-if ifclass REPARTITION;then
+if ifclass REPARTITION; then
   partition=true # force a full wipe
 else
   partition=false # change to true to force a full wipe
 fi
+if ifclass NOWIPE; then
+  wipe=false
+else
+  wipe=true
+fi
 
 ## ignore disks that are mounted, eg when running from fai-cd
 declare -A disk_excludes
@@ -297,6 +304,10 @@ if [[ ! $DISTRO ]]; then
     DISTRO=debiantesting
   elif ifclass VOL_XENIAL; then
     DISTRO=ubuntuxenial
+  elif ifclass VOL_BIONIC; then
+    DISTRO=ubuntubionic
+  elif ifclass VOL_FOCAL; then
+    DISTRO=ubuntufocal
   elif ifclass VOL_BELENOS; then
     DISTRO=trisquelbelenos
   elif ifclass VOL_FLIDAS; then
@@ -320,36 +331,33 @@ bpart() { # btrfs a partition
 }
 
 
-# see README for docs about how to create these
-luks_dir=$FAI/distro-install-common/luks
-
+if [[ ! -e /a/bin/fai/fai-wrapper ]]; then
+  # see README for docs about how to create these
+  luks_dir=$FAI/distro-install-common/luks
+
+  luks_file=$luks_dir/host-$HOSTNAME
+  if [[ ! -e $luks_file ]]; then
+    hostkeys=($luks_dir/host-*)
+    # if there is only one key, we might be deploying somewhere
+    # where dhcp doesnt give us a proper hostname, so use that.
+    if [[ ${#hostkeys[@]} == 1 && -e ${hostkeys[0]} ]]; then
+      luks_file=${hostkeys[0]}
+    else
+      echo "$0: error: no key for hostname at $luks_file" >&2
+      exit 1
+    fi
+  fi
 
-luks_file=$luks_dir/host-$HOSTNAME
-if [[ ! -e $luks_file ]]; then
-  hostkeys=($luks_dir/host-*)
-  # if there is only one key, we might be deploying somewhere
-  # where dhcp doesnt give us a proper hostname, so use that.
-  if [[ ${#hostkeys[@]} == 1 && -e ${hostkeys[0]} ]]; then
-    luks_file=${hostkeys[0]}
+  # # note, corresponding changes in /b/ds/keyscript-{on,off}
+  if ifclass demohost; then
+    lukspw=x
+  elif [[ -e $luks_dir/$HOSTNAME ]]; then
+    lukspw=$(cat $luks_dir/$HOSTNAME)
   else
-    echo "$0: error: no key for hostname at $luks_file" >&2
-    exit 1
+    lukspw=$(cat $luks_dir/iank)
   fi
 fi
 
-# # note, corresponding changes in /b/ds/keyscript-{on,off}
-if ifclass tpnew; then
-  lukspw=$(cat $luks_dir/traci)
-elif ifclass ziva; then
-  lukspw=$(cat $luks_dir/ziva)
-elif ifclass demohost; then
-  lukspw=x
-elif [[ -e $luks_dir/$HOSTNAME ]]; then
-  lukspw=$(cat $luks_dir/$HOSTNAME)
-else
-  lukspw=$(cat $luks_dir/iank)
-fi
-
 
 first_root_crypt=$(root-cryptdev ${devs[0]})
 
@@ -487,7 +495,7 @@ if $partition; then
   bpart ${boot_devs[@]}
 else
   for dev in ${devs[@]}; do
-    if [[ -e /a/bin/fai/fai-wrapper && -e /dev/mapper/$(root-cryptname) ]]; then
+    if [[ -e /dev/mapper/$(root-cryptname) ]]; then
       continue
     fi
     cryptsetup luksOpen $(rootdev) $(root-cryptname) \
@@ -497,7 +505,7 @@ else
 fi
 
 
-if [[ $DISTRO != debianstretch_bootstrap ]]; then
+if $wipe && [[ $DISTRO != debianstretch_bootstrap ]]; then
   # bootstrap distro doesn't use separate encrypted root.
   mount -o subvolid=0 $first_root_crypt /mnt
   # systemd creates subvolumes we want to delete.
@@ -541,8 +549,12 @@ if [[ $DISTRO == debianstretch_bootstrap ]]; then
 else
   boot_vol=boot_$DISTRO
 fi
-[[ ! -e /mnt/$boot_vol ]] || btrfs subvolume delete /mnt/$boot_vol
-btrfs subvolume create $boot_vol
+if $wipe; then
+  if [[ -e /mnt/$boot_vol ]]; then
+    btrfs subvolume delete /mnt/$boot_vol
+  fi
+  btrfs subvolume create $boot_vol
+fi
 cd /
 umount /mnt
 ## end create subvols ##
@@ -570,10 +582,11 @@ $first_boot_dev  /boot  btrfs        nofail,noatime,subvol=$boot_vol  0 0
 $first_boot_dev  /mnt/boot  btrfs    nofail,noatime,subvolid=0  0 0
 EOF
   swaps=()
+  rm -f /tmp/fai/crypttab
   for dev in ${devs[@]}; do
     swaps+=($(swap-cryptname))
     cat >>/tmp/fai/crypttab <<EOF
-$(root-cryptname)  $(rootdev)  none  keyscript=/root/keyscript,discard,luks,initramfs
+$(root-cryptname) $(rootdev)  none  keyscript=/root/keyscript,discard,luks,initramfs
 $(swap-cryptname) $(swapdev)  /dev/urandom  swap,cipher=aes-xts-plain64,size=256,hash=ripemd160
 EOF
     cat >> /tmp/fai/fstab <<EOF
index 852e03a648947bb0b9724b1c3bab575bc2faeae0..d8fb48dc5120cf49dbfe8dd2c5ec3bb0916329c7 100755 (executable)
@@ -19,18 +19,7 @@ if [[ -e /a/bin/fai/fai-wrapper ]]; then
   }
 fi
 
-chroot $FAI_ROOT bash <<'EOFOUTER'
-set -eE -o pipefail
-if getent group systemd-journal >/dev/null; then
-  # makes the journal be saved to disk.
-  mkdir -p /var/log/journal
-  chmod 755 /var/log/journal
-fi
-debconf-set-selections <<EOF
-kexec-tools kexec-tools/load_kexec boolean false
-EOF
-apt-get install -y pxe-kexec
-EOFOUTER
+
 
 # -r = recursive
 # -i = ignore non-matching class warnings, always exit 0
@@ -80,7 +69,20 @@ if [[ ! -r $f ]] || (( $(( $(date +%s) - $(stat -c %Y $f ) )) > 60*60*2 )); then
 fi
 
 
-chroot $FAI_ROOT bash <<'EOF'
+
+#### misc configurations
+chroot $FAI_ROOT bash <<'EOFOUTER'
+if getent group systemd-journal >/dev/null; then
+  # makes the journal be saved to disk.
+  mkdir -p /var/log/journal
+  chmod 755 /var/log/journal
+fi
+debconf-set-selections <<EOF
+kexec-tools kexec-tools/load_kexec boolean false
+EOF
+apt-get install -y pxe-kexec
+
+
 #### begin .ssh setup ###
 set -x
 set -eE -o pipefail
@@ -104,15 +106,14 @@ sudo -u iank mkdir -p $d
 sudo -u iank ln -sf /usr/lib/systemd/user/ssh-agent.service $d
 #### end .ssh setup ###
 
-### duplicated in ssh-emacs-setup
+
+## duplicated in ssh-emacs-setup
 # done here so its setup earlier for convenience
 line='AcceptEnv INSIDE_EMACS BRC COLUMNS'
 f=/etc/ssh/sshd_config
 grep -xFq "$line" $f || tee -a $f <<<"$line"
 
 
-
-
 # default jessie groups + kvm, systemd-journal, adm
 for g in adm cdrom floppy sudo audio dip video plugdev netdev; do
   if getent gropu $g >/dev/null; then
@@ -129,12 +130,10 @@ fi
 # that a normal user can disrupt the system, eg cause a reboot.
 sed -i '$a kernel.sysrq=1
 /^kernel.sysrq=/d' /etc/sysctl.conf
-EOF
+EOFOUTER
 
 
 if [[ $FAI_ACTION != dirinstall ]]; then
-
-
   # luks options, see man systemd-cryptsetup-generator
   # all i know is that with luks.crypttab=no, swap still timed out on boot.
   # and with rd.luks.crypttab=no, it works.
@@ -179,7 +178,7 @@ sed -i '/^ *GRUB_HIDDEN_TIMEOUT/d' /etc/default/grub
 
 update-grub2
 EOF
-fi # end != dirinstall
+fi ##### end != dirinstall
 
 
 # reading through the groups that iank is in but user2 isn't,
@@ -188,7 +187,8 @@ for g in plugdev audio video cdrom; do
 done
 
 
-## begin network setup
+
+###### begin network setup ####
 
 # use old names. the idea of them changing between boots has never
 # happened to me and I usually only have 1 wired or other type.
@@ -262,5 +262,4 @@ systemctl disable systemd-networkd.socket systemd-networkd networkd-dispatcher s
 systemctl mask systemd-networkd.socket systemd-networkd networkd-dispatcher systemd-networkd-wait-online
 EOF
 
-
-## end network setup
+##### end network setup  #####
index d2b4328792fd3f53129c80dc6093f164e6cb796f..61cfe998d2e1ccc911976e25f84f8ea56ca12b92 100755 (executable)
@@ -59,4 +59,7 @@ if [[ $BASEFILE_DIR ]]; then
   cd $BASEFILE_DIR
 fi
 
+if awk '$2 == "/tmp" && $4 ~ /nodev/' /proc/mounts | grep -q . || [[ $? == 141 ]]; then
+  $s mount -o remount,dev /tmp
+  fi
 $s $script_dir/fai/config/basefiles/mk-basefile "$@"
index 6ca453c56790d6ad02939e867541819f9ef760f1..d40751e811ffb90601854d14eda312bc92694bfb 100755 (executable)
@@ -134,7 +134,7 @@ archlike() {
   cat <<EOF
 ${host_tag}209,boot/syslinux/${type}iso.cfg
 ${host_tag}210,/${type}/
-${host_tag}bootfile-name,/${type}/boot/syslinux/lpxelinux.0
+${host_tag}option:bootfile-name,/${type}/boot/syslinux/lpxelinux.0
 EOF
 }
 
@@ -142,15 +142,15 @@ plain() {
   # if arch based was used before, this additionally needs
   # the tftp link in /mnt/usb to be changed.
   cat <<EOF
-${host_tag}bootfile-name,pxelinux.0
+${host_tag}option:bootfile-name,pxelinux.0
 EOF
 }
 
 fai() {
   cat <<EOF
-${host_tag}bootfile-name,pxelinux.0
-${host_tag}server-ip-address,$faiserverip
-${host_tag}tftp-server,$faiserverip
+${host_tag}option:bootfile-name,pxelinux.0
+${host_tag}option:server-ip-address,$faiserverip
+${host_tag}option:tftp-server,$faiserverip
 EOF
   # Note, previously used normal dnsmasq option, but it requires dnsmasq
   # restart, which causes momentary dns failures, which can bork an
index e6e5f284509e5999e58cabe217ef497cf6f595f1..3c572f29b3ef49f95a92ea277e2a01d746ea26b8 100755 (executable)
--- a/wrt-setup
+++ b/wrt-setup
@@ -59,7 +59,8 @@ cat ~/.ssh/home.pub | ssh $h dd of=/etc/dropbear/authorized_keys 2>/dev/null
 scp /a/work/libremanage/libremanage /a/bin/fai/wrt-setup-local /a/bin/cedit/cedit $h:/usr/bin
 # relay is built for openwrt 18.06.2, r7676-cddd7b4c77
 sudo scp /q/root/shadow/router /p/c/machine_specific/wrt/etc/dropbear/dropbear_rsa_host_key \
-     /a/opt/openwrt/source/bin/packages/mips_24kc/mypackages/relay_1.0-1_mips_24kc.ipk $h:
+     /a/opt/openwrt/source/bin/packages/mips_24kc/mypackages/relay_1.0-1_mips_24kc.ipk \
+     /p/c/machine_specific/wrt/etc/wg.{key,psk} $h:
 scp ../openwrtkeyring/usign/* $h:/etc/opkg/keys
 
 ssh $h <<EOFOUTER
index 642c1935150c17dd756a08740f8ed4d94a5c1f04..b8d36e02b2bd6bd23b29366945db079a939156c3 100755 (executable)
@@ -212,6 +212,7 @@ cat /root/router >>/etc/shadow
 uset system.@system[0].ttylogin 1
 
 
+
 cat >/usr/bin/archlike-pxe-mount <<'EOFOUTER'
 #!/bin/bash
 # symlinks are collapsed for nfs mount points, so use a bind mount.
@@ -408,18 +409,38 @@ EOF
 #         option config /etc/openvpn/client.conf
 # EOF
 
+wgip4=10.3.0.1/24
+wgip6=fdfd::1/64
+wgport=26000
 
 
 v cedit /etc/config/network <<EOF || v /etc/init.d/network reload
 config 'route' 'transmission'
-        option 'interface' 'lan'
-        option 'target' '10.173.0.0'
-        option 'netmask' '255.255.0.0'
-        option 'gateway' '$l.3'
+ option 'interface' 'lan'
+ option 'target' '10.173.0.0'
+ option 'netmask' '255.255.0.0'
+ option 'gateway' '$l.3'
+
+option interface 'wg0'
+ option proto 'wireguard'
+ option private_key '$(cat /root/wg.key)'
+ option listen_port $wgport
+ list addresses '10.3.0.1/24'
+ list addresses 'fdfd::1/64'
+
+# tp
+config wireguard_wg0 'wgclient'
+ option public_key '3q+WJGrm85r59NgeXOIvppxoW4ux/+koSw6Fee1c1TI='
+ option preshared_key '$(cat /root/wg.psk)'
+ list allowed_ips '10.3.0.2/24'
+ list allowed_ips 'fdfd::2/64'
 EOF
 
+
 firewall_restart=false
-v cedit /etc/config/firewall <<EOF || firewall_restart=true
+
+firewall-cedit() {
+  v cedit /etc/config/firewall <<EOF
 
 config redirect
  option name ssh
@@ -499,6 +520,13 @@ config rule
  option target           ACCEPT
  option dest_port        2220
 
+config rule
+ option name wg
+ option src              wan
+ option target           ACCEPT
+ option dest_port        $wgport
+ option proto            udp
+
 
 config redirect
  option name vpntp
@@ -595,23 +623,31 @@ config rule
  option target ACCEPT
  option family ipv6
 
-
 EOF
-
-
+}
+firewall-cedit || firewall_restart=true
+
+if ! uci get firewall.@zone[1].network | grep wg0 &>/dev/null; then
+  # cant mix cedit plus uci
+  echo | cedit /etc/config/firewall ||:
+  uci add_list firewall.@zone[1].network=wg0
+  uci commit firewall
+  firewall-cedit ||:
+  firewall_restart=true
+fi
 
 
 dnsmasq_restart=false
 v cedit /etc/hosts <<EOF || dnsmasq_restart=true
 127.0.1.1 $hostname
-$l.1 $hostname
+$l.1 $hostname b8.nz
 $l.2 kd faiserver
 $l.3 frodo
 $l.4 wrt2
 $l.5 x2
 $l.6 demohost
 #$l.7 x3
-$l.8 tp b8.nz
+$l.8 tp
 $l.9 bb8
 $l.14 wrt3
 2600:3c00::f03c:91ff:fe6d:baf8 li