#!/bin/bash
# Setup Ian's computers
# Copyright (C) 2024 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 3 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, see .
# SPDX-License-Identifier: GPL-3.0-or-later
#### for setting up a new machine
# usage: $0 [-r] [HOSTNAME]
# HOSTNAME changes the machine's hostname
# Update target_down alerts in
# /a/bin/ds/filesystem/etc/prometheus/rules/iank.yml
#
# Update hostnames in /b/ds/check-remote-mailqs
# Update hostnames in /b/ds/machine_specific/*.hosts /p/c/machine_specific/*.hosts
# Update hostnames in this file
### end new machine setup
# tips:
# run any sudo command first so your pass is cached
# set the scrollback to unlimited in case something goes wrong
# send to registrar, glue records:
# for iankelling.org:
# ns1.iankelling.org 72.14.176.105
# ns1.iankelling.org 2600:3c00::f03c:91ff:fe6d:baf8
# ns2.iankelling.org 172.105.84.95
# ns2.iankelling.org 2a01:7e01::f03c:91ff:feb5:baec
# for zroe.org:
# ns1.zroe.org 72.14.176.105
# ns1.zroe.org 2600:3c00::f03c:91ff:fe6d:baf8
# ns2.zroe.org 172.105.84.95
# ns2.zroe.org 2a01:7e01::f03c:91ff:feb5:baec
#
####### begin setup environment #######
# shellcheck disable=SC2317 # false positive
### make ssh interactive shell run better. for when running line interactively line by line
sudo bash -c '/a/exe/ssh-emacs-setup' || exit $?
##### setup error handling
interactive=true # set this to false to force set -x
[[ $- == *i* ]] || interactive=false
if ! $interactive; then
set -x
fi
source /a/bin/bash-bear-trap/bash-bear
mkdir -p ~/.local
err-cleanup() {
echo 1 >~/.local/distro-begin
}
source /a/bin/distro-functions/src/package-manager-abstractions
### setup logging
echo "$0: $(date): starting now)"
### sanity checking
if [[ $EUID == 0 ]]; then
if getent passwd iank || getent passwd ian ; then
echo "$0: error: running as root. unprivileged user exists. use it."
exit 1
else
echo "$0: warning: running as root. I will setup users then exit"
fi
fi
### arg parsing
recompile=false
emacs=false
if [[ -e /a/opt/emacs ]]; then
emacs=true
fi
while [[ $1 == -* ]]; do
case $1 in
-r) recompile=true; shift ;;
-e) emacs=false; shift ;;
esac
done
if [[ $1 ]]; then
export HOSTNAME=$1
fi
##### variables/env setup
script_dir="$(readlink -f "${BASH_SOURCE[@]}")"; script_dir=${script_dir%/*}
# shellcheck source=./pkgs
source $script_dir/pkgs
set +x
source /a/bin/distro-functions/src/identify-distros
$interactive || set -x
for f in kd x2 x3 x8 frodo tp li bk je demohost kw sy bo so; do
eval "$f() { [[ $HOSTNAME == $f ]]; }"
done
codename=$(debian-codename)
bitfolk() { je || bk; }
has_wayland() { has_monitor && [[ $codename == buster ]]; }
has_x() { has_monitor && [[ $codename != buster ]]; }
has_monitor() { ! vps ; }
vps() { bitfolk || li; }
# linode actually has btrfs now, but we dont do anything with it.
has_btrfs() { ! vps; }
home_network() { ! vps && ! tp; }
has_p() { ! vps && ! tp; }
encrypted() { ! bitfolk; }
shopt -s extglob
export GLOBIGNORE="*/.:*/.."
umask 022
PATH="/a/exe:$PATH"
sed="sed --follow-symlinks"
####### end setup environment #######
##### begin setup encryption scripts ######
if encrypted; then
# I tried making a service which was dependent on reboot.target,
# but it happened too late in the shutdown process.
sudo dd of=/etc/systemd/system/keyscripton.service <<'EOF'
[Unit]
Description=keyscripton
# This is triggered by reboot and when keyscriptoff stops.
# tried using graphical.target, but it made my display manager restart before rebooting.
# generally, I don't think targets order shutdown like they do startup.
# So, I did systemd-analyze plot > something.svg, and picked a reliably started
# service that happens late in the game.
After=ntp.service
DefaultDependencies=no
# not sure if needed, makes sure we shut down before reboot.target
Conflicts=reboot.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecStop=/a/exe/keyscript-on
[Install]
WantedBy=keyscriptoff.service
EOF
sudo systemctl daemon-reload # needed if the file was already there
sudo systemctl enable keyscripton.service
sudo dd of=/etc/systemd/system/keyscriptoff.service <<'EOF'
[Unit]
Description=keyscriptoff
[Service]
Type=oneshot
ExecStart=/a/exe/keyscript-off
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload # needed if the file was already there
sudo systemctl enable keyscriptoff.service
sudo systemctl start keyscriptoff.service
pi rsync zstd
## /usr/share/doc/dropbear-initramfs/README.initramfs.gz
## claims we need to do this. but it works fine without it.
# tmp=$(mktemp)
# while read -r m _; do /sbin/modinfo -F filename "$m"; done /dev/null; then
# sudo dd if=$tmp of=/etc/initramfs-tools/modules
# sudo /usr/sbin/update-initramfs -u -k all
# fi
#
## if we were creating an intall for a different machine needing different modules, we could include them all like this:
## find /lib/modules/*/kernel/drivers/net /lib/modules/*/kernel/net -type f -name '*.ko' -printf "%f\n" | sed 's/.ko$//' | sort -u >/etc/initramfs-tools/modules
# this is here to cleanup the leftover from the comments above. remove it eventually.
if [[ -s /etc/initramfs-tools/modules ]]; then
sudo truncate -s0 /etc/initramfs-tools/modules
sudo /usr/sbin/update-initramfs -u -k all
fi
# initram auth keys get setup with rootsshsync later on.
$script_dir/rootsshsync
### To do a remote unlock: ssh and do this once per crypt disk:
# echo -n PASS >/lib/cryptsetup/passfifo
# or for buster+
# cryptroot-unlock
fi
##### end setup encryption scripts ######
# disabled until its fixed up
# install-myqueue
# todo, it would be nice to cut down on some of the output
#### rerun my fai-time scripts
# already ran for pxe installs, but used for vps & updates
distro=$(distro-name)
case $distro in
ubuntu|debian|trisquel)
sudo bash -c ". /a/bin/fai/fai-wrapper && /a/bin/fai/fai/config/scripts/IANK/11-iank"
;;
*)
sudo bash -c ". /a/bin/fai/fai-wrapper &&
/a/bin/fai/fai/config/distro-install-common/end"
;;
esac
###### setup hostname
if [[ $HOSTNAME != $(cat /etc/hostname) ]]; then
echo $HOSTNAME > /etc/hostname
hostname -F /etc/hostname
fi
# office vpn dhcp adds to /etc/resolv.conf search office.fsf.org which
# makes that be #1 priority, which makes dnsmasq resolve that for
# unqualified hosts first, which means we skip the hosts file. Ya, its
# kinda dumb, but it is what it is. There is a dnsmasq config option to
# override it too, but this seems simpler.
sudo sed -i --follow-symlinks -f - /etc/hosts </dev/null; then
sudo apt-get -y remove --purge --auto-remove nscd
sudo systemctl stop nscd ||: # fails if already stopped
fi
# http://strugglers.net/~andy/blog/2020/12/03/starting-services-only-when-the-network-is-ready-on-debiansystemd/
if systemctl cat ifupdown-wait-online.service &>/dev/null; then
sudo systemctl enable ifupdown-wait-online.service
fi
if bitfolk; then
# remove line like this: 85.119.82.128 je.iankelling.org je
# it messes with hostname -f.
sudo sed -ri "/^127\./n;/[[:space:]]$HOSTNAME\$/d" /etc/hosts
fi
if isdeb && [[ $(debian-codename) == aramo ]]; then
sudo dd of=/etc/apt/preferences.d/aramo-jammy-missing <<'EOF'
Package: linux-libc-dev libmysqlclient21
Pin: release n=jammy,o=Ubuntu
Pin-Priority: 500
EOF
fi
# libfdk just has some patent worries.
# https://www.gnu.org/licenses/license-list.en.html#fdk
if isdeb && [[ $(debian-codename) == nabia ]]; then
sudo dd of=/etc/apt/preferences.d/nabia-focal-missing <<'EOF'
Package: libfdk-aac1
Pin: release n=focal,o=Ubuntu
Pin-Priority: 500
EOF
# it has a dependency python-paramiko that should be
# python3-paramiko. the backport version is pretty close to the normal
# version, so i just set the pin priority low for the backport and it
# doesnt bother me
sudo dd of=/etc/apt/preferences.d/nabia-backport <<'EOF'
Package: ansible
Pin: release a=nabia-backports
Pin-Priority: -100
EOF
fi
# to test when these become available in trisquel, copy the package list, remove the * chars, repaplace PACKAGES below
# for x in PACKAGES; do hr; e $x; if [[ $x == *- ]]; then s="^$x"; dpkg -l "$x*" | sed '0,/^+++/d'; else s="^$x\$"; fi; aptitude search "~O Trisquel ~n $s"; done
#### setup firefox backport
## ian: disabled. backports are not being published atm due to rust packaging issue
# if isdeb; then
# codename=$(debian-codename)
# if isdebian-stable && has_x; then
# s dd of=/etc/apt/sources.list.d/mozilla-iceweasel.list <$x
sudo dd of=/etc/pacman.conf if=$x; rm $x
sudo systemctl enable pacserve.service
sudo systemctl start pacserve.service
fi
#### update all packages
# shellcheck disable=SC2119 # obvious
pup
###### p1 packages install ######
pi ${p1[@]}
######## fix evbug bug ######
case $(debian-codename-compat) in
xenial|bionic|focal|jammy|noble)
# noticed in flidas. dunno if it affects any others
#https://bugs.launchpad.net/ubuntu/+source/module-init-tools/+bug/240553
#https://wiki.debian.org/KernelModuleBlacklisting
#common advice when searching is to use /etc/modprobe.d/blacklist.conf,
#but that file won't work and will get automatically reverted
sudo rmmod evbug ||: # might not be loaded yet
file=/etc/modprobe.d/evbug.conf
line="blacklist evbug"
if [[ $(cat $file) != "$line" ]]; then
sudo dd of=$file status=none <<<"$line"
sudo depmod -a
sudo update-initramfs -u
fi
;;
esac
#### arch specific early packages
case $(distro-name) in
arch)
# pkgfile is like apt-cache
pi pkgfile
sudo pkgfile --update
;;
esac
#### enable trim
# enable trim for volume delete, other rare commands
sudo $sed -ri 's/( *issue_discards\b).*/\1 = 1/' /etc/lvm/lvm.conf
if encrypted; then
# flidas or so, these units arent built-in
if isdeb && ! systemctl list-unit-files | grep ^fstrim.timer &>/dev/null ; then
sudo cp /usr/share/doc/util-linux/examples/fstrim.{service,timer} /etc/systemd/system
fi
# does weekly trim
sudo systemctl enable fstrim.timer
fi
##### make extra dirs
dirs=()
for dir in /mnt/{1,2,3,4,5,6,7,8,9} /nocow/t; do
[[ -e $dir ]] && continue
dirs+=($dir)
done
if (( ${#dirs[@]} )); then
# mkdir -p on a mounted directory will fail. so will chown if its an ro mount
sudo mkdir -p "${dirs[@]}"
sudo chown $USER:$USER "${dirs[@]}"
fi
# disabled temporarily
###### setup /i
# if home_network; then
# sudo /a/exe/teeu /etc/fstab <<'EOF'
# /i/w /w none bind,noauto 0 0
# /i/k /k none bind,noauto 0 0
# EOF
# if ! mountpoint /kr; then
# sudo mkdir -p /kr
# sudo chown $USER:user2 /kr
# fi
# if [[ $HOSTNAME == frodo ]]; then
# sudo /a/exe/teeu /etc/fstab <<'EOF'
# /k /kr none bind,noauto 0 0
# EOF
# else
# sudo /a/exe/teeu /etc/fstab <<'EOF'
# frodo:/k /kr nfs noauto 0 0
# EOF
# fi
# sudo mkdir -p /i/{w,k}
# for dir in /{i,w,k}; do
# if mountpoint $dir; then continue; fi # already mounted
# sudo mkdir -p $dir
# sudo chown $USER:$USER $dir
# done
# # debian auto mounting of multi-disk encrypted btrfs is busted. It is
# # in jessie, and in stretch as of 11/26/2016 I have 4 disks in cryptab,
# # based on 3 of those, it creates .device units for /dev/mapper/dev...
# # then waits endlessly for them on bootup, after the /dev/mapper disks
# # have already been created and exist. todo: create a simple repro
# # for this in a vm and report it upstream.
# pi nfs-common
# sudo dd of=/root/imount <<'EOF'
# #!/bin/bash
# [[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
# set -eE -o pipefail
# trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
# for dir in /i /k /kr /w; do
# if ! mountpoint $dir &>/dev/null && \
# awk '{print $2}' /etc/fstab | grep -xF $dir &>/dev/null; then
# if awk '{print $3}' /etc/fstab | grep -xF nfs &>/dev/null; then
# mount $dir || echo "warning: failed to mount nfs on $dir"
# else
# mount $dir
# fi
# fi
# done
# EOF
# sudo chmod +x /root/imount
# sudo dd of=/etc/systemd/system/imount.service < 2)) && echo ,compress=zstd ) 0 0
EOF
sudo mkdir -p $dir
sudo chown $USER:$USER $dir
sudo mount $dir
fi
else
sudo mkdir -p $dir
fi
case $HOSTNAME in
kd)
sudo /a/exe/teeu /etc/fstab <<'EOF'
/dev/mapper/crypt_dev_ata-Samsung_SSD_870_QVO_8TB_S5VUNG0N900656V-part7 /d btrfs nofail,x-systemd.device-timeout=30s,x-systemd.mount-timeout=30s,noatime,compress=zstd,subvol=d 0 0
/d/m /i none bind,compress=zstd 0 0
EOF
if ! mountpoint /d &>/dev/null; then
sudo mkdir -p /d
if [[ -d /mnt/r7/d ]]; then
sudo mount /d
fi
fi
if ! mountpoint /i &>/dev/null; then
sudo mkdir -p /i
sudo mount /i
fi
;;
frodo)
sudo /a/exe/teeu /etc/fstab <<'EOF'
/dev/mapper/crypt_dev_ata-ata-Hitachi_HDS722020ALA330_JK1121YAG7SXWS-part1 /i btrfs nofail,x-systemd.device-timeout=30s,x-systemd.mount-timeout=30s,noatime,subvol=i 0 0
EOF
if ! mountpoint /i &>/dev/null; then
sudo mkdir -p /i
if [[ -d /mnt/i/i ]]; then
sudo mount /i
fi
fi
;;
esac
if bitfolk; then
sudo systemctl disable systemd-networkd
fi
##### setup email
primary-setup
#### ubuntu nicety
if isubuntu; then
# disable crash report annoying dialogs.
sudo dd of=/etc/default/apport <<<'enabled=0'
fi
##### install laptop hardware packages
if tp || x2 || x3 || bo || sy; then
case $distro in
debian)
pi task-laptop
;;
ubuntu|trisquel)
# the exact packages that task-laptop would install, since ubuntu
# doesn\'t have this virtual in practice package.
pi avahi-autoipd bluetooth powertop iw wireless-tools wpasupplicant
;;
# todo: other distros unknown
esac
fi
if has_monitor; then
# sway not packaged for t9, not bothering to build it yet since
# i3 doesnt seem to tear and stutter on video anymore.
if [[ $codename == buster ]]; then
pi sway xwayland
fi
###### install X
pi i3
##### install xinput
case $(distro-name) in
trisquel|ubuntu|debian)
pi xinput
;;
esac
##### setup X autostart
## disabled since i'm not using gdm atm
# dir=/etc/gdm3
# sudo mkdir -p $dir/PostLogin
# sudo cp /a/bin/distro-setup/myx $dir/PostLogin/Default
sudo mkdir -p /etc/lightdm/lightdm.conf.d
# etiona lightdm.log:
# [SeatDefaults] is now called [Seat:*], please update this configuration
sudo dd of=/etc/lightdm/lightdm.conf.d/12-iank.conf <<'EOF'
[Seat:*]
# display-setup-script=/a/bin/ds/lightdm-start
session-setup-script=/a/bin/distro-setup/myx
EOF
# originally used xkbcomp, documented in input-setup.sh, this doesnt
# work under wayland, but its still useful for creating the config,
# then modifying the system files.
sudo sed -i.orig '/key * *{/,/}/s/KP_Multiply/underscore/g' /usr/share/X11/xkb/symbols/keypad
##### basic graphical packages
pi konsole suckless-tools ssh-askpass
fi
##### install emacs
if $emacs; then
if isarch; then
# emacs git build was broken last time i checked,
x=$(mktemp -d)
pushd $x
aurex emacs-git
makepkg -si --noconfirm
popd
rm -rf $x
pi hunspell hunspell-en
else
if $recompile; then
/a/bin/buildscripts/emacs
/a/bin/buildscripts/mu4e
else
/a/bin/buildscripts/emacs --no-r
/a/bin/buildscripts/mu4e --no-r
fi
fi
# the first pup command can kill off our /etc/ mod, so rerun this
/a/exe/ssh-emacs-setup
fi
if [[ $HOSTNAME == kd ]] && ! mountpoint /d &>/dev/null; then
cat <<'EOFOUTER'
# if this is a fresh reinstall, need to run something like this
# to restore data:
mkdir /mnt/r7/btrbk
btrbk archive /mnt/rust1/btrbk /mnt/r7/btrbk
btrfs sub snap /mnt/r7/btrbk/LATEST /mnt/r7/d
mount /d
EOFOUTER
fi
echo 0 >~/.local/distro-begin
echo "$0: $(date): ending now"
echo "exiting with status 0"
exit 0