In this documentation, Arch Linux is installed in a virtual machine for testing purposes. I downloaded the ISO file from the official website.
If you are new to Arch, I strongly recommend starting in a VM rather than installing it directly on your computer (bare-metal installation). In a VM, you can take snapshots and revert to a working state if something goes wrong. On a physical system, a single mistake during installation can break the OS and make recovery more complicated than necessary.
For completeness, I’ve also included general notes on how the process would differ for a bare-metal installation. You can return to this documentation after completing the initial setup in a VM or after following a dedicated guide for local installation, which can be found in the Comprehensive Breakdown folder as "bare-metal-prep" or directly here.
Warning
If you are not familiar with Arch Linux, avoid installing it directly on bare metal. Start in a VM, get comfortable with the system, and only move to a physical installation once you’re confident in the process. If you choose to install bare-metal without prior experience, you do so entirely at your own risk — you’ve been warned.
In my case, this VM is hosted in my CSL (Cybersecurity Lab) using Proxmox. You can use any virtualization platform you prefer, such as VMware Workstation, VirtualBox, Hyper-V, or similar — all will work for this setup.
Since my CSL has ample resources, I allocated more than the average recommended specs. This ensures the VM runs as close to bare-metal performance as possible — even with heavy ricing, compiling from the AUR, or multitasking with multiple desktop environments.
| Resource | Minimum Specs | High-Performance Setup (Used) | Notes |
|---|---|---|---|
| CPU Sockets | 1 | 1 | 1 socket is optimal for VM scheduling efficiency. |
| CPU Cores | 4 | 8 | More cores drastically speed up package compilation and multitasking. |
| RAM | 8 GB | 16 GB | High RAM ensures smooth performance with multiple DE/WM setups and heavy applications. |
| Storage | 40 GB (SSD) | 100 GB (SSD-backed) | Extra space for themes, AUR builds, and snapshots; SSD significantly improves install and load times. |
| Swap | 2 GB | 2 GB | Small safety net; rarely used with high RAM allocation. |
| GPU / Video | VirtIO / VMware SVGA II | VirtIO / VMware SVGA II | Use with 3D acceleration enabled for smooth animations and compositor effects. |
| Network | VirtIO (Bridged) | VirtIO (Bridged) | Provides low-latency networking and fast package downloads. |
| Display VRAM | 64 MB | 256 MB | Higher VRAM improves rendering of animations and high-resolution wallpapers. |
| NUMA | Disabled | Enabled | Improves CPU and memory allocation efficiency on multi-core, multi-RAM-node systems. |
| CPU Type | Default | host / x86-64-v4 | host matches the host CPU exactly for max performance; x86-64-v4 enables the latest instruction set supported. |
Why this matters:
With 8 cores + 16 GB RAM, backed by NUMA and an optimized CPU type (host or x86-64-v4), this VM can:
- Compile large AUR packages quickly (e.g., Firefox, KDE Plasma)
- Run compositors like
picomor full desktop environments with animations and no lag - Host multiple DEs/WMs for testing without impacting responsiveness
- Fully leverage the server’s SSD-backed 2 TB storage for storing large themes, icon sets, and VM snapshots
The pre-installation stage can be thought of as preparing the foundation of the operating system before any actual software is installed. This involves setting up the essential environment — such as partitioning the disk, formatting file systems, and mounting the target directories — so that the installation process has a proper location to work with. Without this base, there would be no place to execute the installation or store the system files.
Boot Arch Linux according to your setup: if you’re using a VM, start the virtual machine; if you’re installing on bare metal, insert the USB stick, set it as the first boot device in the BIOS, and begin the pre-installation process.
When the pre-installation process begins and Arch Linux boots, you’ll be dropped into a terminal. At this stage, you can configure your keyboard layout to match your preferred language and layout.
# Lists all available keyboard layouts
localectl list-keymaps
# Example: set German keyboard layout
loadkeys de-latin1If you are unsure of the exact layout name, run localectl list-keymaps and search within the list (you can use grep to filter, e.g., localectl list-keymaps | grep de).
After configuring your keyboard layout, you can also change the font used in your terminal. This step is optional, but it demonstrates one of Arch Linux’s strengths — the ability to customize even the smallest details of your system. Console fonts are stored in /usr/share/kbd/consolefonts/. To explore the available fonts:
# Browse through all console fonts
ls /usr/share/kbd/consolefonts | lessAdditionally you can preview a font without permanently changing your configuration. Simply run:
# Temporary preview
setfont ter-v16n
setfont lat9w-16setfontapplies the font instantly.- The change lasts only until you reboot or switch consoles.
- The
.psf.gzfile extension and full path are optional when usingsetfont.
Once you find a font you like, you can make it the default by editing the /etc/vconsole.conf file:
nano /etc/vconsole.conf
# Add or edit the following line:
FONT=ter-v16nSave the file and reboot to apply the change.
You can check which boot mode your system is using during installation. The firmware’s bitness (UEFI 32-bit or 64-bit, or Legacy BIOS) must be compatible with the boot loader you plan to install.
Run:
cat /sys/firmware/efi/fw_platform_size64--> 64-bit UEFI mode (recommended)32--> 32-bit UEFI mode (rare, older hardware)- No such file or directory --> Legacy BIOS mode
In my case, running:
cat /sys/firmware/efi/fw_platform_sizereturned:
No such file or directory
This meant the VM was not booting in UEFI mode, but instead using Legacy BIOS (SeaBIOS). This is not necessarily a problem — Legacy BIOS is simply older technology. Compared to UEFI, it lacks certain modern features and can be slightly slower, but it works fine for most cases.
However, for the sake of this project and for better alignment with modern hardware, I decided to switch the VM to UEFI.
-
Shut down the VM completely.
- Do not just restart it; make sure it’s powered off.
-
Add an EFI Disk
- In the Proxmox web interface, go to: VM --> Hardware --> Add --> EFI Disk
- Storage: Select a fast storage location (e.g.,
local-lvmorlocal) - Size: Leave at default (usually 128 KB)
- Confirm.
-
Change BIOS type
- Go to VM --> Options --> BIOS
- Change from SeaBIOS to OVMF (UEFI).
- Save the change.
-
Check the machine type
- While still in Options, set Machine Type to
q35(recommended for UEFI VMs). - This improves hardware compatibility and supports PCIe devices better.
- While still in Options, set Machine Type to
-
Verify boot order
- Go to VM --> Options --> Boot Order.
- Ensure the CD/DVD drive with your Arch ISO is first in the list.
- Move the EFI Disk above the hard drive if possible.
-
Start the VM
- Boot normally.
- The VM should now start in UEFI mode.
Once you restart the VM, you may be unable to boot into the Arch Linux installer if Secure Boot is enabled. To resolve this:
- Open the Device Manager in the UEFI firmware interface.
- Navigate to Secure Boot Configuration.
- Disable Secure Boot.
- Save the changes and select Continue to proceed with booting.
After the system starts, you can verify that UEFI boot mode is active by running this command again:
cat /sys/firmware/efi/fw_platform_sizeIf it returns 64 or 32, you are in UEFI mode. If it returns No such file or directory, the system is still booted in Legacy BIOS mode.
These are the steps to ensure you have a intternet connection:
- Ensure that your network adapter is listed and enabled
ip link- Connect to the network
- Ethernet: Plug in the cable
- Wi-Fi: Authenticate to the wireless network using iwd.
- Configure your network connection
- DHCP: dynamic IP address and DNS server assignment should work out of the box for Ethernet, WLAN, and WWAN network interfaces.
- Static IP address: follow Network configuration Assign static IP address.
- Verify the connection with a simple ping
ping archlinux.org
Note
Since this Arch installation is running on a VM inside my CSL, no additional network setup was required. The Lab environment is already configured to provide internet connectivity to any VM that is assigned to the correct VLAN and connected to the appropriate Linux bridge.
In the Arch Linux live environment, systemd-timesyncd is enabled by default. This means the system clock will be automatically synchronized with internet time servers as soon as an internet connection is established.
You can verify the time status using:
timedatectlLook for System clock synchronized: yes to confirm that synchronization is active. If the clock is not synchronized, you can enable and start the time synchronization service:
timedatectl set-ntp trueArch uses timedatectl (part of systemd) to handle timezones. To list all available timezones, use this command:
timedatectl list-timezonesTip
You can scroll or search with / if the list is long.
To set your desired timezone, use this command:
sudo timedatectl set-timezone <timezone name>
# To verify the change again
timedatectlWhile automatic synchronization is preferred, you can manually set the system date and time using timedatectl:
# Set date and time (format: YYYY-MM-DD HH:MM:SS)
sudo timedatectl set-time "2025-08-14 19:30:00"To change only the date:
sudo timedatectl set-time "2025-08-14"To change only the time:
sudo timedatectl set-time "19:30:00"When detected by the live system, disks are assigned to block devices such as /dev/sda, /dev/nvme0n1, or /dev/mmcblk0. To identify available devices, use:
lsblk
# or
fdisk -lIgnore devices ending in rom, loop, or airootfs. For eMMC (mmcblk*), partitions like boot0, boot1, and rpmb can also be ignored.
Note
If the disk does not appear, ensure that the disk controller is NOT in RAID mode in your BIOS/UEFI settings.
At minimum, you will need:
- One partition for the root directory (
/). - For UEFI systems: an EFI System Partition (ESP).
- Swap space can be set up as a swap file, a dedicated partition, or with zram after installation.
Tip
Plan your partition scheme carefully to avoid risky conversions or resizing in the future. If an EFI partition already exists, reuse it — do not create a second one.
Use a tool such as fdisk to create or modify partition tables:
fdisk /dev/sdXOther options include cfdisk, gdisk, or parted.
Example layouts
UEFI with GPT
| Mount Point | Partition | Type | Suggested Size |
|---|---|---|---|
/boot¹ |
/dev/efi_partition |
EFI System Partition | 1 GiB |
[SWAP] |
/dev/swap_partition |
Linux swap | ≥ 4 GiB |
/ |
/dev/root_partition |
Linux root (x86-64) | Remainder (≥ 23–32 GiB) |
¹ Can also be mounted at /efi, depending on bootloader support.
BIOS with MBR
| Mount Point | Partition | Type | Suggested Size |
|---|---|---|---|
[SWAP] |
/dev/swap_partition |
Linux swap | ≥ 4 GiB |
/ |
/dev/root_partition |
Linux root | Remainder (≥ 23–32 GiB) |
In my case, I have a clean 100 GiB disk (/dev/sda) with nothing on it, just as intended in Proxmox. I need to make a fresh UEFI + GPT layout, but first I need to partition the disk with fdisk:
fdisk /dev/sdaInside fdisk, do this step by step:
-
Create a new GPT partition table
- Type
g--> creates a new empty GPT.
- Type
-
Create EFI System Partition (ESP)
- Type
n--> new partition. - Partition number:
1 - First sector: press Enter (default).
- Last sector:
+1G(1 GiB size). - Type
t--> change type --> select1--> enterEFI System.
- Type
-
Create swap partition
- Type
n--> new partition. - Partition number:
2 - First sector: press Enter
- Last sector:
+4G(at least 4 GiB; you can do 8 GiB if you want). - Type
t--> change type --> select2--> enterLinux swap.
- Type
-
Create root partition
/- Type
n--> new partition. - Partition number:
3 - First sector: press Enter
- Last sector: press Enter (take all remaining space).
- Leave type as default (
Linux filesystem).
- Type
-
Write changes
- Type
w--> save and exit.
- Type
Now you’ll have:
/dev/sda1= EFI (1 GiB)/dev/sda2= Swap (4 GiB)/dev/sda3= Root (≈95 GiB)
Tip
In my case, a single root partition is sufficient since this setup runs inside a VM on my CSL-Server.
For a bare-metal installation, however, it is generally recommended to create additional partitions such as /home, /var, /tmp, or /srv to improve data separation, security, and long-term system stability.
Now format them as follows:
# EFI partition
mkfs.fat -F32 /dev/sda1
# Swap partition
mkswap /dev/sda2
swapon /dev/sda2 # enable swap immediately
# Root partition
mkfs.ext4 /dev/sda3After formatting, mount them for the Arch installation:
# Mount root
mount /dev/sda3 /mnt
# Create boot dir for EFI
mkdir -p /mnt/boot
# Mount EFI
mount /dev/sda1 /mnt/bootSwap is already active with swapon.
For a detailed breakdown of these steps, including explanations of why they are necessary and what each one does, refer to the corresponding document here.
Arch downloads its packages from mirror servers. These are listed in /etc/pacman.d/mirrorlist.
By default, the Reflector utility generated this file when you booted into the live ISO. It picked 20 recently synchronized HTTPS mirrors, sorted by speed. To check or edit:
nano /etc/pacman.d/mirrorlistRecommendation:
- Keep fast and geographically close mirrors at the top.
- You can reorder them manually inside
nano.
Run the following to install the base system, kernel, and firmware:
pacstrap -K /mnt base linux linux-firmware nano man-db man-pages texinfo
# Additionally in my case
pacstrap -K /mnt git sudo htop opensshThis gives you:
- base --> core system (package manager, libraries, essential tools)
- linux --> kernel
- linux-firmware --> firmware for devices
- nano --> simple text editor
- man-db / man-pages / texinfo --> local documentation
If you are on bare metal, add CPU microcode:
-
Intel:
pacstrap -K /mnt base linux linux-firmware intel-ucode nano man-db man-pages texinfo
-
AMD:
pacstrap -K /mnt base linux linux-firmware amd-ucode nano man-db man-pages texinfo
Important
Microcode is critical for hardware-level bug and security fixes.
Once the base system is installed, we need to prepare it so that it can actually boot and behave like a normal Linux installation. Two critical steps here are:
- Generating the filesystem table (
fstab) - Changing root (
arch-chroot) into the new system
When Linux boots, it needs to know what partitions exist and where they should be mounted. This is what fstab (“file system table”) provides.
-
What it does:
- Maps partitions --> to their mount points (
/,/boot,/home, etc.) - Defines mount options (e.g. read/write, filesystem type, whether swap should activate, etc.)
- Ensures consistency: every reboot mounts the correct partitions in the correct places.
- Maps partitions --> to their mount points (
-
Why use
-Uor-L?-U: Refers to partitions by UUID (unique identifier). This is the most reliable, because even if the disk order changes (e.g.,/dev/sdabecomes/dev/sdb), Linux will still mount the correct partition.-L: Refers to partitions by label. Works too, but less robust.- Plain
/dev/sdaXreferences can break if drives are added/removed, so we avoid them.
This scans all mounted partitions under /mnt (your root, EFI, swap, etc.) and appends their definitions into /mnt/etc/fstab:
genfstab -U /mnt >> /mnt/etc/fstabCheck the file manually:
cat /mnt/etc/fstabIf anything looks wrong (wrong filesystem, missing mount point, etc.), edit it with nano before proceeding:
nano /mnt/etc/fstabWarning
A broken fstab will cause boot failures (e.g., if / or /boot aren’t mounted properly). That’s why checking it now is critical.
Up to this point, we’ve been working inside the Arch ISO live environment.
But now, we want to configure the system as if we were booted into it — setting hostname, locale, installing bootloader, etc. That’s what chroot (change root) does.
arch-chroot /mnt-
What happens:
- You’re now “teleported” into your installed system at
/mnt— but/mntbecomes/. - From this moment, everything you do (install packages, edit configs, set timezone, users, etc.) applies directly to your new Arch system.
- Think of it as “booting into your system without rebooting.
- You’re now “teleported” into your installed system at
-
Why this step matters:
- You cannot configure the system (like setting passwords, bootloader, locale) from the ISO — those configs must live in the installed root.
- Without
chroot, your new system is incomplete and won’t boot correctly.
Your system needs to know in which time zone it operates. This ensures:
- The clock displays correctly for your location.
- Daylight Saving Time (DST) is applied automatically if relevant.
ln -sf /usr/share/zoneinfo/Region/City /etc/localtimeComputers have two clocks:
- System clock (software clock) --> maintained by the Linux kernel, resets at boot.
- Hardware clock (RTC, Real-Time Clock) --> battery-backed clock on the motherboard, independent of OS.
We synchronize the system clock to the hardware clock so they match:
hwclock --systohcThis creates /etc/adjtime and assumes the hardware clock is in UTC (best practice). UTC avoids confusion with DST and multi-boot systems.
To prevent clock drift (when hardware slowly loses/gains seconds), enable automatic synchronization with internet time servers using systemd-timesyncd:
timedatectl set-ntp trueCheck status:
timedatectl statusLocalization defines how your system handles language, character sets, and formatting (dates, currency, decimal separators, etc.). To achieve this, edit /etc/locale.gen. Uncomment the locales you want. At least one UTF-8 locale is strongly recommended. For example:
en_US.UTF-8 UTF-8
de_CH.UTF-8 UTF-8
After that generate the locales, by running:
locale-genCreate /etc/locale.conf and set your main locale:
LANG=en_US.UTF-8
You can later switch language at any time by editing this file.
If you used a non-US keyboard layout during installation (e.g. German, Russian, Croatian, French), you should make it persistent. This ensures that your console (TTYs) uses the correct keyboard layout on every boot:
Create /etc/vconsole.conf:
KEYMAP=de-latin1
The hostname is the system’s name on the network. It makes your machine identifiable to you and to other machines/services. Create /etc/hostname and add a simple, unique name:
echo "test-archvm" > /etc/hostname- Must be 1–63 characters long.
- Only lowercase letters (
a–z), digits (0–9), and hyphens (-) are allowed. - Must not start or end with
-.
Next, link the hostname to 127.0.0.1 (loopback address) in /etc/hosts to avoid errors from programs that expect hostname resolution:
127.0.0.1 localhost
::1 localhost
127.0.1.1 arch-vm
127.0.1.1 is conventionally used for your machine’s hostname.
Arch does not come with preconfigured networking, so you need to set it up manually or install a tool.
There are two common approaches for network management on Arch Linux. Which one you choose depends on whether your system is a server/VM or a desktop environment.
- Built into systemd.
- Very lightweight, with no extra dependencies.
- Ideal for servers, headless setups, and lab VMs where only basic Ethernet/DHCP is required.
- Pairs well with environments like my CSL VLANs, where networking is already controlled by OPNsense.
systemctl enable systemd-networkd
systemctl enable systemd-resolved- Provides automatic handling of Ethernet, Wi-Fi, VPNs, and mobile broadband.
- Integrates seamlessly with desktop environments (GNOME, KDE, XFCE, etc.).
- Comes with both a command-line interface (
nmcli) and GUI tools. - Slightly more overhead than
systemd-networkd, but far more convenient for a full desktop setup.
pacman -S networkmanager
systemctl enable NetworkManagerSince this Arch Linux VM is meant as a testbed for a future bare-metal daily driver, I will use NetworkManager. This ensures the VM behaves like a real desktop OS (with Wi-Fi, VPN, and GUI support), rather than a stripped-down server.
During installation, mkinitcpio already created an initial ramdisk (initramfs) when the kernel package was installed with pacstrap.
In a standard VM setup (like this project), you normally don’t need to touch it again.
However, if you later configure LVM, full-disk encryption, or RAID, you must update the initramfs configuration (/etc/mkinitcpio.conf) and regenerate it with:
mkinitcpio -PSet a secure password for the root account so you can log in and perform administrative tasks:
passwdTip
Use a strong password (even for a VM) — this simulates the real-world bare-metal install and trains good security habits.
The system now needs a boot loader to load the kernel and initramfs. Since I'm using UEFI + GPT in this VM, the recommended boot loader is GRUB with EFI support.
pacman -S grub efibootmgrThen install GRUB to the EFI system partition and generate its config. After this step, the system will be bootable:
# Install GRUB to EFI
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
# Generate config
grub-mkconfig -o /boot/grub/grub.cfgBefore exiting chroot and rebooting, make sure everything is correct:
lsblk -f
swapon --show
ls -lh /boot/initramfs-linux*.img
ls -lh /boot/vmlinuz-linux
ls -R /boot/EFI
cat /boot/grub/grub.cfg | less
efibootmgr -v
cat /etc/fstab
cat /etc/hostname
cat /etc/locale.conf
timedatectlExit the chroot environment by typing exit or pressing Ctrl+d. Optionally manually unmount all the partitions with umount -R /mnt: this allows noticing any "busy" partitions, and finding the cause with fuser(1).
# Example
fuser -vm /mnt
lsof | grep /mntFinally, restart the machine by typing reboot: any partitions still mounted will be automatically unmounted by systemd. Remember to remove the installation medium and then login into the new system with the root account.
If everything has been configured and installed correctly, you should be able to log in to your root account and access the terminal.
Working as root is unsafe. Create a normal user and give it admin rights.
useradd -m -G wheel -s /bin/bash [name] # replace [name] with your username
passwd [name]Install and configure sudo:
pacman -S sudo
EDITOR=nano visudoUncomment this line so that members of the wheel group can use sudo:
%wheel ALL=(ALL:ALL) ALL
From now on, you should use this new user for everything.
Since this system will be used as a desktop, I installed NetworkManager (easy handling of Ethernet, Wi-Fi, VPNs):
pacman -S networkmanager
systemctl enable NetworkManager --nowInstall basic utilities you’ll always need:
pacman -S base-devel git htop wget curl unzip zipbase-devel--> compilers and tools (needed for the AUR).git--> for cloning AUR packages.htop--> process viewer.wget/curl--> download tools.zip/unzip--> archive utilities.
For stability and performance, install microcode updates:
# Intel CPU
pacman -S intel-ucode
# AMD CPU
pacman -S amd-ucodeHyprland requires working graphics drivers.
-
Intel:
pacman -S mesa
-
AMD:
pacman -S mesa xf86-video-amdgpu
-
NVIDIA (new cards):
pacman -S nvidia nvidia-utils
Hyprland runs on Wayland (not Xorg). Install the necessary packages:
pacman -S wayland xorg-xwayland xdg-desktop-portal-hyprland wl-clipboard \
grim slurp swappy \
polkit polkit-gnome \
seatdEnable seat management:
systemctl enable seatdInstall Hyprland and some required tools:
pacman -S hyprland hyprpaper hyprlock hypridle \
alacritty \
thunar \
pavucontrol pipewire pipewire-pulse wireplumber \
firefoxhyprland--> the compositor itself.hyprpaper--> wallpaper utility.hyprlock--> lockscreen.hypridle--> idle management.alacritty--> terminal emulator.thunar--> file manager.pipewire+pavucontrol--> modern audio stack.firefox--> browser.
To boot into Hyprland graphically, install a Display Manager. Recommended: GDM or SDDM.
pacman -S gdm
systemctl enable gdm👉 On reboot, you’ll get a login screen. Select Hyprland as your session.
For proper display and later ricing:
pacman -S ttf-dejavu ttf-liberation noto-fontsFor terminal icons and rice setups:
pacman -S ttf-nerd-fonts-symbolsOnce logged in as your new user, create Hyprland config:
mkdir -p ~/.config/hypr
cp /usr/share/hyprland/hyprland.conf ~/.config/hypr/This file (~/.config/hypr/hyprland.conf) is where all your ricing happens.
rebootAfter reboot --> login with your user --> select Hyprland --> enjoy your desktop. 🎉















