Skip to content

Instantly share code, notes, and snippets.

@Th3Whit3Wolf
Last active December 20, 2024 21:43
Show Gist options
  • Save Th3Whit3Wolf/2f24b29183be7f8e9c0b05115aefb693 to your computer and use it in GitHub Desktop.
Save Th3Whit3Wolf/2f24b29183be7f8e9c0b05115aefb693 to your computer and use it in GitHub Desktop.
My install instruction for a secure Arch Linux (sway) laptop workstation

What's Cool

  • Encrypted root partition
    • AES-256 bit cipher
    • Argon2id variant for PBKDF
    • Sha3-512 bit hash
  • rEFInd bootloader
    • With dreary theme
    • Optimal Settings (optimized for aesthetics, and boot time)
    • Boot into backups thanks to refind-btrfs
  • Optimized Settings
    • pacman.conf (optimized for aesthetics and use)
    • makepkg.conf (optimized for faster binaries)
  • Xanmod Cacule Linux Kernel
    • Preemptive Full Tickless Kernel at 500Hz w/ Tuned CPU Core Scheduler.
    • RCU Boost for better responsiveness and lower overall system latency.
    • Full multi-core block layer runqueue requests for high I/O throughput.
    • Caching, Virtual Memory Manager and CPUFreq Governor improvements.
    • BBR TCP Congestion Control + FQ-PIE Packet Scheduling and AQM Algorithm [5.10].
    • ORC Unwinder for Kernel Stack Traces (debuginfo) implementation.
    • Third-party patchset available: BBRv2 TCP Congestion [5.10][as module], ZSTD kernel, initrd and modules support [5.10], Clear Linux [partial], CK's Hrtimer patchset, Proton Fsync support, PCIe ACS Override, Aufs [5.4] and Graysky's GCC patchset.
    • Btrfs Checksum hardware acceleration
    • High responsiveness CacULE scheduler (SCHED_NORMAL) based on ULE interactivity score mechanism build available [5.10-cacule]
      • Each CPU has its own runqueue.
      • NORMAL runqueue is a linked list of sched_entities (instead of RB-Tree).
      • RT and other runqueues are just the same as the CFS's.
      • Wake up tasks preempt currently running tasks if its interactivity score value is higher
  • Miscellaneous
    • Secureboot
    • Udev rule for faster IO performance from NVME and SSD
    • Hooks for zsh and secureboot
    • Improved laptop battery life
      • Zram
      • Btrfs
      • Profile-sync-daemon
    • Automatic CPU frequency scaling depending on load
    • Improved system responsiveness in low memory situations
      • Nohang, an OOM prevention daemon
      • Prelockd, a daemon that locks memory mapped executables & shared libraries in memory to improve system responsiveness
      • Memavaild, improve responsiveness during heavy swapping
    • Zram, compressed swap in ram - Faster swap & less drive writes (longer ssd lifespan)
    • Profile-sync-daemon, faster web browsing experience and less drive writes (longer ssd lifespan)
    • Improved security
      • Nftables Firewall
      • Apparmor
      • SSHGuard
      • Stricter Mount Options
      • Stricter File access permissions
      • Enforce a delay after a failed login attempt
      • Restricting access to kernel pointers in the proc filesystem
      • BPF hardening
      • Restrict access to kernel logs
      • Disable kexec
      • Intitialize lsm (required to set lockdown mode)
      • Disabled Unprivileged user namespace usage
      • TCP SYN cookie protection
      • Protect against tcp time-wait assassination hazards
      • Reverse path filtering (helps protect against attackers that are using IP spoofing methods to do harm)
      • Disable ICMP redirects
      • Automatic logout for vtconsole
      • Wayland (unlike x11 applications have GUI-Level isolation)
    • Cgroups V2
    • Docker using IPV6
    • Most responsive DNS autoupdater (lower latency network connections)
    • Fastest Arch Linux mirror list autoupdater
    • Automount USB
    • All the codecs, encryption, and archive formats you could want
    • Wayland
    • Chrony for NTP (Best NTP for laptops)
    • Btrfs filesystem
      • Optimized mount settings (optimized for IO, storage, and drive lifespan)
      • Snapshots
        • On initial install
        • Pre/Post package install/uninstall/updates
        • Daily

What this is not

  • A minimal or generic arch linux install

This guide should allow you to make an optimized, complete, secure Arch Linux install with out having to touch an editor except for when editing PKGBUILD for linux-xanmod-cacule

Why GDM

  • Only wayland login manager
  • Can unlock gnome-keyring on automatic login when password is set to LUKS password

This means after I unlock LUKS I don't need to enter any more password. SSH, git, and GPG passwords are automatically used without me entering them(after you enter them the first time).

Prologue

If possible you'll have much nicer experience installing arch if you ssh into the machine you want to install arch onto from another machine

In the desired arch laptop after booting up the archiso set the password.

passwd

Start the ssh daemon

systemctl start sshd.service

Connect to wifi

iwctl

Get your IP address

ip a

Step 1 - Partitioning

cfdisk /dev/nvme0n1 # replace nvme0n1 with your drive

Step 2 Encrypt Partition

cryptsetup luksFormat --perf-no_read_workqueue --perf-no_write_workqueue --type luks2 --cipher aes-xts-plain64 --key-size 512 --iter-time 2000 --pbkdf argon2id --hash sha3-512 /dev/nvme0n1p2
cryptsetup --allow-discards --perf-no_read_workqueue --perf-no_write_workqueue --persistent open /dev/nvme0n1p2 crypt

Step 3 - Formatting the partitions

mkfs.vfat -F32 -n "EFI" /dev/nvme0n1p1
mkfs.btrfs -L Arch -f /dev/mapper/crypt

Step 4 - Create and Mount Subvolumes

Create subvolumes for root, home, snapshots, swap, the entire Btrfs file system, and for things that are not worth being snapshotted, like /var/cache, /var/abs, /var/tmp, and /srv.

mount /dev/mapper/crypt /mnt
btrfs sub create /mnt/@ && \
btrfs sub create /mnt/@home && \
btrfs sub create /mnt/@abs && \
btrfs sub create /mnt/@tmp && \
btrfs sub create /mnt/@srv && \
btrfs sub create /mnt/@snapshots && \
btrfs sub create /mnt/@btrfs && \
btrfs sub create /mnt/@log && \
btrfs sub create /mnt/@cache
umount /mnt

Mount the subvolumes

mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@ /dev/mapper/crypt /mnt
mkdir -p /mnt/{boot,home,var/cache,var/log,.snapshots,btrfs,var/tmp,var/abs,srv}
mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@home /dev/mapper/crypt /mnt/home  && \
mount -o nodev,nosuid,noexec,noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@abs /dev/mapper/crypt /mnt/var/abs && \
mount -o nodev,nosuid,noexec,noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@tmp /dev/mapper/crypt /mnt/var/tmp && \
mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@srv /dev/mapper/crypt /mnt/srv && \
mount -o nodev,nosuid,noexec,noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@log /dev/mapper/crypt /mnt/var/log && \
mount -o nodev,nosuid,noexec,noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@cache /dev/mapper/crypt /mnt/var/cache && \
mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@snapshots /dev/mapper/crypt /mnt/.snapshots && \
mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvolid=5 /dev/mapper/crypt /mnt/btrfs

NOTE

  • nodev - Do not interpret character or block special devices on the file system
  • nosuid - Do not allow set-user-identifier or set-group-identifier bits to take effect
  • noexec - Do not allow direct execution of any binaries on the mounted file system
  • discard=async - Freed extents are not discarded immediately, but grouped together and trimmed later by a separate worker thread, improving commit latency
  • compress-force=zstd - empirical testing on multiple mixed-use systems showed a significant improvement of about 10% disk compression from using compress-force=zstd over just compress=zstd (which also had 10% disk compression), resulting in a total effective disk space saving of 20%.
  • noatime - The noatime option is known to improve performance of the filesystem. It also disables disk writes when a file is read, prolongin the lifespan of SSDs.
  • commit - The resolution at which data are written to the filesystem is dictated by Btrfs itself and by system-wide settings. This means less writes (prolongs SSD lifespan) and better performance (multiple writes are combined into one single larger write, updates to previous writes within the commit time frame are cancelled out).
  • space_cache - Btrfs stores the free space data ondisk to make the caching of a block group much quicker.
  • autodefrag – will detect random writes into existing files and kick off background defragging. It is well suited to bdb or sqlite databases, but not virtualization images or big databases (yet). Once the developers make sure it doesn’t defrag files over and over again, they’ll move this toward the default
  • ssd - tells btrfs to use SSD Specific options

It's recommended if we have VMs or databases, to disable copy-on-write (COW).

mkdir -p /mnt/var/lib/{docker,machines,mysql,postgres} && \
chattr +C /mnt/var/lib/{docker,machines,mysql,postgres}

Mount the EFI partition

mount -o nodev,nosuid,noexec /dev/nvme0n1p1 /mnt/boot

Step 5 - Base System and /etc/fstab

(this is the time where you change the mirrorlist, if that's your thing) The following assumes you have an AMD CPU & GPU

pacstrap /mnt base base-devel linux linux-firmware amd-ucode btrfs-progs git go \
    kanshi zstd iwd networkmanager mesa vulkan-radeon libva-mesa-driver openssh \
    mesa-vdpau xf86-video-amdgpu docker libvirt qemu refind rustup wl-clipboard \
    zsh sshguard npm bc ripgrep bat tokei hyperfine rust-analyzer xdg-user-dirs \
    systemd-swap pigz pbzip2 snapper chrony noto-fonts a52dec faac iptables-nft \
    tlp faad2 flac jasper grim libdca libdv libmad libmpeg2 libtheora libvorbis \
    waybar wavpack xvidcore libde265 gstreamer gst-libav gst-plugins-bad breeze \
    gst-plugins-base gst-plugins-good gst-plugins-ugly gstreamer-vaapi seahorse \
    sway lollypop alacritty wofi polkit-gnome mako slurp xdg-desktop-portal-wlr \
    gvfs libxv libsecret gnome-keyring nautilus nautilus-image-converter gdm fd \
    xarchiver arj cpio lha udiskie nautilus-share nautilus-sendto imv mpv lrzip \
    unrar zip chezmoi powertop brightnessctl lastpass-cli sbsigntools x264 lzip \
    xorg-xwayland apparmor ttf-roboto ttf-roboto-mono ttf-dejavu ttf-liberation \
    ttf-fira-code ttf-hanazono ttf-fira-mono seahorse-nautilus exa ttf-opensans \
    pulseaudio lzop p7zip ttf-hack noto-fonts noto-fonts-emoji ttf-font-awesome \
    ttf-droid adobe-source-code-pro-fonts firefox-decentraleyes libva-utils man \
    firefox-dark-reader lame network-manager-applet unarj blueman yarn npm code \
    firefox-ublock-origin irqbalance swayidle haveged profile-sync-daemon shfmt \
    compsize pipewire-pulse pipewire-jack pipewire-alsa gnome-boxes wf-recorder \
    dbus-broker wireplumber skim youtube-dl nftables python-nautilus celluloid \
    entr reflector postgresql tmux gnome-podcasts

generate the fstab

genfstab -U /mnt > /mnt/etc/fstab

Step 6 - System Configuration

Use timedatectl(1) to ensure the system clock is accurate

timedatectl set-ntp true

Add some zsh configs for a nicer experience

cp /etc/zsh/zprofile /mnt/root/.zprofile && \
cp /etc/zsh/zshrc /mnt/root/.zshrc

Add pacman mirrorlist

cp /etc/pacman.d/mirrorlist /mnt/etc/pacman.d/mirrorlist

Chroot into the new system

arch-chroot /mnt /bin/zsh

Export some variables

export USER=username      # Replace username with the name for your new user
export HOST=hostname      # Replace hostname with the name for your host
export TZ="Europe/London" # Replace Europe/London with your Region/City

Set root password & shell

passwd && \
chsh -s /bin/zsh

Set locale

echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen && \
echo "LANG=\"en_US.UTF-8\"" > /etc/locale.conf && \
echo "KEYMAP=us" > /etc/vconsole.conf && \
export LANG="en_US.UTF-8" && \
export LC_COLLATE="C"

Set timezone

ln -sf /usr/share/zoneinfo/$TZ /etc/localtime  && \
hwclock -uw # or hwclock --systohc --utc

Set Hostname

echo $HOST > /etc/hostname

Add user

WARNING Giving a user passwordless sudo is not safe, I put it in only for my own convenience. You may replace echo "$USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \ with echo "$USER ALL=(ALL) ALL" >> /etc/sudoers && \ to have sudo only with passwd

WARNING Anyone added to the docker group is root equivalent because they can use the docker run --privileged command to start containers with root privileges. For more information see 3 and 4.

useradd -m -G  docker,input,kvm,libvirt,storage,video,wheel -s /bin/zsh $USER && \
passwd $USER && \
echo "$USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
echo "Defaults timestamp_timeout=0" >> /etc/sudoers

NOTE

  • docker - Members of docker group are able to run the docker CLI command as a non-root user
  • input - Access to input devices.
  • kvm - Access to virtual machines using KVM.
  • libvirt - Members of the libvirt group have passwordless access to the RW daemon socket by default
  • storage - Used to gain access to removable drives such as USB hard drives, flash/jump drives, MP3 players; enables the user to mount storage devices.
  • video - Access to video capture devices, 2D/3D hardware acceleration, framebuffer
  • wheel - Administration group, commonly used to give privileges to perform administrative actions. It has full read access to journal files and the right to administer printers in CUPS. Can also be used to give access to the sudo and su utilities (neither uses it by default).

Set hosts

cat << EOF >> /etc/hosts
# <ip-address>	<hostname.domain.org>	<hostname>
127.0.0.1	localhost
::1		localhost
127.0.1.1	$HOST.localdomain	$HOST
EOF

Step 6 - fix the mkinitcpio.conf to contain what we actually need.

sed -i 's/BINARIES=()/BINARIES=("\/usr\/bin\/btrfs")/' /etc/mkinitcpio.conf && \
sed -i 's/MODULES=()/MODULES=(amdgpu)/' /etc/mkinitcpio.conf && \
sed -i 's/#COMPRESSION="lz4"/COMPRESSION="lz4"/' /etc/mkinitcpio.conf && \
sed -i 's/#COMPRESSION_OPTIONS=()/COMPRESSION_OPTIONS=(-9)/' /etc/mkinitcpio.conf && \
sed -i 's/^HOOKS.*/HOOKS=(base systemd autodetect modconf block sd-encrypt filesystems keyboard fsck)/' /etc/mkinitcpio.conf
# if you have more than 1 btrfs drive
# sed -i 's/^HOOKS.*/HOOKS=(base systemd autodetect modconf block sd-encrypt resume btrfs filesystems keyboard fsck)/' mkinitcpio.conf

mkinitcpio -p linux

Step 7 - Quality of Life Improvements

Laptop Power Saving Improvements

Audio

By default, audio power saving is turned off by most drivers. It can be enabled by setting the power_save parameter; a time (in seconds) to go into idle mode.

If lspci -k | grep snd_ac97_codec returns Kernel driver in use: snd_hda_intel, then run the following command to idle the audio card after one second.

echo "options snd_hda_intel power_save=1" > /etc/modprobe.d/audio_powersave.conf

Otherwise

echo "options snd_ac97_codec power_save=1" > /etc/modprobe.d/audio_powersave.conf

PulseAudio

By default, PulseAudio suspends any audio sources that have become idle for too long. When using an external USB microphone, recordings may start with a pop sound. As a workaround, comment out load-module module-suspend-on-idle in /etc/pulse/default.pa

sed -i 's/load-module module-suspend-on-idle/#load-module module-suspend-on-idle/' /etc/pulse/default.pa

Wifi

Additional power saving functions of Intel wireless cards with iwlwifi driver can be enabled by passing the correct parameters to the kernel module. Making them persistent can be achieved by adding the lines below to the /etc/modprobe.d/iwlwifi.conf file.

echo "options iwlwifi power_save=1" >> /etc/modprobe.d/iwlwifi.conf

This option will probably increase your median latency:

options iwlwifi uapsd_disable=0 >> /etc/modprobe.d/iwlwifi.conf

If lsmod | grep '^iwl.vm' returns iwlmvm

echo "options iwlmvm power_scheme=3" >> /etc/modprobe.d/iwlwifi.conf

If lsmod | grep '^iwl.vm' returns iwlmvm

echo "options iwldvm force_cam=0" >> /etc/modprobe.d/iwlwifi.conf

SATA Active Link Power Management

Since Linux 4.15 there is a new setting called med_power_with_dipm that matches the behaviour of Windows IRST driver settings and should not cause data loss with recent SSD/HDD drives. The power saving can be significant, ranging from 1.0 to 1.5 Watts (when idle).

echo 'ACTION=="add", SUBSYSTEM=="scsi_host", KERNEL=="host*", ATTR{link_power_management_policy}="med_power_with_dipm"' > /etc/udev/rules.d/hd_power_save.rules

Here are some sensible default settings for TLP

cat << EOF > /etc/tlp.conf
SATA_LINKPWR_ON_AC="max_performance"
SATA_LINKPWR_ON_BAT="med_power_with_dipm"
RADEON_POWER_PROFILE_ON_AC="high"
RADEON_POWER_PROFILE_ON_BAT="low"
RESTORE_DEVICE_STATE_ON_STARTUP="1"
EOF

Set Network Manager iwd backend

cat << EOF >> /etc/NetworkManager/conf.d/nm.conf
[device]
wifi.backend=iwd
EOF

Preventing snapshot slowdowns

echo 'PRUNENAMES = ".snapshots"' >> /etc/updatedb.conf

Set reflector up

cat << EOF > /etc/xdg/reflector/reflector.conf
# Set the output path where the mirrorlist will be saved (--save).
--save /etc/pacman.d/mirrorlist
# Select the transfer protocol (--protocol).
--protocol https
# Use only the  most recently synchronized mirrors (--latest).
--latest 100
# Sort the mirrors by MirrorStatus score
--sort score
EOF

Autosign Kernel

mkdir /etc/pacman.d/hooks && cat << EOF > /etc/pacman.d/hooks/999-sign_kernel_for_secureboot.hook
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = linux
Target = linux-lts
Target = linux-hardened
Target = linux-zen
Target = linux-xanmod
Target = linux-xanmod-cacule
Target = linux-xanmod-git
Target = linux-xanmod-lts
Target = linux-xanmod-rt
Target = linux-xanmod-anbox

[Action]
Description = Signing kernel with Machine Owner Key for Secure Boot
When = PostTransaction
Exec = /usr/bin/fd vmlinuz /boot -d 1 -x /usr/bin/sbsign --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output {} {}
Depends = sbsigntools
Depends = fd
EOF

Update rEFInd ESP on update

cat << EOF > /etc/pacman.d/hooks/refind.hook
[Trigger]
Operation=Upgrade
Type=Package
Target=refind

[Action]
Description = Updating rEFInd on ESP
When=PostTransaction
Exec=/usr/bin/refind-install --shim /usr/share/shim-signed/shimx64.efi --localkeys
EOF

Zsh hook

cat << EOF > /etc/pacman.d/hooks/zsh.hook
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = usr/bin/*
[Action]
Depends = zsh
When = PostTransaction
Exec = /usr/bin/install -Dm644 /dev/null /var/cache/zsh/pacman
EOF

Reflector hook

cat << EOF > /etc/pacman.d/hooks/mirrorupgrade.hook
[Trigger]
Operation = Upgrade
Type = Package
Target = pacman-mirrorlist

[Action]
Description = Updating pacman-mirrorlist with reflector and removing pacnew...
When = PostTransaction
Depends = reflector
Exec = /bin/sh -c 'systemctl start reflector.service; if [ -f /etc/pacman.d/mirrorlist.pacnew ]; then rm /etc/pacman.d/mirrorlist.pacnew; fi'
EOF

Better IO Scheduler

cat << EOF > /etc/udev/rules.d/60-ioschedulers.rules
# set scheduler for NVMe
ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="none"
# set scheduler for SSD and eMMC
ACTION=="add|change", KERNEL=="sd[a-z]|mmcblk[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
# set scheduler for rotating disks
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
EOF

Create zram

cat << EOF > /etc/systemd/swap.conf
#  This file is part of systemd-swap.
#
# Entries in this file show the systemd-swap defaults as
# specified in /usr/share/systemd-swap/swap-default.conf
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See swap.conf(5) and /usr/share/systemd-swap/swap-default.conf for details.
zram_enabled=1
zswap_enabled=0
swapfc_enabled=0
zram_size=\$(( RAM_SIZE / 4 ))
EOF

Optimize Makepkg

sed -i 's/^CFLAGS.*/CFLAGS="-march=native -mtune=native -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -fno-plt"/' /etc/makepkg.conf && \
sed -i 's/^CXXFLAGS.*/CXXFLAGS="-march=native -mtune=native -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -fno-plt"/' /etc/makepkg.conf && \
sed -i 's/^#RUSTFLAGS.*/RUSTFLAGS="-C opt-level=2 -C target-cpu=native"/' /etc/makepkg.conf && \
sed -i 's/^#BUILDDIR.*/BUILDDIR=\/tmp\/makepkg/' /etc/makepkg.conf && \
sed -i 's/^#MAKEFLAGS.*/MAKEFLAGS="-j$(getconf _NPROCESSORS_ONLN) --quiet"/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSGZ.*/COMPRESSGZ=(pigz -c -f -n)/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSBZ2.*/COMPRESSBZ2=(pbzip2 -c -f)/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSXZ.*/COMPRESSXZ=(xz -T "$(getconf _NPROCESSORS_ONLN)" -c -z --best -)/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSZST.*/COMPRESSZST=(zstd -c -z -q --ultra -T0 -22 -)/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSLZ.*/COMPRESSLZ=(lzip -c -f)/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSLRZ.*/COMPRESSLRZ=(lrzip -9 -q)/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSLZO.*/COMPRESSLZO=(lzop -q --best)/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSZ.*/COMPRESSZ=(compress -c -f)/' /etc/makepkg.conf && \
sed -i 's/^COMPRESSLZ4.*/COMPRESSLZ4=(lz4 -q --best)/' /etc/makepkg.conf

Pacman

sed -i 's/#UseSyslog/UseSyslog/' /etc/pacman.conf && \
sed -i 's/#Color/Color\\\nILoveCandy/' /etc/pacman.conf && \
sed -i 's/Color\\/Color/' /etc/pacman.conf && \
sed -i 's/#TotalDownload/TotalDownload/' /etc/pacman.conf && \
sed -i 's/#CheckSpace/CheckSpace/' /etc/pacman.conf

Chrony

cat <<EOF > /etc/chrony.conf
# Use public NTP servers from the pool.ntp.org project.
server 0.pool.ntp.org offline
server 1.pool.ntp.org offline
server 2.pool.ntp.org offline
server 3.pool.ntp.org offline

# Record the rate at which the system clock gains/losses time.
driftfile /etc/chrony.drift

# In first three updates step the system clock instead of slew
# if the adjustment is larger than 1 second.
makestep 1.0 3

# Enable kernel synchronization of the real-time clock (RTC).
rtcsync

rtconutc
EOF

Chrony work with Network Manager

cat << EOF > /etc/NetworkManager/dispatcher.d/10-chrony
#!/bin/sh

INTERFACE=\$1
STATUS=\$2

# Make sure we're always getting the standard response strings
LANG='C'

CHRONY=\$(which chronyc)

chrony_cmd() {
    echo "Chrony going \$1."
    exec \$CHRONY -a \$1
}

nm_connected() {
    [ "\$(nmcli -t --fields STATE g)" = 'connected' ]
}

case "\$STATUS" in
    up)
        chrony_cmd online
    ;;
    vpn-up)
        chrony_cmd online
    ;;
    down)
        # Check for active interface, take offline if none is active
        nm_connected || chrony_cmd offline
    ;;
    vpn-down)
        # Check for active interface, take offline if none is active
        nm_connected || chrony_cmd offline
    ;;
EOF
chmod +x /etc/NetworkManager/dispatcher.d/10-chrony

Docker use IPV6 & Btrfs

mkdir /etc/docker && cat << EOF > /etc/docker/daemon.json
{
  "ipv6": true,
  "fixed-cidr-v6": "fd00::/80",
  "storage-driver": "btrfs"
}
EOF

Security & Performance

sed -i 's/^umask.*/umask\ 077/' /etc/profile && \
chmod 700 /etc/{iptables,arptables,nftables.conf} && \
echo "auth optional pam_faildelay.so delay=4000000" >> /etc/pam.d/system-login && \
echo "tcp_bbr" > /etc/modules-load.d/bbr.conf && \
echo "write-cache" > /etc/apparmor/parser.conf
cat << EOF >/etc/sysctl.d/99-sysctl-performance-tweaks.conf
# The swappiness sysctl parameter represents the kernel's preference (or avoidance) of swap space. Swappiness can have a value between 0 and 100, the default value is 60. 
# A low value causes the kernel to avoid swapping, a higher value causes the kernel to try to use swap space. Using a low value on sufficient memory is known to improve responsiveness on many systems.
vm.swappiness=10

# The value controls the tendency of the kernel to reclaim the memory which is used for caching of directory and inode objects (VFS cache). 
# Lowering it from the default value of 100 makes the kernel less inclined to reclaim VFS cache (do not set it to 0, this may produce out-of-memory conditions)
vm.vfs_cache_pressure=50

# This action will speed up your boot and shutdown, because one less module is loaded. Additionally disabling watchdog timers increases performance and lowers power consumption
# Disable NMI watchdog
#kernel.nmi_watchdog = 0

# Contains, as a percentage of total available memory that contains free pages and reclaimable
# pages, the number of pages at which a process which is generating disk writes will itself start
# writing out dirty data (Default is 20).
vm.dirty_ratio = 5

# Contains, as a percentage of total available memory that contains free pages and reclaimable
# pages, the number of pages at which the background kernel flusher threads will start writing out
# dirty data (Default is 10).
vm.dirty_background_ratio = 5

# This tunable is used to define when dirty data is old enough to be eligible for writeout by the
# kernel flusher threads.  It is expressed in 100'ths of a second.  Data which has been dirty
# in-memory for longer than this interval will be written out next time a flusher thread wakes up
# (Default is 3000).
#vm.dirty_expire_centisecs = 3000

# The kernel flusher threads will periodically wake up and write old data out to disk.  This
# tunable expresses the interval between those wakeups, in 100'ths of a second (Default is 500).
vm.dirty_writeback_centisecs = 1500

# Enable the sysctl setting kernel.unprivileged_userns_clone to allow normal users to run unprivileged containers.
kernel.unprivileged_userns_clone=1

# To hide any kernel messages from the console
kernel.printk = 3 3 3 3

# Restricting access to kernel logs
kernel.dmesg_restrict = 1

# Restricting access to kernel pointers in the proc filesystem
kernel.kptr_restrict = 2

# Disable Kexec, which allows replacing the current running kernel. 
kernel.kexec_load_disabled = 1

# Increasing the size of the receive queue.
# The received frames will be stored in this queue after taking them from the ring buffer on the network card.
# Increasing this value for high speed cards may help prevent losing packets: 
net.core.netdev_max_backlog = 16384

# Increase the maximum connections
#The upper limit on how many connections the kernel will accept (default 128): 
net.core.somaxconn = 8192

# Increase the memory dedicated to the network interfaces
# The default the Linux network stack is not configured for high speed large file transfer across WAN links (i.e. handle more network packets) and setting the correct values may save memory resources: 
net.core.rmem_default = 1048576
net.core.rmem_max = 16777216
net.core.wmem_default = 1048576
net.core.wmem_max = 16777216
net.core.optmem_max = 65536
net.ipv4.tcp_rmem = 4096 1048576 2097152
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192

# Enable TCP Fast Open
# TCP Fast Open is an extension to the transmission control protocol (TCP) that helps reduce network latency
# by enabling data to be exchanged during the sender’s initial TCP SYN [3]. 
# Using the value 3 instead of the default 1 allows TCP Fast Open for both incoming and outgoing connections: 
net.ipv4.tcp_fastopen = 3

# Enable BBR
# The BBR congestion control algorithm can help achieve higher bandwidths and lower latencies for internet traffic
net.core.default_qdisc = cake
net.ipv4.tcp_congestion_control = bbr

# TCP SYN cookie protection
# Helps protect against SYN flood attacks. Only kicks in when net.ipv4.tcp_max_syn_backlog is reached: 
net.ipv4.tcp_syncookies = 1

# Protect against tcp time-wait assassination hazards, drop RST packets for sockets in the time-wait state. Not widely supported outside of Linux, but conforms to RFC: 
net.ipv4.tcp_rfc1337 = 1

# By enabling reverse path filtering, the kernel will do source validation of the packets received from all the interfaces on the machine. This can protect from attackers that are using IP spoofing methods to do harm. 
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

# Disable ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# To use the new FQ-PIE Queue Discipline (>= Linux 5.6) in systems with systemd (>= 217), will need to replace the default fq_codel. 
net.core.default_qdisc = fq_pie
EOF

Nftables Firewall

cat << EOF > /etc/nftables.conf
flush ruleset

table ip filter {
  chain DOCKER-USER {
    mark set 1
  }
}

table inet my_table {
	chain my_input {
		type filter hook input priority 0; policy drop;

		iif lo accept comment "Accept any localhost traffic"
		ct state invalid drop comment "Drop invalid connections"
		
		meta l4proto icmp icmp type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods"
		meta l4proto ipv6-icmp icmpv6 type echo-request limit rate over 10/second burst 4 packets drop comment "No ping floods"

		ct state established,related accept comment "Accept traffic originated from us"

		meta l4proto ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept comment "Accept ICMPv6"
		meta l4proto ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept comment "Accept ICMPv6"
		meta l4proto icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept comment "Accept ICMP"
		ip protocol igmp accept comment "Accept IGMP"

		tcp dport ssh ct state new limit rate 15/minute accept comment "Avoid brute force on SSH"

		udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS"
		udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS"

		udp sport 1900 udp dport >= 1024 ip6 saddr { fd00::/8, fe80::/10 } meta pkttype unicast limit rate 4/second burst 20 packets accept comment "Accept UPnP IGD port mapping reply"
		udp sport 1900 udp dport >= 1024 ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 } meta pkttype unicast limit rate 4/second burst 20 packets accept comment "Accept UPnP IGD port mapping reply"

		udp sport netbios-ns udp dport >= 1024 meta pkttype unicast ip6 saddr { fd00::/8, fe80::/10 } accept comment "Accept Samba Workgroup browsing replies"
		udp sport netbios-ns udp dport >= 1024 meta pkttype unicast ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 } accept comment "Accept Samba Workgroup browsing replies"

		counter comment "Count any other traffic"
	}

	chain my_forward {
		type filter hook forward priority security; policy drop;
  		mark 1 accept
		# Drop everything forwarded to that's not from docker us. We do not forward. That is routers job.
	}

	chain my_output {
		type filter hook output priority 0; policy accept;
		# Accept every outbound connection
	}

}

table inet dev {
    set blackhole {
        type ipv4_addr;
        flags dynamic, timeout;
        size 65536;
    }

    chain input {
        ct state new tcp dport 443 \
                meter flood size 128000 { ip saddr timeout 10s limit rate over 10/second } \
                add @blackhole { ip saddr timeout 1m }

        ip saddr @blackhole counter drop
    }
}
EOF

SSHGuard

cat << EOF > /etc/sshguard.conf
# Full path to backend executable (required, no default)
BACKEND="/usr/lib/sshguard/sshg-fw-nft-sets"

# Log reader command (optional, no default)
LOGREADER="LANG=C /usr/bin/journalctl -afb -p info -n1 -t sshd -t vsftpd -o cat"

# How many problematic attempts trigger a block
THRESHOLD=20
# Blocks last at least 180 seconds
BLOCK_TIME=180
# The attackers are remembered for up to 3600 seconds
DETECTION_TIME=3600

# Blacklist threshold and file name
BLACKLIST_FILE=100:/var/db/sshguard/blacklist.db

# IPv6 subnet size to block. Defaults to a single address, CIDR notation. (optional, default to 128)
IPV6_SUBNET=64
# IPv4 subnet size to block. Defaults to a single address, CIDR notation. (optional, default to 32)
IPV4_SUBNET=24
EOF

Automatic logout

cat << EOF > /etc/profile.d/shell-timeout.sh
TMOUT="\$(( 60*30 ))";
[ -z "\$DISPLAY" ] && export TMOUT;
case \$( /usr/bin/tty ) in
	/dev/tty[0-9]*) export TMOUT;;
esac
EOF

Prepare gnome-keyring-daemon

cat <<EOF > /etc/pam.d/login
#%PAM-1.0
 
auth       required     pam_securetty.so
auth       requisite    pam_nologin.so
auth       include      system-local-login
auth       optional     pam_gnome_keyring.so
account    include      system-local-login
session    include      system-local-login
session    optional     pam_gnome_keyring.so auto_start
EOF
cat <<EOF > /etc/pam.d/passwd
#%PAM-1.0

#password	required	pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 retry=3
#password	required	pam_unix.so sha512 shadow use_authtok
password	required	pam_unix.so sha512 shadow nullok
password	optional	pam_gnome_keyring.so
EOF

Set ZDOTDIR (this will help declutter the home directory

cat << EOF > /etc/zsh/zshenv
export ZDOTDIR=$HOME/.config/zsh
export HISTFILE="$XDG_DATA_HOME"/zsh/history
EOF

Setup PostgreSQL

su -l postgres
initdb --locale=en_US.UTF-8 -E UTF8 -D /var/lib/postgres/data && \
exit

cat << EOF > /var/lib/postgres/data/postgresql.conf
stats_temp_directory = '/run/postgresql'
EOF

Step 8 - Setup the user & configure the bootloader

Install AUR helper

su $USER
cd ~  && \
git clone https://aur.archlinux.org/yay.git && \
cd yay && \
makepkg -si && \
cd .. && \
sudo rm -dR yay

Sign bootloader & kernel for Secure Boot

yay --noremovemake --nodiffmenu -S shim-signed && \
sudo refind-install --shim /usr/share/shim-signed/shimx64.efi --localkeys && \
sudo sbsign --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output /boot/vmlinuz-linux /boot/vmlinuz-linux

Add some user niceties whiler you are there

rustup default stable && \
yay --noremovemake --nodiffmenu --batchinstall -S otf-san-francisco fedora-firefox-wayland-bin \
    otf-san-francisco pamac-aur starship-bin firefox-extension-amazon-container \
    gst-plugin-libde265 firefox-extension-privacybadger poweralertd zoxide-bin \
    firefox-extension-https-everywhere firefox-extension-facebook-container wob \
    firefox-extension-containerise ananicy-git lastpass nwg-launchers persway \
    neovim-nightly-git swaylock-effects-git lazygit-bin grimshot memavaild \
    prelockd nohang-git auto-cpufreq-git otf-nerd-fonts-monacob-mono refind-btrfs \
    bat-extras-git opennic-up ttf-wps-office-fonts wps-office wps-office-mime \
    neovim-remote git-delta-bin  git-journal just gitui-bin procs-bin smug \
    nushell-bin
yay --noremovemake --nodiffmenu --editmenu -S linux-xanmod-cacule linux-xanmod-cacule-headers
export PATH=/usr/bin/ && yay -S nerd-fonts-jetbrains-mono
# Now is a good time to install dotfiles
# Example 1 (bare git repo)
# git clone --bare https://github.com/Th3Whit3Wolf/.dots.git $HOME/.dots
# git --git-dir=$HOME/.dots/ --work-tree=$HOME checkout
# Example 2 (chezmoi)
# chezmoi init https://github.com/Th3Whit3Wolf/dots.git
exit

Add rEFInd theme

mkdir /boot/EFI/refind/themes  && \
git clone https://github.com/dheishman/refind-dreary.git /boot/EFI/refind/themes/refind-dreary-git && \
mv /boot/EFI/refind/themes/refind-dreary-git/highres /boot/EFI/refind/themes/refind-dreary && \
rm -dR /boot/EFI/refind/themes/refind-dreary-git

Configure rEFInd

sed -i 's/#resolution 3/resolution 1920 1080/' /boot/EFI/refind/refind.conf && \
sed -i 's/#use_graphics_for osx,linux/use_graphics_for linux/' /boot/EFI/refind/refind.conf && \
sed -i 's/#scanfor internal,external,optical,manual/scanfor manual,external/' /boot/EFI/refind/refind.conf
sed -i 's/^hideui.*/hideui singleuser,hints,arrows,badges/' /boot/EFI/refind/themes/refind-dreary/theme.conf

Add rEFInd Manual Stanza

cat << EOF >> /boot/EFI/refind/refind.conf

menuentry "Arch Linux" {
    icon     /EFI/refind/themes/refind-dreary/icons/os_arch.png
    volume   "Arch Linux"
    loader   /vmlinuz-linux
    initrd   /initramfs-linux.img
    options  "rd.luks.name=$(blkid /dev/nvme0n1p2 | cut -d " " -f2 | cut -d '=' -f2 | sed 's/\"//g')=crypt root=/dev/mapper/crypt rootflags=subvol=@ rw quiet nmi_watchdog=0 kernel.unprivileged_userns_clone=0 net.core.bpf_jit_harden=2 apparmor=1 lsm=lockdown,yama,apparmor systemd.unified_cgroup_hierarchy=1 add_efi_memmap initrd=\amd-ucode.img"
    submenuentry "Boot - terminal" {
        add_options "systemd.unit=multi-user.target"
    }
}

menuentry "Arch Linux - Low Latency" {
    icon     /EFI/refind/themes/refind-dreary/icons/os_arch.png
    volume   "Arch Linux"
    loader   /vmlinuz-linux-xanmod-cacule
    initrd   /initramfs-linux-xanmod-cacule.img
    options  "rd.luks.name=$(blkid /dev/nvme0n1p2 | cut -d " " -f2 | cut -d '=' -f2 | sed 's/\"//g')=crypt root=/dev/mapper/crypt rootflags=subvol=@ rw quiet nmi_watchdog=0 kernel.unprivileged_userns_clone=0 net.core.bpf_jit_harden=2 apparmor=1 lsm=lockdown,yama,apparmor systemd.unified_cgroup_hierarchy=1 add_efi_memmap initrd=\amd-ucode.img"
    submenuentry "Boot - terminal" {
        add_options "systemd.unit=multi-user.target"
    }
}

include themes/refind-dreary/theme.conf
EOF

Edit refing-btrfs

sed -i 's/^count.*/count = "inf"/' /etc/refind-btrfs.conf
sed -i 's/^include_sub_menus.*/include_sub_menus = true/' /etc/refind-btrfs.conf

Add snap-pac for automatic pre/post backups for package install/uninstalls/updates

sudo pacman --noconfirm -S snap-pac

NOTE

Make scripts to start service & setup snapshots

cat << EOF >> /home/$USER/init.sh
sudo umount /.snapshots
sudo rm -r /.snapshots
sudo snapper -c root create-config /
sudo mount -a
sudo chmod 750 -R /.snapshots
sudo chmod a+rx /.snapshots
sudo chown :wheel /.snapshots
sudo snapper -c root create --description "Fresh Install"
sudo sed -i 's/^TIMELINE_MIN_AGE.*/TIMELINE_MIN_AGE="1800"/' /etc/snapper/configs/root && \
sudo sed -i 's/^TIMELINE_LIMIT_HOURLY.*/TIMELINE_LIMIT_HOURLY="0"/' /etc/snapper/configs/root && \
sudo sed -i 's/^TIMELINE_LIMIT_DAILY.*/TIMELINE_LIMIT_DAILY="7"/' /etc/snapper/configs/root && \
sudo sed -i 's/^TIMELINE_LIMIT_WEEKLY.*/TIMELINE_LIMIT_WEEKLY="0"/' /etc/snapper/configs/root && \
sudo sed -i 's/^TIMELINE_LIMIT_MONTHLY.*/TIMELINE_LIMIT_MONTHLY="0"/' /etc/snapper/configs/root && \
sudo sed -i 's/^TIMELINE_LIMIT_YEARLY.*/TIMELINE_LIMIT_YEARLY="0"/' /etc/snapper/configs/root
sudo systemctl enable --now snapper-timeline.timer snapper-cleanup.timer
sudo systemctl disable --now systemd-timesyncd.service
sudo systemctl mask systemd-rfkill.socket systemd-rfkill.service
sudo systemctl enable --now NetworkManager 
sudo systemctl enable --now NetworkManager-wait-online
sudo systemctl enable --now NetworkManager-dispatcher
sudo systemctl enable --now nftables
sudo systemctl enable --now opennic-up.timer
sudo systemctl enable --now sshd 
sudo systemctl enable --now chronyd
sudo systemctl enable --now reflector
sudo systemctl enable --now apparmor 
sudo systemctl enable --now sshguard
sudo systemctl enable --now tlp 
sudo systemctl enable --now memavaild 
sudo systemctl enable --now haveged 
sudo systemctl enable --now irqbalance 
sudo systemctl enable --now prelockd 
sudo systemctl enable --now systemd-swap 
sudo systemctl enable --now nohang-desktop 
sudo systemctl enable --now auto-cpufreq 
sudo systemctl enable --now dbus-broker
sudo systemctl enable --now postgresql
sudo systemctl enable --now refind-btrfs
systemctl --user start psd
sudo systemctl enable --now gdm
rm /home/$USER/init.sh
EOF
chown $USER /home/$USER/init.sh

Step 10 - Reboot into your new install

exit
umount -R /mnt && \
reboot

11 - Post Install

Run script

bash init.sh

Connect to wifi

nmcli -a device wifi connect SSID

Finish setting up postgresql for user

sudo -iu postgres
createuser --interactive
# When asked name of role to add enter your username.
# When asked shall the new role be a superuser enter y

Optional: for asus laptops only

cat << EOF > /etc/systemd/system/battery-charge-threshold.service
[Unit]
Description=Set the battery charge threshold
After=multi-user.target
StartLimitBurst=0

[Service]
Type=oneshot
Restart=on-failure
ExecStart=/bin/bash -c 'echo 80 > /sys/class/power_supply/BAT0/charge_control_end_threshold'

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now
@mrkvn
Copy link

mrkvn commented Jan 14, 2021

Thanks for sharing your setup. What did you change in PKGBUILD for linux-xanmod-cacule?

@mrkvn
Copy link

mrkvn commented Jan 15, 2021

How do you build yay in arch-chroot? I'm getting error: bash: warning: shell level (1000) too high, resetting to 1 when running makepkg -si. Does zsh help with this?

Update:
Found it. In this line, makepkg is being called. Hence the shell level 1000 too high. It's calling itself.
sed -i 's/^#BUILDDIR.*/BUILDDIR=\/tmp\/makepkg makepkg/' /etc/makepkg.conf && \

@Th3Whit3Wolf
Copy link
Author

Th3Whit3Wolf commented Jan 15, 2021

Thanks for sharing your setup. What did you change in PKGBUILD for linux-xanmod-cacule?

PKGBUILD I edited the architecture=42

How do you build yay in arch-chroot? I'm getting error: bash: warning: shell level (1000) too high, resetting to 1 when running makepkg -si. Does zsh help with this?

Update:
Found it. In this line, makepkg is being called. Hence the shell level 1000 too high. It's calling itself.
sed -i 's/^#BUILDDIR.*/BUILDDIR=/tmp/makepkg makepkg/' /etc/makepkg.conf && \

Thank you for finding the source of this issue! I have updated the gist.

@mrkvn
Copy link

mrkvn commented Jan 20, 2021

There's a typo here. cache and log were mismatched.

mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@log /dev/mapper/crypt /mnt/var/cache && \
mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@cache /dev/mapper/crypt /mnt/var/log && \

And I believe this...

# sed -i 's/^HOOKS/HOOKS=(base systemd autodetect modconf block sd-encrypt resume btrfs filesystems keyboard fsck)/' mkinitcpio.conf

Should be this...

# sed -i 's/^HOOKS.*/HOOKS=(base systemd autodetect modconf block sd-encrypt resume btrfs filesystems keyboard fsck)/' mkinitcpio.conf

Because instead of overwriting the HOOKS, it's appending.

@Th3Whit3Wolf
Copy link
Author

There's a typo here. cache and log were mismatched.

mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@log /dev/mapper/crypt /mnt/var/cache && \
mount -o noatime,compress-force=zstd,commit=120,space_cache=v2,ssd,discard=async,autodefrag,subvol=@cache /dev/mapper/crypt /mnt/var/log && \

Good catch! I'll update the gist.

And I believe this...

# sed -i 's/^HOOKS/HOOKS=(base systemd autodetect modconf block sd-encrypt resume btrfs filesystems keyboard fsck)/' mkinitcpio.conf

Should be this...

# sed -i 's/^HOOKS.*/HOOKS=(base systemd autodetect modconf block sd-encrypt resume btrfs filesystems keyboard fsck)/' mkinitcpio.conf

Because instead of overwriting the HOOKS, it's appending.

You're right, I don't know why I left that one like that.

@wcasanova
Copy link

wcasanova commented Apr 8, 2021

hi.

systemd-swap

warning Current code quality and commit frequency is low warning
Users should migrate to systemd/zram-generator since zram should be enough in most systems

suggest to use zram-generator
https://github.com/systemd/zram-generator.

on the other hand, they recommend ESP apart
/efi
/boot
https://wiki.archlinux.org/index.php/EFI_system_partition#Typical_mount_points

@Th3Whit3Wolf
Copy link
Author

zram-generator looks pretty interesting, I didn't put efi on it's own partition because it would have required have an unencrypted /boot and /efi partition to work correctly so I'd prefer to keep them together.

I have recently switched to NixOS so I probably won't update this gist.

@wcasanova
Copy link

/boot can be encrypted with btrfs and luks v1, which cannot is /efi
good luck with NixOS

@Th3Whit3Wolf
Copy link
Author

/boot can be encrypted with btrfs and luks v1, which cannot is /efi

With luks v1 you are unable to use argon2 or ---persistant flag. Right now argon2id is the safest option to encrypt passwords.

good luck with NixOS

Thank you.

@wcasanova
Copy link

you have tried greetd, gtkgreet? it works for wayland

@Th3Whit3Wolf
Copy link
Author

I actually just recently switched to it.

@denji
Copy link

denji commented May 2, 2021

@Th3Whit3Wolf Bug /etc/makepkg.conf

-CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
+CFLAGS="-march=native -mtune=native -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -fno-plt"
         -Wp,-D_FORTIFY_SOURCE=2,-D_GLIBCXX_ASSERTIONS \
         -Wformat -Werror=format-security \
         -fstack-clash-protection -fcf-protection"

-CXXFLAGS="$CFLAGS"
+CXXFLAGS="-march=native -mtune=native -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -fno-plt"

@Corey-Keller
Copy link

@thewhit3wolf, did booting snapshots actually work for you? Because no snapshots show up for me (presumably because the root partition is encrypted and isn't unlocked until AFTER refind is done)

@Th3Whit3Wolf
Copy link
Author

@Corey-Keller yes I was able to use snapshots. I would check refind-btrfs instructions, when I wrote this gist the author had just made support for encrypted devices. It's possible some instructions have changed since then.

@Venom1991
Copy link

Venom1991 commented Jun 10, 2021

I just discovered these instructions, purely by accident. Good job!
However, this line:

sed -i 's/^count.*/count = "inf"/' /etc/refind-btrfs.conf

should be (probably, I'm not proficient in sed):

sed -i 's/^selection_count.*/selection_count = "inf"/' /etc/refind-btrfs.conf

because I've renamed that option a while ago.

"inf" is most likely not a great idea, though. Especially when used in combination with setting the "include_sub_menus" option to true.
But, if it works fine for you, great!

@ni5arga
Copy link

ni5arga commented Jan 24, 2022

Thanks for this

@Th3Whit3Wolf
Copy link
Author

@nisarga-developer no problem I'm glad other people could benefit from my labor!

@TellyO3
Copy link

TellyO3 commented Jan 31, 2022

This looks awesome, the only thing I would love to see is a description of what everything does, you install a lot of packages which are not "necessary", which is fine but it would be nice to see what everything is if you are not used to them. I personally went through everything manually and removed what I wouldn't use and replaced where I use different programs.

@TellyO3
Copy link

TellyO3 commented Jan 31, 2022

Small note, XanMod CacULE has been replaced with XanMod TT, it is no longer available.

@Th3Whit3Wolf
Copy link
Author

@TellyO3 that is a really good idea! When I get time I will update the description, packages, and any configs that have changed since I posted this.

@TellyO3
Copy link

TellyO3 commented Feb 3, 2022

@Th3Whit3Wolf

I already made a start here, not everything is completely correct but its the majority of it. Some packages are different since this is a fork of a fork. I am still working on it, I can't seem to get refind stable, it just disappeared from my boot menu today. Think I might consider using grub instead.

https://gist.github.com/TellyO3/8b33f5470e15a5d9e39b43856598b484

@Venom1991
Copy link

@TellyO3 Have a look at this.

@TellyO3
Copy link

TellyO3 commented Feb 3, 2022

Hey, @Venom1991 while this is interesting, my issue is a bit more drastic. When I rebooted this morning refind was missing completely, it just wiped itself from the list of possible boot devices.

I can change the boot order using my Asus motherboard but it was completely gone. I had not made any changes to refind since starting.

I had other wierd issues too, I don't know if I messed up the config somehow or not but if I try to boot into Linux right after refind shows up it gives an error and doesn't allow me to boot. If I wait 5 or so seconds it boots just fine.

But I am figuring out more issues as I go, I like a lot of the ideas in this gist and am adapting my findings in my fork as we go. The initial install worked relatively well but I had some Chrony, RTKit, and zsh issues.

Setting zsh as it is done right now seems to set it to /root/.config/zsh which causes issues later because you can't easily edit that as a user.

I was not entirely sure what RTKit does, but I got a lot of errors in my logs without it.

Not sure how I fixed Chrony.

@wcasanova
Copy link

@TellyO3 if you do not need the NTP server (Chrony), systemd-timesyncd is sufficient and easy to configure as a client (SNTP)

@untainsYD
Copy link

@Th3Whit3Wolf can you explain the purpose of btrfs sub create /mnt/@btrfs?
Is it like root entrypoint to follow in commands like btrfs sub list /btrfs etc?

Should it be empty?
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment