Installation notes to install Arch Linux on Lenovo T480

Btrfs (B-tree file system) is a modern, copy-on-write (CoW) filesystem for Linux designed for high scalability, fault tolerance, and easy administration. It supports advanced features like snapshots, data compression, and built-in RAID. It is widely used in Linux distributions (e.g., Fedora) and enterprise NAS systems for data integrity.

zram: Zram (formerly compcache) is a Linux kernel module that creates a compressed, RAM-based block device, acting as a faster alternative to traditional swap. By compressing data in memory (typically at a 3:1 ratio), it allows systems to store more data in RAM, significantly reducing disk I/O and enhancing responsiveness on low-memory devices.

timeshift: Timeshift is a powerful open-source tool for Linux that creates incremental snapshots of the system files and settings, allowing users to restore their system to a previous state. It functions similarly to Windows System Restore or macOS Time Machine, protecting against broken updates or misconfigurations. It supports Btrfs for efficient, near-instant snapshots and rsync for all other file systems.

COSMIC :is a free and open-source desktop environment for Linux and other Unix-like operating systems. Originally a modified version of GNOME made for Pop! OS, it was later rebuilt from scratch as a standalone desktop environment using the Iced toolkit.

Prep the T480

In BIOS disable Secure boot

Step 1: Creating a bootable Arch media device

I used Rufus to generate the bootable USB.
Partition scheme GPT. Target system UEFI.
Insert the USB into the device you intend to install Arch linux on and boot into the USB.

bigger font

setfont ter-132b

Step 2: Setting Up the System with the Arch ISO

[optional] if you would like to ssh into your target machine you will need to: Create a password for the ISO root user with the passwd command. passwd

Ensure that ssh is running with systemctl status sshd (if it isn’t start it with systemctl start ssdhd). systemctl status sshd

systemctl start ssdhd

Set the console keybooard layout (US by default): list available keymaps with localectl list-keymaps; and, localectl list-keymaps

load the keymap with loadkeys .

loadkeys us

[optional] set the font size with setfont ter-132b.

setfont ter-132b

Verify the UEFI boot mode cat /sys/firmware/efi/fw_platform_size.

This installation is written for a system with a 62-bit x64 UEFI. This isn’t required, but if you are on a different boot mode, consult section 1.6 of the official guide.

cat /sys/firmware/efi/fw_platform_size

Network Connection

I used the iwctl utility for this purpose.

iwctl

note the device name of our WiFi adapter so we can refer to it later. wlan0 in this example

Scan available networks

station wlan0 get-networks

exit from iwctl

exit

connect to network

iwctl --passphrase <passphrase> station <interface> connect NetworkName

Confirm that your connection is active with ping -c 2 archlinux.org.

ping -c 2 archlinux.org

[optional] Obtain your IP Address with ip addr show, and now you’re ready to ssh into your target machine.

ip addr show

You can now ssh from another computer. Handy if you have a PC with bigger screen and keyboard.

Set the timezone:

timedatectl list-timezones

timedatectl set-timezone America/Phoenix

timedatectl set-ntp true

Partition your disk:

list your partitions with lsblk;

lsblk

delete the existing partitions on the target disk [WARNING: your data will be lost]

create two partitions:

!NOTE: The official Arch Linux installation guide suggests implementing a swap partition. You could also create a swap subvolume within BTRFS, however, snapshots will be disabled where a volume has an active swapfile. In my case, I have opted instead for zram which works by compressing data in RAM, thereby stretching your RAM further. zram is only active when your RAM is at or close to capacity.

efi = 1G

main = allocate all remaining space (or as otherwise fit for your specific case) noting that BTRFS doesn’t require pre-defined partition sizes, but rather allocates dynamically through subvolumes which act in a similar fashion to partitions but don’t require the physical division of the target disk.

gdisk /dev/nvme0n1

In gdisk utility list known partition types. search for eft

l - this is a lower case letter l

efi

will return ef00

create a new empty GUID table using the command o
create a new partition using n
use the fist part of the sector as the default
last sector enter +1G
for current type of file system enter ef00
you can use p to print the partition table

optional Swap

create the second partition using n
default the partition number
default the start of the partition
default the last sector
default the Linux 8300 filesystem
use p to check the table
use w to write

lsbk

to check the work

Format the main partition

mkfs.btrfs /dev/nvme0n1p2

mount /dev/nvme0n1p2 /mnt

now we need to cd into the /mnt directory with
cd /mnt

create our subvolumes: using the name @ for timeshift

root:
btrfs subvolume create @
or shortened
btrfs su cr /mnt/@

home:
btrfs subvolume create @home

!NOTE: you can create your own subvolume names, these subvolumes will also be referenced later when taking snapshots with timeshift.

go back to the original (/home/root) directory with
cd -

unmount our mnt partition:
umount /mnt

mount the subvolumes:

(the first time we mounted the partition so that we could create the btrfs subvolumes. we then umount the partition so that we can mount the subvolumes.)

btrfs mount options for nvme To optimize Btrfs for an NVMe drive, you should focus on options that minimize write amplification and leverage the high bandwidth of the PCIe interface.

Recommended Mount Options

noatime: Disables access time updates, which significantly reduces metadata writes and prevents unnecessary Copy-on-Write (CoW) cycles.

compress-force=zstd:1: Using zstd:1 provides a good balance of compression and speed. High compression levels (like 3+) can bottleneck ultra-fast NVMe throughput by waiting on the CPU. Using compress-force is often preferred to bypass Btrfs’s internal heuristics and let zstd handle incompressible data.

discard=async: This allows the filesystem to send TRIM commands to the NVMe in the background without blocking I/O operations. Note: It is automatically enabled on supported devices since kernel 6.2.

ssd: Explicitly tells Btrfs the device is solid-state. While usually auto-detected, including it ensures SSD-specific optimizations like spread-out block allocation are active.

space_cache=v2: A more efficient way to track free space on the drive, especially beneficial for larger volumes (over 1TB). It is the default for most modern distributions.

Summary Table for /etc/fstab

What I used for options

noatime Reduces disk writes; improves performance.

compress=zstd Saves space with minimal CPU overhead; extends drive life.

discard=async Efficiently handles TRIM for better long-term performance.

ssd Optimizes block allocation for flash storage.

space_cache=v2 Modern, faster free space tracking.

Mount main subvolume

mount -o noatime,ssd,compress=zstd,space_cache=v2,discard=async,subvol=@ /dev/nvme0n1p2 /mnt

create home mounting point

mkdir /mnt/home

mount our subvolumes:

mount -o noatime,ssd,compress=zstd,space_cache=v2,discard=async,subvol=@home /dev/nvme0n1p2 /mnt/home

efi partition:

format your efi partition:
mkfs.fat -F32 /dev/nvme0n1p1

create boot mounting point
mkdir /mnt/boot

mount our efi partition with
mount /dev/nvme0n1p1 /mnt/boot

install base packages:

pacstrap -K is a crucial Arch Linux installation command that initializes a fresh, empty keyring in the new system’s target directory, preventing issues from the host’s potentially outdated or untrusted keys by forcing a new key generation, making it a recommended practice for a clean installation. It’s used with the mount point and essential packages like base, linux, and linux-firmware, e.g., pacstrap -K /mnt base linux linux-firmware, to install core components for a new Arch system.

Note I went with the lts kernel
pacstrap -K /mnt base linux-lts linux-firmware

generate the file system table (U option to include UUID): genfstab -U -p /mnt >> /mnt/etc/fstab

(you can check this with cat /mnt/etc/fstab)

change root into the new system:

arch-chroot /mnt

You are now working from within in your new arch system - i.e. not from the ISO - and you will now see that your prompt start with #. Great work so far!

Step 3: Working Within Our New System install neovim to modify config files pacman -S neovim

check sudo nvim/etc/fstab and get rid of the Subvolid entries (not needed, and optional step) if swap partition can set the pri=10 (swap partition after defaults,) low priority

We are now working within our Arch system on our device, but it’s important to note that we can’t yet reboot our machine. Let’s continue with a few steps that we need to repeat again (such as setting our root password, timezones, keymaps and language) given the previous settings were in the context of our ISO.

set your local time and locale on your system:

ln -sf /usr/share/zoneinfo/America/Phoenix /etc/localtime

(this is in your system, not on the iso) sync hardware clock to system time

hwclock --systohc

locale

Substitute text: sed ’s/old/new/’ file.txt replaces the first occurrence of “old” with “new” in each line. sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen && locale-gen or neovim or whatever editor you want to use to set locale

nvim /etc/locale.gen uncomment your locale (en_US.UTF-8) , write and exit and then run locale-gen

then

echo "LANG=en_US.UTF-8" >> /etc/locale.conf

for locale

echo "KEYMAP=us" >> /etc/vconsole.conf

for keyboard (select yours as appropriate)

change the hostname

echo "jim-t480" >> /etc/hostname

(feel free to customise to your case, the t480 in my case is for the Lenovo t480 I am installing Arch on).

set hosts file echo "127.0.0.1 localhost" >> /etc/hosts echo "::1 localhost" >> /etc/hosts echo "127.0.1.1 jim-t480.localdomain jim-t480" >> /etc/hosts

set your root password: passwd

set up a new user (replace jim with your preferred username): create

useradd -m -g users -G wheel jim

give your user a password with

passwd jim

(you will be prompted to enter a password);

create a sudoers directory with

mkdir /etc/sudoers.d

set the sudoers direcotry permissions

chmod 755 /etc/sudoers.d

add your user to the sudoers group:

echo "jim ALL=(ALL) ALL" >> /etc/sudoers.d/jim

; and,

set the permissions for your sudoers user file

chmod 0440 /etc/sudoers.d/jim

install sudo and reflector (reflector needs rsync)

pacman -S sudo reflector rsync

set mirrorlist

Packages to be installed must be downloaded from mirror servers, which are defined in /etc/pacman.d/mirrorlist. The higher a mirror is placed in the list, the more priority it is given when downloading a package.

On the live system, all HTTPS mirrors are enabled (i.e. uncommented). The topmost worldwide mirror should be fast enough for most people, but you may still want to inspect the file to see if it is satisfactory. If it is not, edit the file accordingly, and move the geographically closest mirrors to the top of the list, although other criteria should be taken into account. Alternatively, you can use reflector to create a mirrorlist file based on various criteria.

This file will later be copied to the new system by pacstrap, so it is worth getting right.

Reflector is a Python script which can retrieve the latest mirror list from the Arch Linux Mirror Status page, filter the most up-to-date mirrors, sort them by speed and overwrite the file /etc/pacman.d/mirrorlist.

cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak

reflector -c 'United States' -a 12 --sort rate --save /etc/pacman.d/mirrorlist

Next, we will install all of the packages we need for our system. It’s imperative to always know what you are doing, and what you are installing!

!NOTE: you could of course install all of the following packages together, but I have broken them up so they are easier to reason about.

install the main packages that our system will use:

pacman -Syu
base-devel
linux-lts
linux-lts-headers
linux-firmware
btrfs-progs
grub
efibootmgr
mtools
iwd
networkmanager
network-manager-applet \

  • networkmanager-openvpn
    wpa_supplicant
    dialog
    dosfstools
    openssh
    git
    iptables-nft
    ipset
    firewalld
    acpi
    acpid
    tlp
    grub-btrfs

install the following based on the manufacturer of your CPU:

intel: (microcode that can patch firmware)

pacman -S intel-ucode

amd: pacman -S amd-ucode

install your Desktop Environment and Display Manager of choice:

pacman -Syu cosmic-session

  • S: Synchronizes packages
  • y: Refreshes the database for packages
  • u: Upgrade all installed packages to their newest version

!NOTE: I am using COSMIC by System76, but you can just as easily install gnome, kde or whichever tiling window manager or graphical user environment that you would like at this stage.

install other useful packages:

pacman -S
man-db
man-pages
texinfo
cifs-utils
cups
hplip
system-config-printer
python-pyqt5
foomatic-db
foomatic-db-engine
gutenprint
simple-scan
cups-pdf
cups-pk-helper
ghostscript
gsfonts
bash-completion
htop
git
bluez
bluez-utils
alsa-utils
pipewire
pipewire-pulse
pipewire-jack
sof-firmware
ttf-firacode-nerd
alacritty
firefox

edit the mkinitcpio file for encrypt:

nvim /etc/mkinitcpio.conf

and search for HOOKS; add encrypt (before filesystems hook); add usbhid & atkbd to the MODULES (enables external keyboard at device decryption prompt); add btrfs to the MODULES; example: MODULES=(btrfs atkbd usbhid) and,

recreate the mkinitcpio

mkinitcpio -p linux for lts mkinitcpio -p linux-lts

setup grub for the bootloader so that the system can boot linux:

grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB

NOTE: –disable-shim-lock disables GRUB’s built in shim lock protocol support. This flag is optional, and should only be passed if you are using custom keys (not the Microsoft Signed shim mechanism).

grub-mkconfig -o /boot/grub/grub.cfg

run blkid and obtain the UUID for the main partition (TYPE=“cypto_LUKS”: copy the UUID

blkid or cat /etc/fstab

UUID=“2032ebd8-13e7-4a6d-9c8e-d9028151aef8”

edit the grub config

nvim /etc/default/grub

make the grub config with

grub-mkconfig -o /boot/grub/grub.cfg

enable services: Cosmic greeter systemctl enable cosmic-greeter.servce

network manager with

systemctl enable NetworkManager

bluetooth with

systemctl enable bluetooth

ssh with

systemctl enable sshd

firewall with

systemctl enable firewalld

reflector

systemctl enable reflector.timer

systemctl enable fstrim.timer

systemctl enable acpid

systemctl enable cups.service

systemctl enable fstrim.timer

systemctl enable tlp.service

edit bluetooth

vim /etc/bluetooth/main.conf

find AutoEnable and set AutoEnable=true

Now for the moment of truth. Make sure you have followed these steps above carefully, then reboot your system with the reboot command.

Step 4: Tweaking our new Arch system

When you boot up you will be presented with the grub bootloader menu, and then, once you have selected to boot into arch linux (or the timer has timed out and selected your default option) you will be prompted to enter your encryption password. Upon successful decryption, you will be presented with the ly greeter. Enter the password for the user you created earlier.

use network manager to connect wifi

nmcli device wifi list

nmcli device wifi connect DogsNHogs

ping archlinux.org -c 5

install paru:

sudo pacman -S –needed base-devel git clone https://aur.archlinux.org/paru.git cd paru makepkg -si

zram-generator

zram-generator is a systemd-related project hosted under its GitHub organization that makes use of its conventions and mechanisms.

It provides systemd-zram-setup@zramN.service units to automatically initialize zram devices without users needing to enable/start the template or its instances. See zram-generator(8).

To use it, install zram-generator, sudo pacman -Syu zram-generator and create /etc/systemd/zram-generator.conf with the following:

/etc/systemd/zram-generator.conf

[zram0]
zram-size = min(ram / 2, 16384)
compression-algorithm = zstd
swap-priority = 100
fs-type = swap

systemctl daemon-reexec

systemctl start /dev/zram0 systemctl start systemd-zram-setup@zram0.service

Then reboot.

lsblk

to see that the zram0 has been set up as swap

TIMESHIFT

install timeshift:

paru -S timeshift timeshift-autosnap sudo timeshift --list-devices sudo timeshift --create --comments "[10MAY2025] start of time" --tags D

sudo EDITOR=nvim systemctl edit --full grub-btrfsd !NOTE: rm : ExecStart=/usr/bin/grub-btrfsd –syslog /.snapshots add: ExecStart=/usr/bin/grub-btrfsd –syslog -t ExecStart=/usr/bin/grub-btrfsd –syslog –timeshift-auto

sudo grub-mkconfig -o /boot/grub/grub.cfg

COSMIC

some files did not install with cosmic-session added: sudo pacman -S cosmic-text-editor sudo pacman -S cosmic-terminal sudo pacman -S cosmic-wallpaper sudo pacman -S cosmic-player

for smb network shares in cosmic files sudo pacman -S gvfs-smb

Next: Optional Further Steps

install power-profiles-daemon:

!NOTE: you may also like to check out tlp, although for my use case tlp does not work with COSMIC’s power applet (see next step).

pacman -Syu power-profiles-daemon sudo systemctl enable --now power-profiles-daemon.service

install auto-cpufreq:

paru -S auto-cpufreq
sudo systemctl enable –now auto-cpufreq.service

install brave-browser: paru -S brave-browser

Printers

cups should be loaded and can be found in the desktop under System, ManagePrinting will pull the cups page http://localhost:631

Go to Administration and select Find New Printer I had to Add Printer for the HP_Blue socket://192.168.86.40:9100 or ipp://192.168.84.40/ipp/print

the main printer is socket://192.168.86.30:9100

PDF printer

update the cups-pdf.conf sudo nvim /etc/cups/cups-pdf.conf uncoment the out and set to Out ${HOME}/PDF

T480 Specific issues with Arch

Thermal throttling install throttled sudo pacman -S throttled sudo systemctl start throttled sudo systemctl enable throttled

Fingerprint reader

The fingerprint sensor is not supported by libfprint. There is a project python-validity based on open-fprintd, see [10]. Install python-validityAUR and enroll your fingerprint:

$ fprintd-enroll Refer to Fprint#Configuration for configuration.

You may experience an issue where the fingerprint reader does not work after the laptop wakes up from suspension. To fix this, try enabling the open-fprintd-resume and open-fprintd-suspend systemd services [11][dead link 2025-08-15—HTTP 404]. If the issue is still present, create a unit file as follows, then enable it [12].

/etc/systemd/system/fingerprint-restart.service [Unit] Description=Restart services to fix fingerprint integration After=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target

[Service] Type=oneshot ExecStart=systemctl restart open-fprintd.service python3-validity.service

[Install] WantedBy=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target If this solves the issue, you may disable open-fprintd-resume and open-fprintd-suspend again.

GRUB Theme

nstallation ( Manual )

Download your favourite version of the theme from Pling https://www.pling.com/p/1603282/ Now extract your downloaded .zip file.

Either manually extract it or use the command below. unzip dark-matter-debian.zip

Copy the theme directory. sudo cp -r dark-matter /boot/grub/themes/

Make changes to the GRUB config file. sudo nano /etc/default/grub Find the line GRUB_THEME= then change it to GRUB_THEME="/boot/grub/themes/dark-matter/theme.txt"

Then save the file.

Finally, update the grub. sudo grub-mkconfig -o /boot/grub/grub.cfg

NAS shares on fstab

set up /etc/fstab to load the nas shares on bootup

create smbcredentials

nvim ~/.smbcredentials within .smbcredentials username=nasusername password=naspassword

secure the file chmod 600 ~/.smbcredentials

create mount points for the shares sudo mkdir -p /media/nas/jim sudo mkdir -p /media/nas/viki sudo mkdir -p /media/nas/percifieldshare sudo mkdir -p /media/nas/media

modify /etc/fstab address of nas share [tab] mount point [tab] location of credentials then options These /etc/fstab options manage how filesystems mount at boot, focusing on reliability and network availability.

x-systemd.automount mounts on-demand, noauto prevents boot mounting,

_netdev waits for network,

nofail prevents boot failure if the device is missing.

Combining noauto,x-systemd.automount is ideal for removable or network drives.

Key Differences and Use Cases: x-systemd.automount: Mounts the filesystem only when it is first accessed, rather than at boot. It creates a systemd stub that intercepts access to the directory and mounts it on demand. noauto: Tells the system not to mount the device automatically at boot or with mount -a. The device is only mounted if explicitly requested later. Often used with x-systemd.automount. _netdev: Explicitly tells systemd that the mount depends on network access. It forces the mount to wait until the network is online. nofail: Allows the system to continue booting even if the mount fails (e.g., a disconnected USB drive). Without this, missing devices can stop the boot process.

Common Combinations: noauto,x-systemd.automount: Excellent for remote or slow drives; mounts only when you click on the folder. _netdev,nofail: Used for network drives that might not be available at boot, preventing a 90-second hang during boot. x-systemd.device-timeout=10s,nofail: Best for external USB drives, reducing the wait time if the device is unplugged.

iocharset=utf8 sets the encoding (default is iso8859-1 which is 256 characters) x-systemd.automount =

nas 192.168.86.177/jim

//192.168.86.177/jim /media/nas/jim cifs credentials=/home/jim/.smbcredentials,iocharset=utf8,x-systemd.automount,_netdev,nofail

add Viki user

sudo useradd -m -G wheel viki sudo passwd viki

Security

The following steps are the foundation of a secure Arch system. There are additional steps that you may of course take to harden your system further, and so you should consider this as a starting point.

Secure Boot

Step 1: Boot into your system BIOS, and:

Clear Vendor Keys (if you are not dual booting);

Disable Secure Boot; and,

Ensure that Setup Mode is enabled. Step 2: Configure your system for Secure Boot

Install sbctl

sudo pacman -Syu sbctl

Generate Keys

sudo sbctl create-keys

Enroll your keys

sudo sbctl enroll-keys

NOTE: this is the compressed kernel that your bootloader will load at boot. If you are using other kernel versions (e.g. linux-zen, linux-lts) you will need to sign these too!

create the grub image:

Reinstall grub:

sudo grub-install –target=x86_64-efi –efi-directory=/boot –bootloader-id=GRUB –disable-shim-lock –modules=“tpm” –recheck

NOTE: –disable-shim-lock disables GRUB’s built in shim lock protocol support. This flag is optional, and should only be passed if you are using custom keys (not the Microsoft Signed shim mechanism).

make the grub config:

sudo grub-mkconfig -o /boot/grub/grub.cfg

sign the necessary binaries loaded at boot:

sudo sbctl sign -s /boot/vmlinuz-linux sudo sbctl sign -s /boot/EFI/GRUB/grubx64.efi

Step 3: REBOOT AND DISABLE SECURE BOOT TO ENSURE IT IS WORKING

create a GRUB password:

grub-mkpasswd-pbkdf2 set superusers=“admin” password_pbkdf2 admin

Restrict access to grub files

sudo chmod 600 /boot/grub/grub.cfg sudo chmod -R 700 /etc/grub.d

prevent modifications to your grub file:

chattr +i /boot/grub/grub.cfg

update /etc/default/grub:

set GRUB_DISABLE_RECOVERY=“true”; and,

set GRUB_DISABLE_OS_PROBER=true.

Make the grub config:

grub-mkconfig -o /boot/grub/grub.cfg

Reboot the machine and disable Secure Boot in the BIOS