Update new setup

master
Tobias Strobel 2 months ago
parent 842511035a
commit 39633f5303
  1. 2
      .chezmoiignore
  2. 195
      bootstrap-from-iso.sh
  3. 241
      dot_config/sway/config
  4. 6
      dot_config/systemd/user/sway-session.target
  5. 48
      dot_config/wldash/config.yaml
  6. 0
      etc/bluetooth.conf
  7. 5
      etc/dracut-sbctl.conf
  8. 19
      etc/dracut.conf
  9. 8
      etc/faillock.conf
  10. 3
      etc/gdm-profile
  11. 5
      etc/iwd/main.conf
  12. 1
      etc/kernel/cmdline
  13. 7
      etc/loader.conf
  14. 4
      etc/mkinitcpio.conf
  15. 9
      etc/modprobe.conf
  16. 1
      etc/modprobe.d/i915.conf
  17. 7
      etc/networkmanager-mdns.conf
  18. 4
      etc/pacman/00-global-options.conf
  19. 27
      etc/pacman/50-core-repositories.conf
  20. 8
      etc/pacman/55-multilib-repository.conf
  21. 4
      etc/pacman/60-aurutils-repository.conf
  22. 2
      etc/pacman/99-options.conf
  23. 69
      etc/pacman/pacman.conf
  24. 5
      etc/reflector.conf
  25. 46
      etc/snap-pac.ini
  26. 0
      etc/snapper-root.conf
  27. 35
      etc/sudoers.d/10-defaults
  28. 2
      etc/sudoers.d/50-aurutils
  29. 0
      etc/sudoers.d/50-wheel
  30. 58
      etc/sysctl.conf
  31. 1
      etc/sysctl.d/20-quiet-printk.conf
  32. 13
      etc/systemd/network/20-wired.network
  33. 13
      etc/systemd/network/25-wireless.network
  34. 3
      etc/systemd/oomd.conf
  35. 6
      etc/systemd/resolved.conf
  36. 13
      etc/systemd/root-slice-oomd.conf
  37. 7
      etc/systemd/system.conf
  38. 3
      etc/systemd/system/getty@tty1.service.d/override.conf
  39. 3
      etc/systemd/timesyncd.conf
  40. 17
      etc/systemd/user-service-oomd.conf
  41. 1
      etc/systemd/zram-generator.conf
  42. 585
      install.sh
  43. 2
      private_dot_gnupg/gpg-agent.conf
  44. 24
      private_dot_local/bin/executable_cglaunch
  45. 206
      private_dot_local/private_share/chezmoi/executable_setup-system.sh
  46. 15
      run_once_setup-gpg.sh
  47. 223
      run_once_setup-user.sh
  48. 206
      setup-system.sh

@ -1,4 +1,4 @@
# Do not apply the following files
etc/
install.sh
setup-system.sh
bootstrap-from-iso.sh

@ -0,0 +1,195 @@
#!/usr/bin/env bash
#
# Bootstrap a new Arch system from an installation ISO.
#
# Bootable USB:
# - [Download](https://archlinux.org/download/) ISO and GPG files
# - Verify the ISO file: `$ pacman-key -v archlinux-<version>-x86_64.iso.sig`
# - Create a bootable USB with: `# dd if=archlinux*.iso of=/dev/sdX && sync`
#
# UEFI setup:
#
# - Set boot mode to UEFI, disable Legacy mode entirely.
# - Temporarily disable Secure Boot.
# - Make sure a strong UEFI administrator password is set.
# - Delete preloaded OEM keys for Secure Boot, allow custom ones.
#
# Run installation:
#
# - Connect to wifi via: `# iwctl station wlan0 connect $SSID`
# - Run: `# bash <(curl -sL https://link.rafe.li/dot)`
#
set -uo pipefail
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
args=()
target_device=""
new_hostname=""
while [[ $# -gt 0 ]]
do
arg="$1"
case "$arg" in
"--device")
target_device="$2"
shift
shift
;;
"--hostname")
new_hostname="$2"
shift
shift
;;
*)
args+=("$arg")
shift;
esac
done
if [[ -z "$target_device" ]]; then
echo "Missing --device <device> argument" >&2
exit 2;
fi
if [[ -z "$new_hostname" ]]; then
echo "Missing --hostname <hostname> argument" >&2
exit 2;
fi
if [[ "${#args[@]}" -ne 0 ]]; then
echo "Unexpected extra arguments: ${args[*]}" >&2
exit 2
fi
if [ ! -f /sys/firmware/efi/fw_platform_size ]; then
echo >&2 "You must boot in UEFI mode to continue"
exit 2
fi
if [[ "$UID" -ne 0 ]]; then
echo "This script needs to be run as root!" >&2
exit 3
fi
read -rp "THIS SCRIPT WILL OVERWRITE ALL CONTENTS OF ${target_device}. Type uppercase yes to continue: " confirmed
if [[ "$confirmed" != "YES" ]]; then
echo "aborted" >&2
exit 128
fi
timedatectl set-ntp true
hwclock --systohc --utc
loadkeys de-latin1
# Partition
sgdisk --zap-all "${target_device}"
sgdisk --clear \
--new 1:0:+550MiB --typecode 1:ef00 --change-name 1:EFI \
--new 2:0:+8GiB --typecode 2:8200 --change-name 2:swap \
--new 3 --typecode 3:8304 --change-name 3:system \
"${target_device}"
# Reload partition table
sleep 5
partprobe -s "${target_device}"
sleep 3
# Encrypt root
echo -n "password" | cryptsetup luksFormat --type luks2 --pbkdf argon2id "/dev/disk/by-partlabel/system"
echo -n "password" | cryptsetup luksOpen --allow-discards --persistent "/dev/disk/by-partlabel/system" system
# Create file systems
mkfs.fat -F 32 -n "EFI" /dev/disk/by-partlabel/EFI
mkfs.btrfs --force --label system /dev/mapper/system
# Mount system subvolume and create additional subvolumes
o=defaults,x-mount.mkdir
o_btrfs=$o,compress=zstd,ssd,noatime
mount -t btrfs LABEL=system /mnt
btrfs subvolume create /mnt/@ # /
btrfs subvolume create /mnt/@home # /home
btrfs subvolume create /mnt/@snapshots # /.snapshots
btrfs subvolume create /mnt/@pkg # /var/cache/pacman/pkg
btrfs subvolume create /mnt/@aurbuild # /var/lib/aurbuild
btrfs subvolume create /mnt/@archbuild # /var/lib/archbuild
btrfs subvolume create /mnt/@log # /var/log
btrfs subvolume create /mnt/@tmp # /var/tmp
umount -R /mnt
mount -t btrfs -o subvol=@,$o_btrfs LABEL=system /mnt
mount -t btrfs -o subvol=@home,$o_btrfs,nodatacow LABEL=system /mnt/home
mount -t btrfs -o subvol=@snapshots,$o_btrfs LABEL=system /mnt/.snapshots
mount -t btrfs -o subvol=@pkg,$o_btrfs LABEL=system /mnt/var/cache/pacman/pkg
mount -t btrfs -o subvol=@aurbuild,$o_btrfs LABEL=system /mnt/var/lib/aurbuild
mount -t btrfs -o subvol=@archbuild,$o_btrfs LABEL=system /mnt/var/lib/archbuild
mount -t btrfs -o subvol=@log,$o_btrfs LABEL=system /mnt/var/log
mount -t btrfs -o subvol=@tmp,$o_btrfs LABEL=system /mnt/var/tmp
# Mount additional partitions
mount -o $o LABEL=EFI /mnt/efi
# Change default btrfs sub-volume (for DPS)
default_subvolume=$(btrfs subvolume list /mnt | grep "path @$" | cut -d ' ' -f2)
btrfs subvolume set-default ${default_subvolume} /mnt
# Disable CoW for /home due to large loopback files by systemd-homed
chattr +C /mnt/home
if ! grep "# Installer cache" /etc/pacman.conf > /dev/null; then
cat >> /etc/pacman.conf << EOF
# Installer cache
[options]
CacheDir = /mnt/var/cache/pacman/pkg
EOF
fi
# Bootstrap new chroot
reflector --country 'Germany' --protocol https --sort age --latest 5 --save /etc/pacman.d/mirrorlist
pacstrap /mnt base linux linux-firmware intel-ucode btrfs-progs dracut neovim iwd networkmanager
genfstab -L -p /mnt >> /mnt/etc/fstab
# Configure timezone, locale, keymap, network
sed -i 's/^#en_US\.UTF-8/en_US\.UTF-8/' /mnt/etc/locale.gen
sed -i 's/^#de_DE\.UTF-8/de_DE\.UTF-8/' /mnt/etc/locale.gen
arch-chroot /mnt locale-gen
arch-chroot /mnt systemd-firstboot \
--locale="en_US.UTF-8" \
--keymap="de-latin1" \
--timezone="Europe/Berlin" \
--hostname="${new_hostname}" \
--setup-machine-id
echo -e "127.0.0.1\tlocalhost" >> /mnt/etc/hosts
echo -e "127.0.1.1\t$new_hostname" >> /mnt/etc/hosts
echo -e "\n::1\tlocalhost" >> /mnt/etc/hosts
# Use systemd-resolved as dns backend for NetworkManager (auto-detected)
ln -sf /run/systemd/resolve/stub-resolv.conf /mnt/etc/resolv.conf
# Enable iwd as wifi backend for NetworkManager
cat > /mnt/etc/NetworkManager/conf.d/wifi-backend.conf <<EOF
[device]
wifi.backend=iwd
EOF
# Install dracut opt deps required to build unified kernel images
arch-chroot /mnt pacman -S --noconfirm --asdeps binutils elfutils
arch-chroot /mnt dracut -f --uefi --regenerate-all
# Install bootloader
arch-chroot /mnt bootctl install
# Enable resolved
systemctl --root /mnt enable systemd-resolved
# Enable NetworkManager
systemctl --root /mnt enable NetworkManager
# Enable homed
systemctl --root /mnt enable systemd-homed
# Set root password
echo "root:password" | chpasswd -R /mnt
echo "BOOTSTRAPPING FINISHED"

@ -1,241 +0,0 @@
# Default config for sway
#
# Copy this to ~/.config/sway/config and edit it to your liking.
#
# Read `man 5 sway` for a complete reference.
### Variables
#
# Logo key. Use Mod1 for Alt.
set $mod Mod4
# Home row direction keys, like vim
set $left h
set $down j
set $up k
set $right l
# Your preferred terminal emulator
set $term foot
### Output configuration
#
# Default wallpaper (more resolutions are available in /usr/share/backgrounds/sway/)
output * bg /usr/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
#
# Example configuration:
#
# output HDMI-A-1 resolution 1920x1080 position 1920,0
#
# You can get the names of your outputs by running: swaymsg -t get_outputs
### Idle configuration
#
# Example configuration:
#
exec swayidle -w \
timeout 300 'swaylock -f -c 1e1e1e' \
timeout 600 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' \
before-sleep 'swaylock -f -c 1e1e1e'
#
# This will lock your screen after 300 seconds of inactivity, then turn off
# your displays after another 300 seconds, and turn your screens back on when
# resumed. It will also lock your screen before your computer goes to sleep.
### Input configuration
#
# Example configuration:
#
# input "2:14:SynPS/2_Synaptics_TouchPad" {
# dwt enabled
# tap enabled
# natural_scroll enabled
# middle_emulation enabled
# }
#
# You can get the names of your inputs by running: swaymsg -t get_inputs
# Read `man 5 sway-input` for more information about this section.
input * {
xkb_layout "de"
}
input type:touchpad {
tap enabled
natural_scroll enabled
}
seat * hide_cursor 10000
# Gaps
gaps inner 5
smart_gaps on
# Borders
default_border pixel 2
default_floating_border none
hide_edge_borders --i3 none
# Disable cursor jumping
mouse_warping none
focus_follows_mouse no
tiling_drag disable
for_window [app_id=".*"] sticky enable
for_window [window_role="pop-up"] floating enable
### Key bindings
#
# Basics:
#
# Start a terminal
bindsym $mod+Return exec $term
# Kill focused window
bindsym $mod+Shift+q kill
# Start your launcher
bindsym $mod+d exec cglaunch wldash
# Drag floating windows by holding down $mod and left mouse button.
# Resize them with right mouse button + $mod.
# Despite the name, also works for non-floating windows.
# Change normal to inverse to use left mouse button for resizing and right
# mouse button for dragging.
floating_modifier $mod normal
# Reload the configuration file
bindsym $mod+Shift+c reload
# Exit sway (logs you out of your Wayland session)
bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit'
#
# Moving around:
#
# Move your focus around
bindsym $mod+$left focus left
bindsym $mod+$down focus down
bindsym $mod+$up focus up
bindsym $mod+$right focus right
# Or use $mod+[up|down|left|right]
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right
# Move the focused window with the same, but add Shift
bindsym $mod+Shift+$left move left
bindsym $mod+Shift+$down move down
bindsym $mod+Shift+$up move up
bindsym $mod+Shift+$right move right
# Ditto, with arrow keys
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
#
# Workspaces:
#
# Switch to workspace
bindsym $mod+1 workspace number 1
bindsym $mod+2 workspace number 2
bindsym $mod+3 workspace number 3
bindsym $mod+4 workspace number 4
bindsym $mod+5 workspace number 5
bindsym $mod+6 workspace number 6
bindsym $mod+7 workspace number 7
bindsym $mod+8 workspace number 8
bindsym $mod+9 workspace number 9
bindsym $mod+0 workspace number 10
# Move focused container to workspace
bindsym $mod+Shift+1 move container to workspace number 1
bindsym $mod+Shift+2 move container to workspace number 2
bindsym $mod+Shift+3 move container to workspace number 3
bindsym $mod+Shift+4 move container to workspace number 4
bindsym $mod+Shift+5 move container to workspace number 5
bindsym $mod+Shift+6 move container to workspace number 6
bindsym $mod+Shift+7 move container to workspace number 7
bindsym $mod+Shift+8 move container to workspace number 8
bindsym $mod+Shift+9 move container to workspace number 9
bindsym $mod+Shift+0 move container to workspace number 10
# Note: workspaces can have any name you want, not just numbers.
# We just use 1-10 as the default.
#
# Layout stuff:
#
# You can "split" the current object of your focus with
# $mod+b or $mod+v, for horizontal and vertical splits
# respectively.
bindsym $mod+b splith
bindsym $mod+v splitv
# Switch the current container between different layout styles
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split
# Make the current focus fullscreen
bindsym $mod+f fullscreen
# Toggle the current focus between tiling and floating mode
bindsym $mod+Shift+space floating toggle
# Swap focus between the tiling area and the floating area
bindsym $mod+space focus mode_toggle
# Move focus to the parent container
bindsym $mod+a focus parent
#
# Scratchpad:
#
# Sway has a "scratchpad", which is a bag of holding for windows.
# You can send windows there and get them back later.
# Move the currently focused window to the scratchpad
bindsym $mod+Shift+minus move scratchpad
# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
bindsym $mod+minus scratchpad show
#
# Resizing containers:
#
mode "resize" {
# left will shrink the containers width
# right will grow the containers width
# up will shrink the containers height
# down will grow the containers height
bindsym $left resize shrink width 10px
bindsym $down resize grow height 10px
bindsym $up resize shrink height 10px
bindsym $right resize grow width 10px
# Ditto, with arrow keys
bindsym Left resize shrink width 10px
bindsym Down resize grow height 10px
bindsym Up resize shrink height 10px
bindsym Right resize grow width 10px
# Return to default mode
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"
# Keybindings
bindsym --to-code {
XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +5%
XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -5%
XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ toggle
XF86AudioMicMute exec pactl set-source-mute @DEFAULT_SOURCE@ toggle
XF86MonBrightnessDown exec brightnessctl set 5%-
XF86MonBrightnessUp exec brightnessctl set +5%
}
#
# Status Bar:
#
# Read `man 5 sway-bar` for more information about this section.
bar {
swaybar_command waybar
}
include /etc/sway/config.d/*
exec systemctl --user start sway-session.target

@ -1,6 +0,0 @@
[Unit]
Description=sway compositor session
Documentation=man:systemd.special(7)
BindsTo=graphical-session.target
Wants=graphical-session-pre.target
After=graphical-session-pre.target

@ -1,48 +0,0 @@
---
outputMode: active
scale: 2
background:
red: 0.14
green: 0.14
blue: 0.14
opacity: 1
widget:
margin:
margins: [40, 40, 40, 40]
widget:
verticalLayout:
- horizontalLayout:
- margin:
margins: [0, 176, 0, 64]
widget:
verticalLayout:
- date:
font: ~
font_size: 128.0
- clock:
font: ~
font_size: 512.0
- verticalLayout:
- margin:
margins: [0, 0, 0, 16]
widget:
battery:
font: ~
font_size: 48.0
length: 0
- calendar:
font_primary: ~
font_secondary: ~
font_size: 32.0
sections: 3
- launcher:
font: ~
font_size: 64.0
length: 0
app_opener: "cglaunch"
term_opener: "cglaunch --term"
url_opener: ""
fonts:
sans: sans
mono: mono

@ -0,0 +1,5 @@
# Sign unified images with sbctl keys to support secure boot
uefi_secureboot_cert="/usr/share/secureboot/keys/db/db.pem"
uefi_secureboot_key="/usr/share/secureboot/keys/db/db.key"
# Enable lockdown if secure boot's on to prevent loading unsigned kernel modules
kernel_cmdline+=" lockdown=integrity "

@ -0,0 +1,19 @@
# Do not show systemd messages at startup (quiet)
# Show plymouth splash screen
kernel_cmdline+=" quiet loglevel=3 rd.udev.log_level=3 fbconf=nodefer splash vt.global_cursor_default=0 mem_sleep_default=deep "
# Compress to load faster
compress="zstd"
# Use hostonly to exclude unnecessary modules, but do not include the hostonly
# cmdline in the image, because I rely on discoverable partitions to mount the
# root filesystem.
# See <https://github.com/dracutdevs/dracut/issues/723#issuecomment-792248568>
hostonly="yes"
hostonly_cmdline="no"
# Add video drivers for early KMS
add_drivers+=" i915 "
# Omit bluetooth; I do not have bluetooth hardware I'd need during early boot,
# and as of 2021-12 it fails to build anyway, see
# https://bugs.archlinux.org/task/72463 and https://github.com/dracutdevs/dracut/pull/1671
omit_dracutmodules+=" bluetooth "
# Make sure we have the TPM stack available
add_dracutmodules+=" tpm2-tss "

@ -0,0 +1,8 @@
# Reduce the aggressive defaults of faillock (three failed attempts within 15 minutes lock for 10 minutes) to something
# bearable and pragmatic: 10 failed attempts within 15 minutes lock for 10 minutes
# Ten failed attempts within 15 minutes…
deny = 10
fail_interval = 900
# …lock the system for ten minutes
unlock_time = 600

@ -0,0 +1,3 @@
user-db:user
system-db:gdm
file-db:/usr/share/gdm/greeter-dconf-defaults

@ -1,5 +0,0 @@
[General]
EnableNetworkConfiguration=true
[Network]
EnableIPv6=true

@ -1 +0,0 @@
rd.luks.name=a4a8535e-cd13-4656-8de3-5394281cb369=luks rd.luks.options=fido2-device=auto root=LABEL=btrfs rootflags=subvol=root rw quiet loglevel=3 rd.udev.log_level=3 fbconf=nodefer splash vt.global_cursor_default=0 mem_sleep_default=deep

@ -0,0 +1,7 @@
# Directly boot the default kernel; to make the boot menu appear
# press any key during the firmware splash screen.
timeout 0
# Disable the editor to prevent editing the command line; doesn't matter
# much because in secure boot mode the kernel ignores the boot loader command
# line anyway.
editor no

@ -1,4 +0,0 @@
MODULES=(i915)
BINARIES=(/usr/bin/btrfs)
FILES=()
HOOKS=(base systemd sd-plymouth keyboard autodetect sd-vconsole modconf block sd-encrypt filesystems fsck)

@ -0,0 +1,9 @@
# Managed by my dotfiles
# Blacklist pcspkr to silence beeps
blacklist pcspkr
# See https://wiki.archlinux.org/index.php/Power_management
options snd_hda_intel power_save=1
options snd_ac97_codec power_save=1
options iwlwifi power_save=1
options i915 fastboot=1

@ -1 +0,0 @@
options i915 fastboot=1

@ -0,0 +1,7 @@
[connection]
# Enable mDNS resolving (1) on all interfaces by default, but do not enable
# mDNS responding, i.e. do not register an mDNS hostname for this connection (2)
#
# We use systemd-resolved only for resolution because responding is handled by
# Avahi for proper discovery.
connection.mdns=1

@ -0,0 +1,4 @@
# Enable colors
Color
VerbosePkgLists
ParallelDownloads = 5

@ -0,0 +1,27 @@
# The testing repositories are disabled by default. To enable, uncomment the
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
#[testing]
#Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
#[community-testing]
#Include = /etc/pacman.d/mirrorlist
[community]
Include = /etc/pacman.d/mirrorlist
# If you want to run 32 bit applications on your x86_64 system,
# enable the multilib repositories as required here.
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist
#[multilib]
#Include = /etc/pacman.d/mirrorlist

@ -0,0 +1,8 @@
# If you want to run 32 bit applications on your x86_64 system,
# enable the multilib repositories as required here.
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist
#[multilib]
#Include = /etc/pacman.d/mirrorlist

@ -0,0 +1,4 @@
# aurutils repo
[aur]
SigLevel = Optional TrustAll
Server = file:///var/cache/pacman/aur

@ -0,0 +1,2 @@
[options]
CacheDir = /var/cache/pacman/pkg

@ -0,0 +1,69 @@
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /var/lib/pacman/
#CacheDir = /var/cache/pacman/pkg/
#LogFile = /var/log/pacman.log
#GPGDir = /etc/pacman.d/gnupg/
#HookDir = /etc/pacman.d/hooks/
HoldPkg = pacman glibc
#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
#CleanMethod = KeepInstalled
Architecture = auto
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
#NoExtract =
# Misc options
#UseSyslog
#Color
#NoProgressBar
CheckSpace
#VerbosePkgLists
#ParallelDownloads = 5
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
#RemoteFileSigLevel = Required
# NOTE: You must run `pacman-key --init` before first using pacman; the local
# keyring can then be populated with the keys of all official Arch Linux
# packagers with `pacman-key --populate archlinux`.
#
# REPOSITORIES
# - can be defined here or included from another file
# - pacman will search repositories in the order defined here
# - local/custom mirrors can be added here or in separate files
# - repositories listed first will take precedence when packages
# have identical names, regardless of version number
# - URLs will have $repo replaced by the name of the current repo
# - URLs will have $arch replaced by the name of the architecture
#
# Repository entries are of the format:
# [repo-name]
# Server = ServerName
# Include = IncludePath
#
# The header [repo-name] is crucial - it must be present and
# uncommented to enable the repo.
#
# Include configuration snippets
Include = /etc/pacman.d/conf.d/*.conf

@ -0,0 +1,5 @@
--save /etc/pacman.d/mirrorlist
--protocol https
--country Germany
--latest 5
--sort age

@ -1,46 +0,0 @@
# snap-pac example configuration file
# see snap-pac(8) for more details
# Each section corresponds with a snapper configuration. Add additional sections to add
# other configurations to be snapshotted. By default, only the root configuration is snapshotted.
# Create a section named [DEFAULT] to have a setting apply for all snapper configurations
## Uncomment to set parameters for snapper configuration named root
#[root]
## How many characters to limit the description for snapper.
## Default is 72
#desc_limit = 72
## Whether or not to take snapshots of this snapper configuration
## Default is True for root configuration and False for all other configurations
#snapshot = True
## What snapper cleanup algorithm to use
## Default is number
#cleanup_algorithm = number
## Pre snapshot description.
## Default is the pacman command that triggered the hook
#pre_description = pacman pre snapshot
## Post snapshot description.
## Default is the list of packages involved in the pacman transaction
#post_description = pacman post snapshot
## Uncomment to add "important=yes" to userdata for snapshots referring to these packages
## Default is []
#important_packages = ["linux", "linux-lts"]
## Uncomment to add "important=yes" to userdata for snapshots that were created with the following commands
## Default is []
#important_commands = ["pacman -Syu"]
## Add custom userdata. Each key-value pair should be an item in the list
## Default is []
#userdata = ["key=value","foo=bar"]
## Example for another snapper configuration named "home"
# [home]
## Default is False
# snapshot = True

@ -0,0 +1,35 @@
#
# Refuse to run if unable to disable echo on the tty.
#
Defaults !visiblepw
#
# Preserving HOME has security implications since many programs
# use it when searching for configuration files. Note that HOME
# is already set when the the env_reset option is enabled, so
# this option is only effective for configurations where either
# env_reset is disabled or HOME is present in the env_keep list.
#
Defaults always_set_home
#
# Provide password input feedback.
#
Defaults pwfeedback
#
# Lookup sudoers groups by ID instead of looking up user groups by name;
# we only have one or two groups in this config so looking up by ID is more
# effective.
#
Defaults match_group_by_gid
#
# Keep a bunch of locale settings and other stuff.
#
Defaults env_reset
Defaults env_keep = "COLORS HOSTNAME HISTSIZE LS_COLORS"
Defaults env_keep += "MAIL LANG LC_ADDRESS LC_CTYPE"
Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"

@ -0,0 +1,2 @@
%aurutils ALL = (root) NOPASSWD: SETENV: /usr/bin/makechrootpkg
%aurutils ALL = (root) NOPASSWD: /usr/bin/mkarchroot, /usr/bin/arch-nspawn

@ -0,0 +1,58 @@
# Don't let non-root users get addresses of kernel symbols
kernel.kptr_restrict=1
# Disable kexec to disallow replacing the running kernel.
kernel.kexec_load_disabled=1
# Only let root ptrace processes, for security reasons.
# Perhaps I'll need to disable this again for devtools & debugging
kernel.yama.ptrace_scope=2
# IPv6 Privacy Extensions (RFC 4941)
# ---
# IPv6 typically uses a device's MAC address when choosing an IPv6 address
# to use in autoconfiguration. Privacy extensions allow using a randomly
# generated IPv6 address, which increases privacy.
#
# Acceptable values:
# 0 - don’t use privacy extensions.
# 1 - generate privacy addresses
# 2 - prefer privacy addresses and use them over the normal addresses.
net.ipv6.conf.all.use_tempaddr=2
net.ipv6.conf.default.use_tempaddr=2
# The magic SysRq key enables certain keyboard combinations to be
# interpreted by the kernel to help with debugging. The kernel will respond
# to these keys regardless of the current running applications.
#
# In general, the magic SysRq key is not needed for the average Ubuntu
# system, and having it enabled by default can lead to security issues on
# the console such as being able to dump memory or to kill arbitrary
# processes including the running screen lock.
#
# Here is the list of possible values:
# 0 - disable sysrq completely
# 1 - enable all functions of sysrq
# >1 - enable certain functions by adding up the following values:
# 2 - enable control of console logging level
# 4 - enable control of keyboard (SAK, unraw)
# 8 - enable debugging dumps of processes etc.
# 16 - enable sync command
# 32 - enable remount read-only
# 64 - enable signalling of processes (term, kill, oom-kill)
# 128 - allow reboot/poweroff
# 256 - allow nicing of all RT tasks
#
# For example, to enable both control of console logging level and
# debugging dumps of processes: kernel.sysrq = 10
#
# 128 + 32 + 16
kernel.sysrq=176
# Disable NMI watchdog (powertop recommendation)
kernel.nmi_watchdog=0
# Increase writeback time (default's 500, powertop recommendation)
vm.dirty_writeback_centisecs=1500
# Quiet
kernel.printk = 3 3 3 3

@ -1 +0,0 @@
kernel.printk = 3 3 3 3

@ -1,13 +0,0 @@
[Match]
Name=en*
[Network]
DHCP=yes
[DHCPv4]
RouteMetric=10
UseDomains=true
[IPv6AcceptRA]
RouteMetric=10
UseDomains=yes

@ -1,13 +0,0 @@
[Match]
Name=wl*
[Network]
DHCP=yes
[DHCPv4]
RouteMetric=20
UseDomains=true
[IPv6AcceptRA]
RouteMetric=20
UseDomains=yes

@ -0,0 +1,3 @@
[OOM]
# Reduce default of 30s to 20s; taken from Fedora, so it's likely a good idea
DefaultMemoryPressureDurationSec=20s

@ -0,0 +1,6 @@
# Managed by my dotfiles
[Resolve]
# Resolve mDNS hostnames via resolved, but leave the rest to Avahi
MulticastDNS=resolve
# Enable and enforce DNSSEC
DNSSEC=true

@ -0,0 +1,13 @@
[Slice]
# Monitor all units, slices, etc. for OOM conditions based on current swap usage
# (default limit is 90% swap use). When the system uses more swap than this
# limit system will start acting on control groups using most swap, in order
# of swap usage (see oomd.conf(5) for details).
#
# systemd recommends to set this on the root slice (see systemd-oomd.service(8)).
#
# systemd does not recommend to generally act upon memory pressure, because most
# system services run fine under memory pressure, and latency (i.e. having a
# responsive service) is usually not important for system services (which are
# mostly invisible anyway).
ManagedOOMSwap=kill

@ -0,0 +1,7 @@
[Manager]
# Enable various cgroup accounts to support systemd-oomd.
# See systemd-oomd(1)
DefaultCPUAccounting=true
DefaultIOAccounting=true
DefaultMemoryAccounting=true
DefaultTasksAccounting=true

@ -1,3 +0,0 @@
[Service]
ExecStart=
ExecStart=/usr/bin/agetty --skip-login --nonewline --noissue --autologin tobias --noclear %I $TERM

@ -0,0 +1,3 @@
[Time]
# Default set of NTP servers
NTP=0.de.pool.ntp.org 1.de.pool.ntp.org 2.de.pool.ntp.org 3.de.pool.ntp.org

@ -0,0 +1,17 @@
[Service]
# Allow oomd to act on user units under memory pressure; if a unit is under
# memory pressure for a configured amount of time (see ooomd configuration)
# oomd may kill the unit.
#
# systemd-oomd.service(8) recommends to set this for the user service, to keep
# the user slice responsive. If applications run under memory pressure they
# cease being responsive, so we should kill them early to make sure the system
# stays responsive.
ManagedOOMMemoryPressure=kill
# Reduce the amount of time a unit must be under memory pressure before oomd.
# Overrides the oomd default of 90%, see oomd.conf(5) for the precise meaning
# of this setting.
#
# systemd-oomd.service(8) recommends to reduce this for user services; it says
# 40%, but Fedora's defaults are 50%, so let's follow Fedora here.
ManagedOOMMemoryPressureLimit=50%

@ -1,195 +1,438 @@
#!/usr/bin/env bash
#
# Bootstrap a new Arch system from an installation ISO.
#
# Bootable USB:
# - [Download](https://archlinux.org/download/) ISO and GPG files
# - Verify the ISO file: `$ pacman-key -v archlinux-<version>-x86_64.iso.sig`
# - Create a bootable USB with: `# dd if=archlinux*.iso of=/dev/sdX && sync`
#
# UEFI setup:
#
# - Set boot mode to UEFI, disable Legacy mode entirely.
# - Temporarily disable Secure Boot.
# - Make sure a strong UEFI administrator password is set.
# - Delete preloaded OEM keys for Secure Boot, allow custom ones.
#
# Run installation:
#
# - Connect to wifi via: `# iwctl station wlan0 connect $SSID`
# - Run: `# bash <(curl -sL https://link.rafe.li/dot)`
#
set -uo pipefail
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
args=()
target_device=""
new_hostname=""
while [[ $# -gt 0 ]]
do
arg="$1"
case "$arg" in
"--device")
target_device="$2"
shift
shift
;;
"--hostname")
new_hostname="$2"
shift
shift
;;
*)
args+=("$arg")
shift;
esac
done
PRESERVE_ENV=AUR_PAGER,PACKAGER,EDITOR
if [[ -z "$target_device" ]]; then
echo "Missing --device <device> argument" >&2
exit 2;
if [[ $EUID != 0 ]]; then
echo 'Elevating privileges'
exec sudo --preserve-env="${PRESERVE_ENV}" "$0" "$@"
fi
if [[ -z "$new_hostname" ]]; then
echo "Missing --hostname <hostname> argument" >&2
exit 2;
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
# 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-repositories.conf" \
"$DIR/etc/pacman/60-aurutils-repository.conf" \
"$DIR/etc/pacman/99-options.conf"
# Remove packages no longer in use
to_remove=()
for pkg in "${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
# File systems
ntfs-3g
exfatprogs
btrfs-progs
# Hardware tools
fwupd # Firmware updates
usbutils # for lsusb
# System monitoring
htop
lsof
# Power management
powertop
power-profiles-daemon
# Networking
networkmanager
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
# Build packages
base-devel
namcap
aurpublish # Publish AUR packages from Git subtrees
# Dotfiles manager
chezmoi
# Terminal, shell & tools
man-db
man-pages
code
neovim
exa # Better ls (with git support)
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
# Desktop tools
wl-clipboard
dconf-editor
# Desktop services
xdg-user-dirs
xdg-utils
xdg-desktop-portal
pcsclite # Smartcard daemon, for e-ID
cups
bluez
sane
pipewire-pulse # Pipewire-based pulse-audio, replaces pulseaudio
wireplumber # Recommended pipewire session & policy manager
firefox # Browser
firefox-i18n-de
vlc # Video player
inkscape # Vector graphics
gimp # Pixel graphics
qalculate-gtk # Powerful calculator
libreoffice-fresh
libreoffice-fresh-de
lollypop # Music player
#xournalpp # Handwriting tool
#signal-desktop # Secure mobile messenger
# Fonts & themes
# 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-shell
gnome-shell-extensions
gnome-shell-extension-appindicator
gnome-remote-desktop
gnome-system-monitor
gnome-control-center
gnome-tweaks
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
)
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
# kiconthemes: Additional icons for KDE apps
#breeze-icons
)
pacman -Syu --needed "${packages[@]}"
pacman -S --needed --asdeps "${optdeps[@]}"
pacman -D --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
# 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
)
if [[ -n "${SUDO_USER:-}" ]]; then
# Scrub home directory of my user account
services+=("btrfs-scrub@$(systemd-escape -p "/home/${SUDO_USER}").timer")
fi
if [[ "${#args[@]}" -ne 0 ]]; then
echo "Unexpected extra arguments: ${args[*]}" >&2
exit 2
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.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
if [ ! -f /sys/firmware/efi/fw_platform_size ]; then
echo >&2 "You must boot in UEFI mode to continue"
exit 2
# 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/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
# 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 us
localectl set-x11-keymap --no-convert us,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
# 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
if [[ "$UID" -ne 0 ]]; then
echo "This script needs to be run as root!" >&2
exit 3
# 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
read -rp "THIS SCRIPT WILL OVERWRITE ALL CONTENTS OF ${target_device}. Type uppercase yes to continue: " confirmed
# 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
if [[ "$confirmed" != "YES" ]]; then
echo "aborted" >&2
exit 128
# 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
timedatectl set-ntp true
hwclock --systohc --utc
loadkeys de-latin1
# Partition
sgdisk --zap-all "${target_device}"
sgdisk --clear \
--new 1:0:+550MiB --typecode 1:ef00 --change-name 1:EFI \
--new 2:0:+8GiB --typecode 2:8200 --change-name 2:swap \
--new 3 --typecode 3:8304 --change-name 3:system \
"${target_device}"
# Reload partition table
sleep 5
partprobe -s "${target_device}"
sleep 3
# Encrypt root
echo -n "password" | cryptsetup luksFormat --type luks2 --pbkdf argon2id "/dev/disk/by-partlabel/system"
echo -n "password" | cryptsetup luksOpen --allow-discards --persistent "/dev/disk/by-partlabel/system" system
# Create file systems
mkfs.fat -F 32 -n "EFI" /dev/disk/by-partlabel/EFI
mkfs.btrfs --force --label system /dev/mapper/system
# Mount system subvolume and create additional subvolumes
o=defaults,x-mount.mkdir
o_btrfs=$o,compress=zstd,ssd,noatime
mount -t btrfs LABEL=system /mnt
btrfs subvolume create /mnt/@ # /
btrfs subvolume create /mnt/@home # /home
btrfs subvolume create /mnt/@snapshots # /.snapshots
btrfs subvolume create /mnt/@pkg # /var/cache/pacman/pkg
btrfs subvolume create /mnt/@aurbuild # /var/lib/aurbuild
btrfs subvolume create /mnt/@archbuild # /var/lib/archbuild
btrfs subvolume create /mnt/@log # /var/log
btrfs subvolume create /mnt/@tmp # /var/tmp
umount -R /mnt
mount -t btrfs -o subvol=@,$o_btrfs LABEL=system /mnt
mount -t btrfs -o subvol=@home,$o_btrfs,nodatacow LABEL=system /mnt/home
mount -t btrfs -o subvol=@snapshots,$o_btrfs LABEL=system /mnt/.snapshots
mount -t btrfs -o subvol=@pkg,$o_btrfs LABEL=system /mnt/var/cache/pacman/pkg
mount -t btrfs -o subvol=@aurbuild,$o_btrfs LABEL=system /mnt/var/lib/aurbuild
mount -t btrfs -o subvol=@archbuild,$o_btrfs LABEL=system /mnt/var/lib/archbuild
mount -t btrfs -o subvol=@log,$o_btrfs LABEL=system /mnt/var/log
mount -t btrfs -o subvol=@tmp,$o_btrfs LABEL=system /mnt/var/tmp
# Mount additional partitions
mount -o $o LABEL=EFI /mnt/efi
# Change default btrfs sub-volume (for DPS)
default_subvolume=$(btrfs subvolume list /mnt | grep "path @$" | cut -d ' ' -f2)
btrfs subvolume set-default ${default_subvolume} /mnt
# Disable CoW for /home due to large loopback files by systemd-homed
chattr +C /mnt/home
if ! grep "# Installer cache" /etc/pacman.conf > /dev/null; then
cat >> /etc/pacman.conf << EOF
# Installer cache
[options]
CacheDir = /mnt/var/cache/pacman/pkg
# 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
# Bootstrap new chroot
reflector --country 'Germany' --protocol https --sort age --latest 5 --save /etc/pacman.d/mirrorlist
pacstrap /mnt base linux linux-firmware intel-ucode btrfs-progs dracut neovim iwd networkmanager
genfstab -L -p /mnt >> /mnt/etc/fstab
# Configure timezone, locale, keymap, network
sed -i 's/^#en_US\.UTF-8/en_US\.UTF-8/' /mnt/etc/locale.gen
sed -i 's/^#de_DE\.UTF-8/de_DE\.UTF-8/' /mnt/etc/locale.gen
arch-chroot /mnt locale-gen
arch-chroot /mnt systemd-firstboot \
--locale="en_US.UTF-8" \
--keymap="de-latin1" \
--timezone="Europe/Berlin" \
--hostname="${new_hostname}" \
--setup-machine-id
echo -e "127.0.0.1\tlocalhost" >> /mnt/etc/hosts
echo -e "127.0.1.1\t$new_hostname" >> /mnt/etc/hosts
echo -e "\n::1\tlocalhost" >> /mnt/etc/hosts
# Use systemd-resolved as dns backend for NetworkManager (auto-detected)
ln -sf /run/systemd/resolve/stub-resolv.conf /mnt/etc/resolv.conf
# Enable iwd as wifi backend for NetworkManager
cat > /mnt/etc/NetworkManager/conf.d/wifi-backend.conf <<EOF
[device]
wifi.backend=iwd
# 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]