I am a novice Linux user, please take all my edits with a grain of salt. I wanted it to work a bit better for a number of reasons. The original guide was written early 2021, it is February 2022 as of now. Some of the utilities, like the original custom kernel are deprecated. Additionally some AUR repos are not up to date, as is the case with auto-cpufreq which was last updated months ago. I also included some troubleshooting tips, based on issues I encountered. Feel free to leave any suggestions or tips, it would be greatly appreciated.
My goal is also to have a more template like setup, give you the utilities you need but not anything else. Especially the first setup had a lot of extra's which were absolutely not necessary and it took me a lot of time to disect some of that from what is actually used in the setup.
- No GDM, because I don't want its gnome dependencies if I don't use them
- Many packages were changed or made optional
- Xanmod-TT
I don't currently use docker, I will leave in the instructions but I cannot test it The same counts for PostgreSQL and Secure Boot.
- 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 TT Linux Kernel
- Miscellaneous
- Udev rule for faster IO performance from NVME and SSD
- Hooks for zsh and secureboot
- Improved laptop battery life
- Zram-generator
- Btrfs
- 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)
- 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
- 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
The following changes were made in comparsion with Th3Whit3Wolf's gist:
- Make it easier to mount partitions with the appropriate options
- Add subvolume prefix for multi OS support
- Changed some packages from pacstrap (some packages were kept as optional)
- Using Booster as initramfs generator
- Using pipewire as jack replacement (may have issues with some audio softwares)
- Using systemd's zram-generator instead of zram-swap
- Using paru instead of yay
To see changes made in comparison to Sixel's gist Look at the warning at the top of the document
- 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-tt
Because I hate the fact that it depends on a bunch of gnome stuff I don't want. And there are alternatives available now, they didn't exist or were underdeveloped at the time of writing the original guide.
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 using iwctl
iwctl
Get your IP address
ip a
Create an EFI partition (IF YOU DON'T HAVE ONE) which should be ~200-500mb and set its type to EFI
Create a main partition with the remaining space, you can leave its type as the default
cfdisk /dev/sda # replace sda with your drive
# replace with the respective partions you created
export BOOT_PARTITION=/dev/sda1
export ROOT_PARTITION=/dev/sda2
While this is very safe, it might take a while (10-20 sec) to unlock on weaker machines. If this concerns you, consider using weaker cryptography.
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 $ROOT_PARTITION
cryptsetup --allow-discards --perf-no_read_workqueue --perf-no_write_workqueue --persistent open $ROOT_PARTITION crypt
mkfs.vfat -F32 -n "EFI" $BOOT_PARTITION
mkfs.btrfs -L Arch -f /dev/mapper/crypt
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
mkdir /mnt/arch
btrfs sub create /mnt/arch/@ && \
btrfs sub create /mnt/arch/@home && \
btrfs sub create /mnt/arch/@abs && \
btrfs sub create /mnt/arch/@tmp && \
btrfs sub create /mnt/arch/@srv && \
btrfs sub create /mnt/arch/@snapshots && \
btrfs sub create /mnt/@btrfs && \
btrfs sub create /mnt/arch/@log && \
btrfs sub create /mnt/arch/@cache
# Extra subvolumes (not necessary)
mkdir /mnt/common
btrfs sub create /mnt/common/@devel && \
btrfs sub create /mnt/common/@games && \
# Remember to umount
umount /mnt
Set MOUNT_OPTIONS
according to your drive type
export HDD_MOUNT_OPTIONS="noatime,compress-force=zstd,autodefrag"
export SSD_MOUNT_OPTIONS="$HDD_MOUNT_OPTIONS,space_cache=v2,ssd,commit=120,discard=async"
export MOUNT_OPTIONS=$SSD_MOUNT_OPTIONS
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
Mount the subvolumes
export STRICT_MOUNT_OPTIONS="noexec,nodev,nosuid,$MOUNT_OPTIONS"
mount -o $MOUNT_OPTIONS,subvol=arch/@ /dev/mapper/crypt /mnt && \
mkdir -p /mnt/{boot,home,var/cache,var/log,.snapshots,btrfs,var/tmp,var/abs,srv}
mount -o $MOUNT_OPTIONS,subvol=arch/@home /dev/mapper/crypt /mnt/home && \
mount -o $MOUNT_OPTIONS,subvol=arch/@srv /dev/mapper/crypt /mnt/srv
strict_mount_targets="cache log abs tmp"
for target in $(echo $strict_mount_targets); do mount /dev/mapper/crypt -o $STRICT_MOUNT_OPTIONS,subvol=arch/@$target /mnt/var/$target; done
mount -o $MOUNT_OPTIONS,subvol=arch/@snapshots /dev/mapper/crypt /mnt/.snapshots && \
mount -o $MOUNT_OPTIONS,subvolid=5 /dev/mapper/crypt /mnt/btrfs
# Extra subvolumes
mkdir -p /mnt/media/{devel,games}
mount /dev/mapper/crypt -o $MOUNT_OPTIONS,subvol=common/@devel /mnt/media/devel
mount /dev/mapper/crypt -o $MOUNT_OPTIONS,subvol=common/@games /mnt/media/games
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}
chattr +C /mnt/media/games
Mount the EFI partition
mount -o nodev,nosuid,noexec $BOOT_PARTITION /mnt/boot
If your ArchISO is a bit older some of the keys might not be up to date
In that case:
pacman -Sy
pacman -S archlinux-keyring
Don't try to -Syu as it might give you errors on the ArchISO
(this is the time where you change the mirrorlist, if that's your thing) -The following assumes you have an Intel CPU & GPU
pacstrap /mnt base base-devel linux-lts linux-lts-headers booster intel-ucode \
zstd iwd networkmanager mesa vulkan-intel libva-mesa-driver openssh wf-recorder \
mesa-vdpau libvirt qemu refind rustup wl-clipboard zsh sshguard neovim nano \
rust-analyzer xdg-user-dirs zram-generator pigz pbzip2 snapper a52dec \
faac iptables-nft git faad2 flac jasper grim swayidle \
libmad libmpeg2 libtheora libvorbis compsize nftables reflector tmux \
waybar wavpack xvidcore libde265 gstreamer gst-libav gst-plugins-bad \
gst-plugins-base gst-plugins-good gst-plugins-ugly gstreamer-vaapi \
sway alacritty polkit-gnome mako slurp xdg-desktop-portal-wlr \
gvfs libxv nautilus nautilus-image-converter noto-fonts btrfs-progs \
udiskie imv mpv lrzip unrar zip powertop brightnessctl linux-firmware \
x264 lzip xorg-xwayland apparmor lz4 wireplumber \
lzop p7zip noto-fonts-emoji ttf-font-awesome libva-utils man chrony dbus-broker \
lame blueman irqbalance pipewire{,-pulse,-jack,-alsa}
Optional:
- profile-sync-daemon - Used to increase performance with some browsers
- xf86-video-linux - Discouraged by some distros, evaluate on a case to case basis
- hyperfine - Used to benchmark the command-line
- flatpak - Alternative package solution
- yadm - Yet Another Dotfiles Manager (Literally)
- fd - Alternative to find
- exa - Alternative to ls
- tlp - Power saving tool, auto-cpufreq aims to succeed it and recommends not using it
- ripgrep - Tool to search directories using RegEx, which respects your gitignore
- bat - Cat clone with useful tools
- skim - Fuzzy finder written in rust
- shfmt - Shell script formatter
What is all of this?
Core
- base base-devel git linux-firmware - Base Arch package, development tools, and drivers.
- linux-lts linux-lts-headers - Linux kernel, I am using LTS because the main kernel is a custom kernel, it functions as a backup.
- booster - Initial ram generator, necessary for booting.
- intel-ucode - Microcode for intel processors, your system might not function correctly without this.
- mesa vulkan-intel libva-mesa-driver mesa-vdpau libva-utils - Graphics drivers for intel systems, research what you need for AMD or Nvidia yourself. Nvidia has terrible Linux support and will probably not work in Wayland the software responsible for giving us a graphical interface.
- zram-generator - Utility that creates optimized swap/ram relations.
- snapper - Responsible for managing BTRFS snapshots.
- refind - Bootloader, this is what starts our system. It is capable of booting many different systems including Windows if you decide to dual boot. It should automatically detect and add this if you decide to dual boot.
- rustup rust-analyzer - Rust language utilities, it is a common language for writing utilities.
- xdg-user-dirs xdg-desktop-portal-wlr - Adds support for the common Downloads, Desktop etc folders. Should work out of the box.
- zsh - Alternative shell which is much cooler. Allows for better peformance and a ton of cosmetic and utilitarian modifications.
- xorg-xwayland - Allows you to run xorg programs inside of wayland if they do not support it
- sway - Window Manager
- gvfs nautilus udiskie nautilus-image-converter - File manager and utilities
- btrfs-progs - Essential for BTRFS
- noto-fonts noto-fonts-emoji ttf-font-awesome - Fonts
Audio/Video
- a52dec faac faad2 flac jasper libmad libmpeg2 libtheora libvorbis wavpack xvidcore libde265 gstreamer gst-libav gst-plugins-bad gst-plugins-base gst-plugins-good gst-plugins-ugly gstreamer-vaapi libxv x264 lame - Audio/Video tools
- pipewire{,-pulse,-jack,-alsa} - Audio service
Programs/Tools
- zstd pigz pbzip2 lrzip unrar zip lzip lz4 lzop p7zip - Compression and archiving tools
- iwd networkmanager - Networking utilities for both wired and wireless. IWD is responsible for iwctl which we used earlier.
- wf-recorder wl-clipboard grim slurp swayidle waybar mako - These are all addons to our desktop, wf-recorder records the desktop, wl-clipboard is a clipboard, grim and slurp are used for screenshots, swayidle is for an idle menu, waybar is a replacement for the default bar at the top of your screen, and mako is for notifications.
- libvirt qemu - Virtual machine technology, allows for high performance virtual machines. Technically not mandatory but it is a commonly used tool and it is easier to configure it now and not worry about it later.
- neovim nano - File editing tools, neovim is very powerful but also complex. It might be easier to use nano for small edits until you familiarize yourself with neovim.
- compsize - Compression checker for BTRFS
- reflector - Updates your pacman mirrorlist
- tmux - Used for splitting the terminal and other useful things
- wireplumber - Networking diagnostics tool
- man - View the manual for a program
- chrony - Time utility specialized in laptops and other devices that move around a lot
- blueman - Bluetooth utility
- irqbalance - Performance utility
- imv mpv - Image viewer and audio/video player
- powertop brightnessctl - Power and backlight utilities
- alacritty - Terminal
Security
- openssh sshguard - Allows for SSHing in and out of the machine, as you are probably doing right now. SSHGuard attempts to make this safer by blocking potential vulnerabilities.
- iptables-nft nftables - Firewall utilities
- apparmor - Security
- polkit-gnome dbus-broker - Security essential, what commands can you run without permission?
generate the fstab
genfstab -U /mnt > /mnt/etc/fstab
Use timedatectl(1) to ensure the system clock is accurate
timedatectl set-ntp true
Export some variables to chroot environment
cat << EOF >> /mnt/env.sh
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
export ROOT_PARTITION="$ROOT_PARTITION"
EOF
Chroot into the new system
arch-chroot /mnt /bin/zsh
Source the environment
source /env.sh && rm /env.sh
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 && \
withecho "$USER ALL=(ALL) ALL" >> /etc/sudoers && \
to have sudo only with passwd
useradd -m -G 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
- 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
I have run into issues running /usr/lib/booster/regenerate_images because of a too many files open error. This can be circumvented by temporarily increasing the max amount of open files.
# ONLY IF YOU HAVE THIS ERROR
ulimit -n 4096
It is also possible to do this permanently, just incase. link
cat << EOF >> /etc/booster.yaml
universal: true
compression: lz4
strip: true
modules_force_load: i915
EOF
/usr/lib/booster/regenerate_images
Laptop Power Saving Improvements
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_hda_intel
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
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
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
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
EOF
Zsh hook
What this does is refresh the known programs if you install new programs. link
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/zram-generator.conf
# This file is part of the zram-generator project
# https://github.com/systemd/zram-generator
# Edit the values as appropriate
# This section describes the settings for /dev/zram0.
[zram0]
# The size of the zram device, as a function of MemTotal, both in MB.
# For example, if the machine has 1 GiB, and zram-size=ram/4,
# then the zram device will have 256 MiB.
# Fractions in the range 0.1–0.5 are recommended.
#
# The default is "min(ram / 2, 4096)".
zram-size = ram / 4
# The compression algorithm to use for the zram device,
# or leave unspecified to keep the kernel default.
# compression-algorithm = lzo-rle
EOF
Optimize Makepkg
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/#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
(OPTIONAL) Docker use IPV6 & Btrfs
pacman -S docker
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
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
(OPTIONAL) Setup PostgreSQL
pacman -S 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
Install AUR helper
su $USER
cd ~ && \
git clone https://aur.archlinux.org/paru-bin.git && \
cd paru-bin && \
makepkg -si && \
cd .. && \
sudo rm -dR paru-bin
Install bootloader
sudo refind-install
Add some user niceties while you are there
rustup default stable && \
paru --noremovemake -S memavaild prelockd nohang-git refind-btrfs just greetd greetd-gtkgreeter
paru --noremovemake -S linux-xanmod-tt linux-xanmod-tt-headers
exit
Add auto-cpu-freq
git clone https://github.com/AdnanHodzic/auto-cpufreq.git
cd auto-cpufreq && sudo ./auto-cpufreq-installer
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 (make sure ROOT_PARITION is set)
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-lts
initrd /booster-linux-lts.img
options "rd.luks.name=$(blkid $ROOT_PARTITION | cut -d " " -f2 | cut -d '=' -f2 | sed 's/\"//g')=crypt root=/dev/mapper/crypt rootflags=subvol=arch/@ 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=\intel-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-tt
initrd /booster-linux-xanmod-tt.img
options "rd.luks.name=$(blkid $ROOT_PARTITION | cut -d " " -f2 | cut -d '=' -f2 | sed 's/\"//g')=crypt root=/dev/mapper/crypt rootflags=subvol=arch/@ 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=\intel-ucode.img"
submenuentry "Boot - terminal" {
add_options "systemd.unit=multi-user.target"
}
}
include themes/refind-dreary/theme.conf
EOF
Edit refind-btrfs
sed -i 's/^selection_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
rd.luks.name=$(blkid /dev/sda2 | cut -d " " -f2 | cut -d '=' -f2 | sed 's/\"//g')=crypt root=/dev/mapper/crypt
- This will expand tord.luks.name=device-UUID=crypt root=/dev/mapper/crypt
, this is required when using the sd-encrypt hook in mkinitcpiorootflags=subvol=@
- This is how to specifty the subvolume to use as the root mountpointrw
- Allows the mountpoint to both read from and written toquiet
- Prevents unneccesary infor being written to stdout durring boot.nmi_watchdog=0
- Disables NMI watchdog from early bootkernel.unprivileged_userns_clone=0
- Allows unpriviledged containers on linux-hardened and custom kernelsnet.core.bpf_jit_harden=2
- The kernel includes a hardening feature for JIT-compiled BPF which can mitigate some types of JIT spraying attacks at the cost of performance and the ability to trace and debug many BPF programsapparmor=1 lsm=lockdown,yama,apparmor
- Enables AppArmor as default security model on every bootsystemd.unified_cgroup_hierarchy=1
- Enables unified cgroup hierarchy, AKA cgroups v2. Click here for more information.add_efi_memmap
- According to this reddit post, this parameter may be required if the UEFI implementation on the system fails to correctly report the amount of available physical memory to the kernel. You may not need it.initrd=\intel-ucode.img
- This is how to set the cpu microcode in refind (inside options \ is used a path separator)
Make scripts to start service & setup snapshots (uncomment the optional services as needed)
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 NetworkManager-wait-online
sudo systemctl mask NetworkManager-wait-online
sudo systemctl enable --now NetworkManager
sudo systemctl enable --now NetworkManager-dispatcher
sudo systemctl enable --now nftables
sudo systemctl enable --now sshd
# uncomment if chronyd NOT is installed
#sudo systemctl disable --now systemd-timesyncd.service
sudo systemctl enable --now chronyd
sudo systemctl enable --now reflector
sudo systemctl enable --now apparmor
sudo systemctl enable --now sshguard
sudo systemctl enable --now memavaild
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
# uncomment if postgres is installed
#sudo systemctl enable --now postgresql
sudo systemctl enable --now refind-btrfs
sudo systemctl enable --now greetd
rm /home/$USER/init.sh
EOF
chown $USER /home/$USER/init.sh
exit
umount -R /mnt && \
reboot
Run script
bash init.sh
Connect to wifi
nmcli -a device wifi connect
SSID
(OPTIONAL) 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