#!/bin/bash # Copyright (C) 2016 Ian Kelling # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # for setting up a new machine # usage: $0 [-r] [HOSTNAME] # HOSTNAME changes the machine's hostname # 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 ####### ### make ssh interactive shell run better. for when running line interactively line by line sudo bash -c '/a/exe/ssh-emacs-setup' ##### 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/errhandle/err 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 frodo tp li bk je demohost kw sy bo; 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/GRUB_PC/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 # 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 pup ###### p1 packages install ###### pi ${p1[@]} ######## fix evbug bug ###### case $(debian-codename-compat) in xenial|bionic|focal) # 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 2>/dev/null <<<"$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 # tu /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 # tu /etc/fstab <<'EOF' # /k /kr none bind,noauto 0 0 # EOF # else # tu /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) tu /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 EOF if ! mountpoint /d &>/dev/null; then sudo mkdir /d if [[ -d /mnt/r7/d ]]; then sudo mount /d 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 # no recommends due to this bug: https://trisquel.info/en/issues/26525 pi --no-install-recommends i3 ##### install xinput case $(distro-name) in trisquel|ubuntu|debian) pi xinput ;; esac # recommends gets us geoclue (for darkening automatically at night i assume), # which recommends modemmanager, which is annoying to fix for the model01 keyboard. # commented because I dont use it much, and in nabia its named changed to redshift-gtk #pi --no-install-recommends gtk-redshift ##### setup X autostart # install for multiple display managers in case we use one dir=/etc/X11/xinit/xinitrc.d/ sudo mkdir -p $dir sudo cp /a/bin/distro-setup/desktop-20-autostart.sh $dir s teeu /etc/systemd/logind.conf <<'EOF' HandleLidSwitch= EOF # this works on dir=/etc/gdm3 sudo mkdir -p $dir/PostLogin sudo cp /a/bin/distro-setup/desktop-20-autostart.sh $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/desktop-20-autostart.sh 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 else /a/bin/buildscripts/emacs --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