#!/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=( gnome-shell-extension-pop-shell-git ) 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 <>"/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 # Android development android-studio # development environment android-sdk-cmdline-tools-latest # command-line tools android-sdk-build-tools # SDK build-tools android-sdk-platform-tools # SDK platform-tools android-platform # SDK platform android-emulator ) 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 # Set plymouth theme if command -v plymouth-set-default-theme > /dev/null; then plymouth-set-default-theme bgrt fi