Creating a Bootable USB Drive with Arch Linux Live Image

Date: 09/08/2025

Today, we’ll create a “live” USB drive with the Arch Linux installation image. By “live,” I mean you’ll be able to install and remove programs, modify any files, and save changes while using it. I’ve prepared a detailed guide on the essential steps, but you’ll be able to customize everything to your liking from there.

Every Linux enthusiast has a favorite operating system. Some even have several, each tailored for specific tasks. One such special case is a portable system that you can boot on someone else’s machine or on your own if your main OS suddenly stops functioning properly.

There are many ready-made solutions designed for these tasks. However, we want to create a fully customized environment—one that’s familiar and equipped with the necessary programs!

There are two options here: create a bootable ISO image or simply install everything on a flash drive. The first option will result in a much more compact system, while the second option provides the important capability to install and remove programs and change settings while the system is running.

Yes, USB drives will wear out over time, but they are inexpensive these days, and being able to run a full-fledged operating system, in my opinion, is far more important.

Preparation

I will conduct all operations on Arch Linux for x86-64 and will use the original archiso, which is used to create official ISO images.

Therefore, the system must have the following packages installed: archiso, arch-install-scripts, and gptfdisk.

You can either install directly onto a USB drive or create a disk image that can later be written to a flash drive. I’ll now describe the process of creating a disk image.

Creating an Empty File Sized for the USB Drive

Navigate to the directory where we will create our image.

cd ~

The following actions will be performed with superuser privileges.

su

To help you navigate more easily, I’ll display the output of certain commands.

You can find out the exact size of the device using the command

lsblk -bo NAME,SIZE

lsblk -bo NAME,SIZE
NAME SIZE
sda4005527552
├─sda1 10485760
├─sda2 268435456
└─sda3 3725540864
mmcblk0 62226694144
├─mmcblk0p1 209715200
└─mmcblk0p2 62015930368

It will display all devices, and you’ll need to identify your USB drive among them.

Once you have the device number, you can create a command and specify the desired file size. Divide the size by 4096 to get the required number of blocks.

Examples:

16 GB: 16034824192 / 4096 = 3914752
4 GB: 4005527552 / 4096 = 977912

4096 is the standard sector size for a file system.

The command to create a file named usb.img with a size of 4 GB is:

dd if=/dev/zero of=usb.img bs=4096 count=977912 status=progress
$ dd if=/dev/zero of=usb.img bs=4096 count=977912 status=progress
Using /dev/zero to create a USB image...
3,651,747,840 bytes (3.7 GB, 3.4 GiB) copied, 8 seconds, 456 MB/s
977,912 records in
977,912 records out
4,005,527,552 bytes (4.0 GB, 3.7 GiB) copied, 8.78 seconds, 456 MB/s

Let’s check:

ls -la usb.img

Here’s the command used to list the detailed information of the file usb.img in a directory. The output shows:

  • File permissions: -rw-rw-r-- indicating it’s a regular file with read and write permissions for the owner and group, and read permission for others.
  • Number of links: 1
  • Owner: root
  • Group: root
  • File size: 4005527552 bytes
  • Last modified date and time: April 25 at 19:51
  • File name: usb.img

If the file turns out to be larger than needed, you can trim it to the desired length using truncate. For example, to reduce it to 16 GB:

truncate -s 16034824192 usb.img

Creating Disk Partitioning Layout

To allow our system to boot on computers using both BIOS and EFI, we need to partition the disk into three sections:

  1. 10 MB without a filesystem, required for installing the GRUB bootloader in BIOS mode.
  2. 256 MB, will be formatted to FAT32, here we will create the boot partition and install GRUB in EFI mode.
  3. The remaining space will be allocated to the root filesystem, which will be formatted as Ext4.

Creating a GPT Layout and Partitioning the Disk into Three Parts:

sgdisk -o -n 1:0:+10M -t 1:EF02 -n 2:0:+256M -t 2:EF00 -n 3:0:0 -t 3:8300 usb.img

$ sgdisk -o -n 1:0:+10M -t 1:EF02 -n 2:0:+256M -t 2:EF00 -n 3:0:0 -t 3:8300 usb.img
Creating new GPT entries in memory.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or kpartx(8)
The operation has completed successfully.

Mounting the Created Image into the System

We establish a connection between the image file usb.img and a loopback device. This allows us to interact with the image file as if it were a physical device, like a USB drive.

losetup --show -Pf usb.img

$ losetup –show -Pf usb.img
/dev/loop0

The command will display the name of the created device, which in this case is /dev/loop0.

Checking.

ls /dev/loop0*

$ ls /dev/loop0*
/dev/loop0
/dev/loop0p1
/dev/loop0p2
/dev/loop0p3

Our image should have three partitions: loop0p1, loop0p2, loop0p3.

Formatting Partitions

According to the standard, the EFI partition should be formatted in FAT32.

mkfs.fat -F32 /dev/loop0p2

$ mkfs.fat -F32 /dev/loop0p2
mkfs.fat 4.2 (2021-01-31)

The third section will be the main one, and you can choose any file system for it that is supported by both the bootloader and the kernel.

Formatting to Ext4:

mkfs.ext4 /dev/loop0p3

$ mkfs.ext4 /dev/loop0p3
mke2fs 1.46.5 (30-Dec-2021)


Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

Mount Partitions on /mnt/usb

First, we’ll mount the partition /dev/loop0p3, which will serve as our main partition for installing the system. Then, within this partition, we’ll create a directory /boot, where we’ll mount the partition /dev/loop0p2.

mkdir -p /mnt/usb
mount /dev/loop0p3 /mnt/usb
mkdir /mnt/usb/boot
mount /dev/loop0p2 /mnt/usb/boot

Copying airootfs

A few words about Archiso. This is the tool used to create official Arch Linux images. It consists of two parts: the mkarchiso script, which assembles the image, and a directory with the configuration settings for the upcoming image. We will need the configuration directory, which contains:

  • A list of packages that need to be installed, stored in the packages.x86_64 file.
  • The airootfs directory. Its structure is identical to that of Arch Linux and contains the system configuration files.

We will need to specify the path to the directory with Archiso settings three times. To make this easier, let’s assign the path to a variable.

export ARCHISO=/usr/share/archiso/configs/releng

We replicate the settings from the official image before installing packages. If a configuration file for a package already exists during its installation, the file is not overwritten; instead, a new file with the extension .pacnew is created. You will see warnings about this during the package installation process.

cp -afv $ARCHISO/airootfs/* /mnt/usb/

Translating Certain Files into Russian (Optional)

You can customize the system’s greeting message to whatever you like. The greeting file is located at /etc/motd. I’ve (okay, Yandex did) provided a simple translation of the original file, and below is the command to replace it.

wget -O /mnt/usb/etc/motd https://gitflic.ru/project/ksandr/archi/blob/raw?file=airootfs/etc/motd

In the installation image, there’s a command called Installation_guide that opens the system installation wiki page in a text-based console browser.

Replace the link so that it points to a Russian-language equivalent of the page.

sed -i 's/https:\/\/wiki.archlinux.org\/title\/Installation_guide/https:\/\/wiki.archlinux.org\/title\/Installation_guide\(%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9)/' /mnt/usb/usr/local/bin/Installation_guide

Installing Packages

The list of packages is taken from the official image settings.

Installation Command:

pacstrap -c -G -M -C $ARCHISO/pacman.conf -- /mnt/usb

To parse the list of packages, you can use the following command:

grep -v '^#' $ARCHISO/packages.x86_64 | tr '\n' ' ' | xargs pacstrap -c -G -M -C $ARCHISO/pacman.conf -- /mnt/usb

$ grep -v ‘^#’ packages.x86_64 | tr ‘\n’ ‘ ‘ | xargs pacstrap -c -G -M -C pacman.conf — /mnt/usb



(14/16) Reloading system bus configuration…
Skipped: Running in chroot.
(15/16) Warn about old perl modules
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LC_MESSAGES = “ru_RU.UTF-8”,
LANG = “ru_RU.UTF-8”
are supported and installed on your system.
perl: warning: Falling back to the standard locale (“C”).
(16/16) Updating the info directory file…

If the process concludes with these lines, you can proceed to the next step. If not, double-check to ensure you completed each action correctly.

Fine-Tuning the Setup

The main part of the installation aligns with what is written in the official wiki.

For convenience, I’ll repeat some of the steps from the official guide in this article.

We are generating the /etc/fstab file for our image, which is a list of file systems that are mounted during system startup.

genfstab -U /mnt/usb > /mnt/usb/etc/fstab

We’ll switch to a chroot environment. This will isolate the process from the rest of the system, creating a virtual environment where the process can operate as if it were on a separate system.

After executing this command, the current process and all its child processes will operate in an isolated environment with /mnt/usb as the root directory.

arch-chroot /mnt/usb

We need to edit the /etc/fstab file.

If the system you’re creating an image from uses a swap partition, then the entry for mounting this partition will be added to the /etc/fstab file when it’s generated.

You need to disable the swap partition in the fstab file if it exists. Remove or comment out the line that corresponds to it.

vim /etc/fstab

I also recommend changing the mount options from realtime to noatime. This reduces the number of write operations to the disk.

Below is an example of a file with modifications; the UUID values in your file will be different.

cat/etc/fstab cat /etc/fstab
/dev/loop0p3
UUID=d6ef477c-8db7-4b1b-9e55-a28fefbf03c1 / ext4 rw,noatime 0 1

$ /dev/loop0p2
UUID=C963-38B9/boot vfat rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro0 2

$ /dev/sda1
#UUID=8ac5fbc3-058e-4a18-a084-e68b52c1af46 none swap defaults0 0

Set your time zone.

ln -sf /usr/share/zoneinfo/Europe/Moscow /etc/localtime

The file /etc/locale.gen includes a list of available system localizations. It is recommended to keep these two:

en_US.UTF-8 UTF-8
ru_RU.UTF-8 UTF-8

Generate localization files.

locale-gen

Set a system-wide value for the LANG variable.

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

Set the font and layout switch parameters.

In the file /etc/vconsole.conf, enter:

KEYMAP=ru
FONT=cyr-sun16

info

Some of the manipulations described in this section can be performed directly with the archiso directory, reducing the number of steps required during installation.

Setting up Bootloaders

Start by creating an initial system boot disk.

Edit the configuration file located at /etc/mkinitcpio.d/linux.preset.

We will use the standard mkinitcpio configuration file, so make sure to modify the line that points to the config.

vim /etc/mkinitcpio.d/linux.preset
$ mkinitcpio preset file for the 'linux' package on archiso
PRESETS=('archiso')
ALL_kver='/boot/vmlinuz-linux'
archiso_config='/etc/mkinitcpio.conf'
archiso_image="/boot/initramfs-linux.img"

Edit the mkinitcpio configuration file. In the HOOKS parameter, you need to remove autodetect.

vim /etc/mkinitcpio.conf
...
HOOKS=(base udev microcode modconf kms keyboard keymap consolefont block filesystems fsck)
...

Regenerate the initcpio image.

info

The mkinitcpio image in Arch Linux is generated by the mkinitcpio script and includes all the necessary files and scripts for booting and initializing the system. This image is used during the boot process after the Linux kernel is loaded, but before the system is fully initialized and control is transferred to user space.

mkinitcpio -P

$ mkinitcpio -P
==> Building image from preset: /etc/mkinitcpio.d/linux.preset: ‘archiso’

==> Initcpio image generation successful

Install the bootloader for systems with BIOS. It is placed at the beginning of the disk, which is why we created the first partition.

Note: The command specifies the disk, not the disk partition!

grub-install --target=i386-pc --recheck /dev/loop0

$ grub-install –target=i386-pc –recheck /dev/loop0
Installation for i386-pc platform is in progress.
Installation completed successfully. No errors.

Installing the bootloader for EFI systems.

grub-install --target=x86_64-efi --efi-directory /boot --recheck --removable

$ grub-install –target=x86_64-efi –efi-directory /boot –recheck –removable
Installing for x86_64-efi platform.
Installation completed. No errors.

Create a configuration file for the bootloader.

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

$ grub-mkconfig -o /boot/grub/grub.cfg
Generating grub configuration file…
Found linux image: /boot/vmlinuz-linux
Found initrd image: /boot/intel-ucode.img /boot/amd-ucode.img /boot/initramfs-linux.img
Warning: os-prober will not be executed to detect other boot partitions.
Their systems will not be added to the GRUB boot configuration.
Refer to the documentation for the GRUB_DISABLE_OS_PROBER option.
Adding boot menu entry for UEFI firmware settings…
Found memtest86+ image: /boot/memtest86+/memtest.bin
/usr/bin/grub-probe: warning: unknown device type loop0.
Found memtest86+ EFI image: /boot/memtest86+/memtest.efi
/usr/bin/grub-probe: warning: unknown device type loop0.
done

As you might have understood, we have installed two bootloaders, and both of them refer to a single configuration file.

The official ISO image of Arch Linux uses the Syslinux bootloader. You could use it too; it’s a matter of preference. I opted for a simpler configuration option.

Configuring Logging

To reduce the number of disk accesses, configure logging to use RAM instead of the disk.

Creating a Directory:

mkdir -p /etc/systemd/journald.conf.d

Record the following settings in the file /etc/systemd/journald.conf.d/10-volatile.conf:

[Journal]
Storage=volatile
SystemMaxUse=16M
RuntimeMaxUse=32M

Additional Setup Steps

When creating an ISO disk image using mkarchiso, some configurations are handled using “hooks” (command-line scripts) in the pacman package manager. These hooks are removed during the ISO creation process.

Since we are building the image ourselves, we need to manually remove certain hooks.

rm -v -- $(grep -Frl 'remove from airootfs' /etc/pacman.d/hooks/)

Setting the Root Password (Optional)

By default, there is no password set for the root user, allowing you to establish your own. During startup, the system automatically logs in as root.

SSH access for the root user is also enabled by default.

passwd
$ passwd
New password:
Retype new password:
passwd: password successfully updated

You can also create a regular user.

Image Ready: Unmount Devices

Exiting chroot.

exit

Unmount the partitions in reverse order.

umount /mnt/usb/boot
umount /mnt/usb

We will deactivate the loop device mapping to the usb.img file.

losetup -D

Writing the Image to a USB Drive

Attention! If you haven’t broken your system yet, this might be a great opportunity to do so. So be extremely cautious.

www

A detailed description of how to write the image is available in the official Arch Linux wiki.

Connect the USB drive to the system and enter the command:

lsblk -piaf

Find the USB drive in the list and note down its number.

And write the image to it. In the command below, replace the of=/dev/sdX parameter (substitute the letter of your drive for X).

dd if=usb.img of=/dev/sdX bs=4096 status=progress && sync

Exit the root environment:

exit

Testing the Image with QEMU (Optional)

To test how our image operates, we can run it in an emulator.

This section assumes that you have these packages installed:

qemu-base tigervnc openbsd-netcat

You can launch a virtual machine from the created image using the following command:

qemu-system-x86_64 -drive file=usb.img,format=raw -m 1024 -enable-kvm -monitor unix:/tmp/monitor.sock,server,nowait

VNC server running on 127.0.0.1:5901

You can connect to the virtual machine using any VNC client.

For TigerVNC, the command to connect would be as follows:

vncviewer 127.0.0.1:5901

TigerVNC Viewer v1.13.1
Build date: 2024-01-20 02:29
Copyright (C) 1999-2022, TigerVNC Team and many others (see README.rst)
More information about TigerVNC can be found at https://www.tigervnc.org

To connect to the virtual machine’s management console, you can use tools like nc (netcat).

nc -U /tmp/monitor.sock

QEMU 9.0.0 monitor – type ‘help’ for more information
(qemu)

Summary

We have a system installation image file that can be written to any media. The key feature is that once you boot from it, you can install additional packages and configure the system to meet your specific needs.

I used a 4 GB flash drive, and after performing all the necessary actions, 1.2 GB of free space remained on it.

[

Bonus Tips

This disk imaging method is versatile and can be used with various Archiso configurations. For example, it can be applied with Ctlos, one of the locally developed Arch Linux distributions.

The author, Сtlos, uses a custom repository for certain packages. You can find the instructions for connecting it on the project page.

Alternatively, you can edit the pacman.conf file (located in the configuration directory) by adding an additional repository and disabling package signature verification.

Here is an example of a modified pacman.conf file:

...
[ctlos_repo]
SigLevel = Optional TrustAll
Server = https://github.com/ctlos/$repo/raw/master/$arch
Server = https://osdn.net/projects/ctlos/storage/$repo/$arch
Server = https://cvc.keybase.pub/$repo
#Include = /etc/pacman.d/ctlos-mirrorlist
[ctlos-aur]
SigLevel = Optional TrustAll
Server = https://github.com/ctlos/$repo/raw/master/$arch
Server = https://osdn.net/projects/ctlos/storage/$repo/$arch
Server = https://cvc.keybase.pub/$repo
#Include = /etc/pacman.d/ctlos-mirrorlist

Important point: It’s better to clone a remote repository as root because all files in the configuration directory should belong to the root user.

Related posts:
2023.02.13 — First Contact: Attacks on Google Pay, Samsung Pay, and Apple Pay

Electronic wallets, such as Google Pay, Samsung Pay, and Apple Pay, are considered the most advanced and secure payment tools. However, these systems are also…

Full article →
2022.06.01 — F#ck AMSI! How to bypass Antimalware Scan Interface and infect Windows

Is the phrase "This script contains malicious content and has been blocked by your antivirus software" familiar to you? It's generated by Antimalware Scan Interface…

Full article →
2023.02.21 — Herpaderping and Ghosting. Two new ways to hide processes from antiviruses

The primary objective of virus writers (as well as pentesters and Red Team members) is to hide their payloads from antiviruses and avoid their detection. Various…

Full article →
2022.02.15 — Reverse shell of 237 bytes. How to reduce the executable file using Linux hacks

Once I was asked: is it possible to write a reverse shell some 200 bytes in size? This shell should perform the following functions: change its name…

Full article →
2022.06.02 — Blindfold game. Manage your Android smartphone via ABD

One day I encountered a technical issue: I had to put a phone connected to a single-board Raspberry Pi computer into the USB-tethering mode on boot. To do this,…

Full article →
2022.06.01 — WinAFL in practice. Using fuzzer to identify security holes in software

WinAFL is a fork of the renowned AFL fuzzer developed to fuzz closed-source programs on Windows systems. All aspects of WinAFL operation are described in the official documentation,…

Full article →
2023.07.07 — Evil Ethernet. BadUSB-ETH attack in detail

If you have a chance to plug a specially crafted device to a USB port of the target computer, you can completely intercept its traffic, collect cookies…

Full article →
2023.03.03 — Infiltration and exfiltration. Data transmission techniques used in pentesting

Imagine a situation: you managed to penetrate the network perimeter and gained access to a server. This server is part of the company's internal network, and, in theory, you could…

Full article →
2022.02.09 — Kernel exploitation for newbies: from compilation to privilege escalation

Theory is nothing without practice. Today, I will explain the nature of Linux kernel vulnerabilities and will shown how to exploit them. Get ready for an exciting journey:…

Full article →
2022.06.01 — Routing nightmare. How to pentest OSPF and EIGRP dynamic routing protocols

The magic and charm of dynamic routing protocols can be deceptive: admins trust them implicitly and often forget to properly configure security systems embedded in these protocols. In this…

Full article →