Skip to content

Arch Linux

This activity puts into practice the concepts from the Linux Server Planning and Configuration lecture. Where Debian’s installer handles partitioning, bootloader installation, user creation, and networking automatically, Arch Linux makes you do each step by hand. That is precisely the point: by the end of this exercise, you will have directly touched every layer of a Linux system that most distributions hide behind a setup wizard.

  • A laptop with a hypervisor installed (VirtualBox, UTM, or similar)
  • The archboot ISO image (used intentionally on both x86_64 and aarch64 so everyone follows the same workflow and screenshots):

Download the latest x86_64 ISO from release.archboot.com/x86_64/latest/iso/. Pick the ISO labelled latest.

  • About 2 GB of free disk space for the VM

Before booting the ISO, you need a virtual machine configured with the right resources and firmware.

  1. In your hypervisor (VirtualBox, UTM, VMware, etc.), create a new virtual machine with these settings:

    • Memory: 4096 MB
    • CPU: 2 cores
    • Disk: 8 GB, dynamically allocated
    • Network: NAT (the default)
    • Make sure (U)EFI is enabled
  2. Attach the Arch Linux ISO you downloaded as the optical drive (or virtual DVD), matching your architecture (x86_64 or aarch64).

  3. Make sure the firmware is set to (U)EFI, not legacy BIOS. In VirtualBox this is under Settings > System > Motherboard > Enable EFI. In UTM this is selected during VM creation. UEFI is required for the EFI System Partition you will create in the next section.

  1. Start the VM. The archboot ISO boots into a setup menu rather than dropping straight to a shell. When you see the menu, press Ctrl+C to exit it and reach the root shell prompt.

  2. Verify you have an internet connection (the VM’s NAT adapter piggybacks on your host’s network):

    Terminal window
    ping -c 3 archlinux.org

    If this fails, verify that the VM’s network adapter is enabled and set to NAT.

  3. Identify the name of your virtual disk:

    Terminal window
    fdisk -l

    fdisk -l lists all block devices and their partitions, showing the size, type, and sector layout of each. Look for a disk with roughly 8 GB of space: that is your virtual hard disk. On VirtualBox the disk is typically /dev/sda; on UTM it is typically /dev/vda. In all commands below, replace /dev/<disk> with your actual disk path.

A raw disk has no structure. Before Linux can use it, you must divide it into partitions and tell the firmware what each one is for. We will use the GPT (GUID Partition Table) scheme, which is required for UEFI booting and supports disks larger than 2 TB. We need three partitions:

  • EFI System Partition (ESP): A small FAT32 partition the firmware reads to find the bootloader. Every UEFI system needs one regardless of operating system.
  • Swap partition: Disk space the kernel uses as overflow when RAM is full, and for hibernation. It has no filesystem; the kernel manages it directly.
  • Root partition: The main filesystem where the entire Linux directory tree lives (/bin, /etc, /home, and everything else).
  1. Launch the partitioning tool:

    Terminal window
    # replace <disk> with your disk name, such as sda or vda
    fdisk /dev/<disk>
  2. Create the EFI System Partition. Type n for a new partition, then p for primary partition. Accept the default partition number (1) and default first sector. For the last sector, type +300M. After that type t, select partition 1, and set the hex code to uefi or ef (EFI System Partition).

    Command (m for help): n
    Partition type
    p primary (0 primary, 0 extended, 4 free)
    e extended
    Select (default p): p
    Partition number (1-4, default 1):
    First sector (..., default = 2048):
    Last sector. +/-sectors or +/-size{K,M,G,T,P} (...): +300M

    The +300M notation means “300 megabytes from the current position”: fidsk calculates the exact sector number for you.

    Command (m for help): t
    Partition number (1-4): 1
    Hex code (type L to list all codes): uefi
  3. Create the swap partition. Type n again, then p for primary partition. Accept defaults for partition number (2) and first sector. For the last sector, type +400M. After that type t, select partition 2, and set the hex code to swap or 82 (Linux swap).

    400 MB of swap is sufficient for a VM that will not hibernate. On a physical machine you would typically match swap to RAM size or use a swap file instead.

  4. Create the root partition. Type n again. Accept all defaults (partition 3, default first sector, default last sector to use all remaining space). By default, fdisk sets the hex code to Linux filesystem (83), which is correct for the root partition, so you do not need to change it.

    Accepting the default last sector uses all remaining disk space for the root partition. This is correct: root gets everything that is left after EFI and swap.

  5. Verify your work. Type p to print the partition table. You should see something like:

    Device Boot Start End Sectors Size Id Type
    /dev/sda1 2048 616447 614400 300M ef EFI (FAT-12/16/32)
    /dev/sda2 616448 1437695 821248 400M 82 Linux swap / Solaris
    /dev/sda3 1437696 16777215 15339520 7.3G 83 Linux
  6. Write the partition table. Type w.

Partitioning only defines boundaries on the disk. Formatting writes the actual filesystem data structures that the kernel needs to store files. Each partition gets the filesystem appropriate to its role.

  1. Format the EFI partition as FAT32:

    Terminal window
    mkfs.fat -F32 /dev/<disk>1

    The UEFI specification requires FAT32 on the ESP. The firmware reads it directly before any OS driver is loaded, so it cannot use a Linux-only format like ext4.

  2. Format the root partition as ext4:

    Terminal window
    mkfs.ext4 -F /dev/<disk>3

    The -F flag forces formatting even if the partition looks like it already has data.

  3. Initialize and activate swap:

    Terminal window
    mkswap /dev/<disk>2
    swapon /dev/<disk>2

    mkswap writes the swap header the kernel needs to recognize the partition as swap space. swapon activates it immediately for the live session.

Before pacstrap can install packages to the new system, the partitions need to be accessible as directories. We use /mnt as a temporary staging root.

  1. Mount the root partition:

    Terminal window
    mount /dev/<disk>3 /mnt
  2. Create the EFI mount point and mount the EFI partition:

    Terminal window
    mkdir -p /mnt/boot/efi
    mount /dev/<disk>1 /mnt/boot/efi

    When GRUB is installed later, it will write its EFI files into whatever is mounted at /boot/efi, so the mount point and the EFI partition need to match.

With the partitions mounted, pacstrap can download and install the core Arch Linux packages directly to your mounted root. The installation is transparent: you can see exactly which packages it installs and why.

  1. Install the base packages:

    Terminal window
    pacstrap /mnt base linux vim

    The three packages do different things:

    • base: the minimal userland (shell, coreutils, systemd, and other tools every Arch system needs). It does not include a kernel.
    • linux: the Linux kernel itself and its modules. Without this the system cannot boot.
    • vim: a text editor. The installed system has no editor by default; you need one to edit config files in the next steps.

    This installs about 120 packages in total and will take a few minutes depending on your internet speed.

  2. Generate the filesystem table:

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

    genfstab generates /etc/fstab, which maps partitions to mount points. The system reads it at every boot. The -U flag identifies each partition by UUID rather than by device name; UUIDs never change even if you add or rearrange disks. Run cat /mnt/etc/fstab to inspect the result.

To configure the installed system, you need to “pivot” into it using chroot (change root). arch-chroot remounts /mnt as the root directory (/) for this shell session, so every path and every command now refers to the installed system rather than the live environment. It also sets up special kernel filesystems like /proc and /sys inside the chroot so tools like grub-install work correctly.

  1. Enter the chroot:

    Terminal window
    arch-chroot /mnt

    Notice that your prompt likely changed. You are now running commands that affect the installed OS on disk, not the RAM-based live environment.

  2. Verify you are inside the chroot:

    Terminal window
    pwd

    The output should be /.

Inside the chroot, every change you make writes to the installed system on disk. Without a timezone and locale set, the system uses defaults that may display times incorrectly and cause internationalization issues in some programs.

  1. Set the timezone (adjust if you are not on the US West Coast):

    Terminal window
    cp /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
    date

    /usr/share/zoneinfo/ contains a database of timezone definitions for every region. Copying one to /etc/localtime tells the system which timezone to use for displaying times and for calculating DST transitions. Run date to confirm the timezone took effect. You can browse the directory (e.g., ls /usr/share/zoneinfo/America/) to find your region.

  2. Configure the locale. Open the locale configuration file:

    Terminal window
    vim /etc/locale.gen

    Find and uncomment these two lines (remove the leading #):

    en_US.UTF-8 UTF-8
    en_US ISO-8859-1

    A locale defines the language, character encoding, date format, number format, and other regional conventions for a system. en_US.UTF-8 is the standard modern choice for English; it supports all Unicode characters. en_US ISO-8859-1 is an older 8-bit encoding included for compatibility with legacy applications.

  3. Generate the locale and set it as default:

    Terminal window
    locale-gen
    echo LANG=en_US.UTF-8 > /etc/locale.conf
    export LANG=en_US.UTF-8

    locale-gen reads /etc/locale.gen and compiles the enabled locales into binary files under /usr/lib/locale/. locale.conf stores the default locale that every login session will use. The export command sets it for the current shell session so subsequent commands in this chroot also respect it.

GRUB bridges the UEFI firmware and the Linux kernel. The firmware finds GRUB on the EFI System Partition and hands control to it; GRUB then locates the kernel and starts it. Without a bootloader installed to the EFI partition, the VM will boot to a firmware error screen instead of Linux.

  1. Install GRUB and supporting EFI tools:

    Terminal window
    pacman -S grub efibootmgr dosfstools mtools

    Each package has a specific role:

    • grub: the bootloader itself, the program the firmware hands off to after POST, which then loads the kernel.
    • efibootmgr: a tool that writes entries into the UEFI firmware’s boot menu (the list of bootable devices stored in NVRAM). grub-install calls it internally.
    • dosfstools: utilities for creating and checking FAT filesystems. Required because the EFI partition is FAT32.
    • mtools: low-level tools for reading FAT filesystems without mounting them, used by GRUB during installation.
  2. Install GRUB to the EFI partition:

    Terminal window
    grub-install --target=x86_64-efi --bootloader-id=arch --recheck

    --target specifies the EFI architecture. --bootloader-id=arch sets the name that appears in the UEFI firmware’s boot menu and creates the directory /boot/efi/EFI/arch/ where GRUB’s EFI binary is written. --recheck forces GRUB to re-probe the EFI partition even if a previous installation is detected.

  3. Generate the GRUB configuration:

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

    grub-mkconfig scans the system for installed kernels and writes a configuration file that tells GRUB what to show in the boot menu and how to load each option. Never edit grub.cfg directly: always regenerate it with this command, because it will be overwritten the next time the kernel updates.

Logging in as root directly is unsafe for everyday use. You need a regular user account and a way to run administrative commands when needed. These steps create that account and grant it controlled root access via sudo.

  1. Install sudo:

    Terminal window
    pacman -S sudo
  2. Open the sudoers file (never edit it directly, always use visudo):

    Terminal window
    EDITOR=/usr/bin/vim VISUAL=/usr/bin/vim visudo

    visudo opens /etc/sudoers in a safe wrapper that validates the syntax before saving. Explicitly setting EDITOR and VISUAL ensures it launches Vim even if the default vi path is missing. A syntax error in sudoers can lock you out of sudo entirely, so direct editing with vim is dangerous.

    Find and uncomment this line:

    %wheel ALL=(ALL) ALL

    Breaking down the syntax: %wheel means “the group named wheel” (a leading % means group). ALL=(ALL) ALL means “from any host, as any user, run any command.” This grants full sudo access to everyone in the wheel group, the Arch equivalent of Ubuntu’s sudo group.

  3. Create a regular user with a home directory, bash shell, and wheel group membership:

    Terminal window
    useradd -m -G wheel -s /bin/bash archuser

    The flags: -m creates the home directory at /home/archuser; without it the directory is not created and many programs will misbehave. -G wheel adds archuser to the wheel supplementary group so sudo works. -s /bin/bash sets the login shell; without this the default shell is /bin/sh, which on Arch is a minimal POSIX shell rather than bash.

  4. Set the password:

    Terminal window
    passwd archuser

The chroot session has given you a complete installed system. Exit it, remove the ISO so the VM boots from disk instead of the live environment, and reboot.

  1. Exit the chroot:

    Terminal window
    exit
  2. Eject the ISO from the VM’s virtual optical drive (use your hypervisor’s UI).

    This is important: if the ISO is still attached, the VM may boot back into the live environment instead of the installed system. Remove it before rebooting.

  3. Reboot:

    Terminal window
    reboot

After a few seconds, GRUB should appear, select Arch Linux, and drop you at a login prompt. Log in as archuser with the password you set.

Your Arch system boots but has no hostname and no network service configured. These steps give the machine an identity and connect it to the network so you can install packages and administer it remotely.

  1. Set a hostname:

    Terminal window
    sudo hostnamectl set-hostname archbox

    Replace archbox with whatever single-word name you want for this machine. Verify it took effect:

    Terminal window
    hostnamectl
  2. Configure /etc/hosts:

    Terminal window
    sudo vim /etc/hosts

    Add these lines:

    127.0.0.1 localhost
    127.0.1.1 archbox.localdomain archbox

    /etc/hosts is a local DNS override file: the system checks it before querying a DNS server. The first line maps localhost to the loopback address, which is required for many local services. The second line maps the machine’s own hostname to 127.0.1.1: a convention that prevents programs from hanging when they try to resolve the local hostname before the network is fully up.

  3. Find your network interface name:

    Terminal window
    ip link

    You will see lo (loopback) and one other interface, likely enp0s3 or similar. Note the name.

  4. Create a systemd-networkd configuration file:

    Terminal window
    sudo vim /etc/systemd/network/20-wired.network

    Add the following (substitute your interface name if it differs):

    [Match]
    Name=enp0s3
    [Network]
    DHCP=yes

    The [Match] section tells systemd-networkd which interface this file applies to; without it the settings would apply to all interfaces. The [Network] section defines what to do with that interface; DHCP=yes tells it to request an IP address, gateway, and DNS configuration automatically via DHCP. The filename prefix 20- controls the order in which configuration files are processed; lower numbers load first.

  5. Enable and start the network service:

    Terminal window
    sudo systemctl enable --now systemd-networkd

    enable registers the service to start automatically at every boot. start starts it immediately. --now combines both into one command. Without enable, the service would start this session but not persist after a reboot.

  6. Verify you received an IP address:

    Terminal window
    ip addr show

    Look for an inet address on your interface (e.g., 10.0.2.15/24).

  7. Configure DNS so you can resolve domain names:

    Terminal window
    sudo vim /etc/resolv.conf

    Add:

    nameserver 1.1.1.1
    nameserver 1.0.0.1

    /etc/resolv.conf tells the system which DNS server to send name queries to. 1.1.1.1 and 1.0.0.1 are Cloudflare’s public resolvers. The system tries the first nameserver and falls back to the second if it does not respond. On production systems this file is usually managed automatically by systemd-resolved or NetworkManager; here we write it manually so nothing is hidden.

  8. Test your connection:

    Terminal window
    ping -c 3 archlinux.org
  1. Install the OpenSSH server:

    Terminal window
    sudo pacman -S openssh
  2. Enable and start the SSH daemon:

    Terminal window
    sudo systemctl enable --now sshd
  3. Add a NAT port-forwarding rule in your hypervisor:

    • Protocol: TCP
    • Host IP: 127.0.0.1
    • Host Port: 2222
    • Guest IP: leave blank (or use the VM’s NAT IP)
    • Guest Port: 22

    This maps 127.0.0.1:2222 on your laptop to 22 inside the Arch VM. You keep NAT for outbound internet access, while still being able to SSH in from the host. In UTM, you might need to switch the network mode to “Emulated VLAN” to enable port forwarding, as UTM’s “Shared Network” mode does not support it.

  4. From your host machine terminal, generate a key pair on your laptop (if you do not already have one):

    Terminal window
    ssh-keygen -t ed25519 -C "cs312-arch-host-key"

    Accept the default path (~/.ssh/id_ed25519) unless you want a course-specific filename. Remember the path you choose; you will need it in the next step.

  5. Copy your host public key into the VM using the forwarded SSH port:

    Terminal window
    ssh-copy-id -p 2222 archuser@127.0.0.1
    # If you used a non-default key name, add: -i /path/to/your/key

    If ssh-copy-id is unavailable, use this fallback from your host terminal:

    Terminal window
    cat ~/.ssh/id_ed25519.pub | ssh -p 2222 archuser@127.0.0.1 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
    # Replace id_ed25519.pub with your key name if you chose a different one
  6. Test key authentication from your host:

    Terminal window
    ssh -p 2222 archuser@127.0.0.1
    # If you used a non-default key name, add: -i /path/to/your/k

    You should receive a shell prompt without entering the VM password.

  7. (Optional) Verify that the SSH service is working from inside the VM using password authentication:

    Terminal window
    ssh archuser@localhost

    When prompted for a password, enter the password you set for archuser during installation. This confirms SSH is working; you are using password auth here since the private key exists only on your host machine.

  8. Locate the password authentication setting:

    Terminal window
    grep PasswordAuthentication /etc/ssh/sshd_config

    On a production server exposed to the internet you would set this to no after confirming key auth works. Disabling password auth means an attacker who does not have your private key file cannot log in, even with the correct password. For this course VM, keep password auth enabled unless an activity explicitly tells you to disable it.

Now that your system boots and services are running, inspect live process IDs so the PID concepts from the lecture become concrete.

  1. Confirm which process is PID 1:

    Terminal window
    ps -p 1 -o pid,ppid,comm,args

    You should see systemd as PID 1.

  2. Find PID 2 and identify what it does:

    Terminal window
    ps -p 2 -o pid,ppid,comm,args

    On most Linux systems this is kthreadd, the kernel thread manager.

  3. Inspect the process tree from the top:

    Terminal window
    ps -e -o pid,ppid,comm --forest | head -40

    Notice how many processes ultimately descend from PID 1.

  4. Pick a service you enabled, then inspect its PID and parent:

    Terminal window
    systemctl status sshd
    ps -C sshd -o pid,ppid,comm,args

    Compare the service’s PID to its PPID to see how systemd supervises it.

  5. Inspect /proc for one running process:

    Terminal window
    cat /proc/1/status | head -20

    This shows the kernel’s process metadata view, including name, state, and PID values.

Your Arch Linux system is installed, networked, and running. Run these commands to confirm everything is in order.

  1. Show system identity and kernel version:

    Terminal window
    hostnamectl

    You will see the hostname you chose, the architecture, and the kernel version you installed.

  2. Confirm your user and group memberships:

    Terminal window
    id

    The output should show archuser with wheel as a supplementary group, confirming that sudo access is configured correctly.

  3. Show active services:

    Terminal window
    systemctl list-units --type=service --state=active

    You should see sshd and systemd-networkd in the list alongside core system services.

  4. Confirm network reachability:

    Terminal window
    ping -c 3 archlinux.org

    All three pings should succeed.

  5. You can now safely shut down the VM:

    Terminal window
    sudo shutdown -h now

    The -h flag is the halt flag. Without it, Arch might reboot instead. Alternatively, you can use sudo poweroff.

Don’t delete your VM just yet! You will use it again in the next activity.

Want to install Arch on real hardware? The Arch Wiki has an excellent installation guide that covers the same steps as this activity but with more details and troubleshooting tips, including more advanced options like LVM, encryption, and desktop environments.