dotfiles/install.sh

494 lines
15 KiB
Bash
Executable file

#!/usr/bin/env bash
set -uo pipefail
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
PRESERVE_ENV=AUR_PAGER,PACKAGER,EDITOR
if [[ $EUID != 0 ]]; then
echo 'Elevating privileges'
exec sudo --preserve-env="${PRESERVE_ENV}" "$0" "$@"
fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
# Initialize AUR repo
if [[ ! -d /var/cache/pacman/aur ]]; then
install -m755 -d /var/cache/pacman/aur
repo-add /var/cache/pacman/aur/aur.db.tar.zst
fi
# Configure pacman
install -pm644 "$DIR/etc/pacman/pacman.conf" /etc/pacman.conf
install -pm644 -Dt /etc/pacman.d/conf.d \
"$DIR/etc/pacman/00-global-options.conf" \
"$DIR/etc/pacman/50-core-repositories.conf" \
"$DIR/etc/pacman/55-multilib-repository.conf" \
"$DIR/etc/pacman/60-aurutils-repository.conf" \
"$DIR/etc/pacman/99-options.conf"
# Remove packages one by one because pacman doesn't handle uninstalled packages
# gracefully
packages_to_remove=(
)
for pkg in "${packages_to_remove[@]}"; do
pacman --noconfirm -Rs "$pkg" || true
done
packages=(
# Basic packages & system tools
base
dracut # Build initrd & unified EFI images
linux-firmware
intel-ucode
linux
lsb-release
sudo
zram-generator # swap on compressed RAM, mostly to support systemd-oomd
sbctl # Manage secure boot binaries and sign binaries
plymouth # Splash screen at boot
# File systems
ntfs-3g
exfatprogs
btrfs-progs
sshfs
# Hardware tools
fwupd # Firmware updates
usbutils # for lsusb
# System monitoring
htop
lsof
# Power management
powertop
power-profiles-daemon
# Networking
firewalld
# DNS-SD, mostly for printers, i.e. CUPS. Service discovery is handled by Avahi,
# name resolution by systemd-resolved.
avahi
# Arch tools & infrastructure
pacman-contrib # paccache, checkupdates, pacsearch, and others
reflector # Weekly mirrorlist updates
kernel-modules-hook # Keep kernel modules on kernel updates
pkgfile
# Build packages
base-devel
namcap
aurpublish # Publish AUR packages from Git subtrees
# Dotfiles manager
chezmoi
# Terminal, shell & tools
man-db
man-pages
bash-completion
code
neovim
exa # Better ls (with git support)
nnn # Command line file manager (also a good pager for aurutils)
rsync
curl
p7zip
zip
# Document processing and rendering
pandoc
mdcat
asciidoctor
zathura # Lightweight document viewer
# Spellchecking
hunspell
hunspell-de
hunspell-en_gb
hunspell-en_us
# Git and related tools
git
git-filter-repo
tea # CLI for gitea servers
tig # Curses git interfaces
# Bash tools
shellcheck
shfmt
# Other development tools
jq # Process JSON on command line
ansible-core
ansible
ansible-lint
# Desktop tools
wl-clipboard
dconf-editor
# Desktop services
xdg-user-dirs
xdg-utils
xdg-desktop-portal
pcsclite # Smartcard daemon, for e-ID
libfido2
cups
bluez
sane
pipewire-pulse # Pipewire-based pulse-audio, replaces pulseaudio
wireplumber # Recommended pipewire session & policy manager
playerctl
qt5-wayland # neccessary for nextcloud-client
firefox # Browser
firefox-i18n-de
firefox-dark-reader
firefox-ublock-origin
vlc # Video player
pipewire-jack # required by vlc
inkscape # Vector graphics
gimp # Pixel graphics
darktable
libreoffice-fresh
libreoffice-fresh-de
lollypop # Music player
#xournalpp # Handwriting tool
#signal-desktop # Secure mobile messenger
# Fonts & themes
qgnomeplatform-qt5
# Fallback font with huge coverage and colored emojis
noto-fonts
noto-fonts-extra
noto-fonts-cjk
noto-fonts-emoji
# Microsoft compatibility fonts
ttf-liberation
ttf-caladea
ttf-carlito
ttf-cascadia-code
# Gnome
gdm
gnome-characters
gnome-keyring
gnome-screenshot
gnome-maps
gnome-clocks
gnome-weather
gnome-calendar
gnome-terminal
gnome-shell
gnome-shell-extensions
gnome-shell-extension-appindicator
gnome-remote-desktop
gnome-system-monitor
gnome-control-center
gnome-tweaks
gnome-calculator
gnome-backgrounds
gnome-themes-extra # For adwaita-dark
xdg-desktop-portal-gnome # Desktop portals
xdg-user-dirs-gtk
evolution
file-roller
yelp # Online help system
nautilus
python-nautilus
gvfs-afc
gvfs-goa
gvfs-gphoto2
gvfs-mtp
gvfs-nfs
gvfs-smb
sushi # Previewer for nautilus
evince # Document viewer
eog # Image viewer
simple-scan
seahorse # Credential manager
baobab # Disk space analyser
# Multimedia for gnome
gst-plugins-good
gst-plugins-bad
gst-plugins-ugly
bitwarden # Password manager
yubikey-touch-detector
nextcloud-client
element-desktop # Matrix client
tailscale
flatpak
)
optdeps=(
# pipewire
pipewire-pulse wireplumber
# linux: wireless frequency policies (provided as crda)
wireless-regdb
# pipewire: zeroconf support
pipewire-zeroconf
# poppler: data files
poppler-data
# dracut:
binutils # --uefi
elfutils # stripping
sbsigntools # efi signing
tpm2-tools # tpm2-tss
# zathura: PDF support
zathura-pdf-mupdf
# libva: intel drivers
intel-media-driver
# gnome-shell-extension-appindicator: GTK3 apps
libappindicator-gtk3
# aurutils: chroot support
devtools
# zim: spell checking
gtkspell3
# inkscape: optimized SVGs
scour
# gnome-shell: Screen recording
gst-plugin-pipewire
# gnome-control-center: Applications
malcontent
# nextcloud-client: integration with Nautilus
python-nautilus
)
pacman -Syu --noconfirm --needed "${packages[@]}"
pacman -S --noconfirm --needed --asdeps "${optdeps[@]}"
pacman -D --noconfirm --asdeps "${optdeps[@]}"
# Currently dracut is missing an optdepends on tpm2-tools, see
# https://bugs.archlinux.org/task/73229
pacman -D --asexplicit tpm2-tools
services=(
# Core system services
systemd-boot-update.service # Update boot loader automatically
systemd-homed.service # homed for user management and home areas
systemd-oomd.service # Userspace OOM killer
systemd-timesyncd.service # Time sync
systemd-resolved.service # DNS resolution
# Other system services
firewalld.service # Firewall
linux-modules-cleanup.service # kernel-modules-hook
# Timers
fstrim.timer # Periodically trim file systems…
"btrfs-scrub@$(systemd-escape -p /).timer" # scrub root filesystem…
paccache.timer # clean pacman cache…
pkgfile-update.timer # update pkgfile list…
fwupd-refresh.timer # check for firmware updates…
reflector.timer # and update the mirrorlist.
# Desktop services
gdm.service # Desktop manager
power-profiles-daemon.service # Power profile management
NetworkManager.service # Network manager for desktops
avahi-daemon.service # Local network service discovery (for WLAN printers)
cups.service # Printing
bluetooth.service # Bluetooth
pcscd.socket # Smartcards, mostly eID
tailscaled.service
)
if [[ -n "${SUDO_USER:-}" ]]; then
# Scrub home directory of my user account
services+=("btrfs-scrub@$(systemd-escape -p "/home/${SUDO_USER}").timer")
fi
systemctl enable "${services[@]}"
# See /usr/share/factory/etc/nsswitch.conf for the Arch Linux factory defaults.
# We add mdns hostnames (from Avahi) and libvirtd names, and also shuffle things around
# to follow the recommendations in nss-resolve(8) which Arch Linux deliberately doesn't
# do by default, see e.g. https://bugs.archlinux.org/task/57852
NSS_HOSTS=(
# Resolves containers managed by systemd-machined
mymachines
# Resolve everything else with systemd-resolved and bail out if resolved
# doesn't find hostname. Everything after this stanza is just fallback in
# case resolved is down
resolve '[!UNAVAIL=return]'
# Resolve hosts from /etc/hosts (systemd-resolved handles /etc/hosts as well
# so this comes after resolve)
files
# Resolves gethostname(), i.e. /etc/hostname
myhostname
# Resolves from DNS
dns
)
sed -i '/^hosts: /s/^hosts: .*/'"hosts: ${NSS_HOSTS[*]}/" /etc/nsswitch.conf
# Bootloader and initrd configuration
install -pm644 "$DIR/etc/dracut.conf" /etc/dracut.conf.d/50-custom.conf
install -pm644 "$DIR/etc/loader.conf" /efi/loader/loader.conf
if [[ ! -f /usr/share/secureboot/keys/db/db.pem ]]; then
sbctl create-keys
sbctl enroll-keys
fi
if [[ -f /usr/share/secureboot/keys/db/db.key ]] && [[ -f /usr/share/secureboot/keys/db/db.pem ]]; then
install -pm644 "$DIR/etc/dracut-sbctl.conf" /etc/dracut.conf.d/90-sbctl-signing.conf
else
rm -f /etc/dracut.conf.d/90-sbctl-signing.conf
fi
# System configuration
install -pm644 "$DIR/etc/faillock.conf" /etc/security/faillock.conf
install -pm644 "$DIR/etc/modprobe.conf" /etc/modprobe.d/modprobe.conf
# sudo configuration
install -dm750 /etc/sudoers.d/
install -pm600 -t/etc/sudoers.d "$DIR"/etc/sudoers.d/*
# Systemd configuration
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
install -Dpm644 "$DIR/etc/systemd/system.conf" /etc/systemd/system.conf.d/50-custom.conf
install -Dpm644 "$DIR/etc/systemd/timesyncd.conf" /etc/systemd/timesyncd.conf.d/50-custom.conf
install -Dpm644 "$DIR/etc/systemd/resolved.conf" /etc/systemd/resolved.conf.d/50-custom.conf
install -Dpm644 "$DIR/etc/systemd/zram-generator.conf" /etc/systemd/zram-generator.conf
install -Dpm644 "$DIR/etc/systemd/oomd.conf" /etc/systemd/oomd.conf.d/oomd.conf
install -Dpm644 "$DIR/etc/systemd/root-slice-oomd.conf" /etc/systemd/system/-.slice.d/50-oomd.conf
install -Dpm644 "$DIR/etc/systemd/user-service-oomd.conf" /etc/systemd/system/user@.service.d/50-oomd.conf
# Services configuration
install -Dpm644 "$DIR/etc/networkmanager-mdns.conf" /etc/NetworkManager/conf.d/50-mdns.conf
install -Dpm644 "$DIR/etc/iwd/main.conf" /etc/iwd/main.conf
install -Dpm644 "$DIR/etc/reflector.conf" /etc/xdg/reflector/reflector.conf
install -Dpm644 "$DIR/etc/bluetooth.conf" /etc/bluetooth/main.conf
install -Dpm644 "$DIR/etc/snapper-root.conf" /etc/snapper/configs/root
install -Dpm644 "$DIR/etc/firefox/policies.json" /etc/firefox/policies/policies.json
# Global font configuration
for file in 10-hinting-slight 10-sub-pixel-rgb 11-lcdfilter-default; do
ln -sf /usr/share/fontconfig/conf.avail/$file.conf /etc/fonts/conf.d/$file.conf
done
# Locale settings
localectl set-locale de_DE.UTF-8
# --no-convert stops localectl from trying to apply the text console layout to
# X11/Wayland and vice versa
localectl set-keymap --no-convert de
localectl set-x11-keymap --no-convert de pc105
# GDM dconf profile, for global GDM configuration, see
# https://help.gnome.org/admin/system-admin-guide/stable/login-banner.html.en
install -Dpm644 "$DIR/etc/gdm-profile" /etc/dconf/profile/gdm
# Start firewalld and configure it
systemctl start firewalld.service
firewall-cmd --permanent --zone=home \
--add-service=upnp-client \
--add-service=rdp \
--add-service=ssh \
--add-service gsconnect
# Don't allow incoming SSH connections on public networks (this is a weird default imho)
firewall-cmd --permanent --zone=public --remove-service=ssh
firewall-cmd --reload
# Setup secure boot
if command -v sbctl > /dev/null && [[ -f /usr/share/secureboot/keys/db/db.key ]]; then
# Generate signed bootloader image
if ! sbctl list-files | grep -q /usr/lib/systemd/boot/efi/systemd-bootx64.efi; then
sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi
bootctl update --graceful
fi
# Generate signed firmware updater
if ! sbctl list-files | grep -q /usr/lib/fwupd/efi/fwupdx64.efi; then
sbctl sign -s -o /usr/lib/fwupd/efi/fwupdx64.efi.signed /usr/lib/fwupd/efi/fwupdx64.efi
fi
sbctl sign-all
sbctl verify # Safety check
fi
# Install or update, and then configure the bootloader.
# Do this AFTER signing the boot loader with sbctl, see above, to make sure we
# install the signed loader.
if ! [[ -e /efi/EFI/BOOT/BOOTX64.EFI ]]; then
bootctl install
else
bootctl update --graceful
fi
# Allow myself to build AUR packages
if [[ -n "${SUDO_USER:-}" && "$(stat -c '%U' /var/cache/pacman/aur)" != "$SUDO_USER" ]]; then
chown -R "$SUDO_USER:$SUDO_USER" /var/cache/pacman/aur
fi
# Bootstrap aurutils
if [[ -n "${SUDO_USER:-}" ]] && ! command -v aur &>/dev/null; then
sudo -u "$SUDO_USER" bash <<'EOF'
set -xeuo pipefail
BDIR="$(mktemp -d --tmpdir aurutils.XXXXXXXX)"
echo "Building in $BDIR"
cd "$BDIR"
git clone --depth=1 "https://aur.archlinux.org/aurutils.git"
cd aurutils
makepkg --noconfirm --nocheck -rsi
EOF
fi
# Configure aurutils
if [[ ! -e "/etc/aurutils/pacman-aur.conf" ]]; then
install -Dpm644 /usr/share/devtools/pacman-extra.conf "/etc/aurutils/pacman-aur.conf"
cat <<EOF >>"/etc/aurutils/pacman-aur.conf"
# aurutils repo
[aur]
SigLevel = Optional TrustAll
Server = file:///var/cache/pacman/aur
EOF
fi
aur chroot --create
aur_packages=(
# AUR helper
aurutils
networkmanager-iwd
# iwd GUI
iwgtk
# Login settings
gdm-settings
# Gnome extensions
gnome-shell-extension-arch-update # Indicator for system update
gnome-shell-extension-gsconnect # Connect phone and desktop system
gnome-shell-extension-dash-to-dock # Move the dash out of the overview transforming it in a dock
gnome-shell-extension-clipboard-history # Searchable history panel of clipboard
gnome-shell-extension-bluetooth-quick-connect
gnome-shell-extension-quick-settings-tweaks-git
gnome-shell-extension-nightthemeswitcher
gnome-shell-extension-tiling-assistant
gnome-shell-extension-alphabetical-grid-extension-git # Restore the alphabetical ordering of the app grid
# Firefox extensions
firefox-extension-bitwarden
newsflash
# Dracut hook to build kernel images for systemd boot
dracut-hook-uefi
# Additional fonts
otf-vollkorn # My favorite serif font for documents
ttf-fira-go # A nice font for presentations
# Additional tools
git-gone
dnscontrol-bin
qtscrcpy # Android screen display
)
aur_optdeps=(
# plymouth: truetype fonts
ttf-dejavu cantarell-fonts
)
if [[ -n "${SUDO_USER:-}" ]]; then
# Build AUR packages and install them
if [[ ${#aur_packages} -gt 0 ]]; then
sudo -u "$SUDO_USER" --preserve-env="${PRESERVE_ENV}" \
nice aur sync -daur -cRT "${aur_packages[@]}" "${aur_optdeps[@]}"
pacman --needed -Syu "${aur_packages[@]}"
fi
if [[ ${#aur_optdeps[@]} -gt 0 ]]; then
pacman --needed -S --asdeps "${aur_optdeps[@]}"
pacman -D --asdeps "${aur_optdeps[@]}"
fi
remove_from_repo=()
if [[ ${#remove_from_repo[@]} -gt 0 ]]; then
for pkg in "${remove_from_repo[@]}"; do
rm -f "/var/cache/pacman/aur/${pkg}-"*.pkg.tar.*
done
sudo -u "$SUDO_USER" repo-remove /var/cache/pacman/aur/aur.db.tar.zst "${remove_from_repo[@]}" || true
fi
fi
# Upgrade flatpak packages
echo Updating flatpak packages...
flatpak update --noninteractive --assumeyes
# Set plymouth theme
if command -v plymouth-set-default-theme > /dev/null; then
plymouth-set-default-theme bgrt
fi