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