Building Your Own ISO with archiso
Official AcreetionOS Documentation & Step-by-Step Tutorial
Every distribution you have ever booted was assembled from a list of files and a list of packages. Arch ships the tool that does this — archiso — and the recipe it reads is called a profile. This guide is how to build an image of your own: one with your packages, your name on the boot menu, and a pacman configuration you chose.
1. What you need
archiso builds images only on Arch Linux. You need a plain Arch installation, not this distribution's customised one, because the build reads the system's pacman configuration.
- An Arch Linux machine with at least 10 GB of free space.
- The build packages:
arch-install-scripts(which providespacstrap),libisoburn(forxorriso),squashfs-tools,dosfstools,e2fsprogs,mtoolsandgrub. - The archiso scripts themselves, from gitlab.archlinux.org/archlinux/archiso.
On Arch:
sudo pacman -S --needed arch-install-scripts libisoburn squashfs-tools dosfstools e2fsprogs mtools grub
2. What a profile is
A profile is a directory. That directory is the recipe — there is no manifest pointing at a set of files elsewhere. Every profile has the same five parts:
profiledef.sh- The identity of the image: its name, its label, where its files sit on the disc, and which boot loaders to bake in.
packages.x86_64- What goes inside. One package per line. Blank lines and lines starting with
#are ignored. pacman.conf- Where those packages come from while the image is being built.
airootfs/- Files copied onto the image's own root filesystem before the packages are installed.
grub/,syslinux/,efiboot/- The boot menus, one directory per boot loader.
3. A minimal profile
Copy the upstream baseline profile and edit it. It is the right starting point because it
is small and it works:
cp -r archiso/configs/baseline ~/my-profile
mkdir -p ~/my-profile/work ~/my-profile/out
profiledef.sh is where the image is described:
iso_name="myflavour"
iso_label="MYFLAVOUR"
iso_publisher="Me"
iso_application="My Flavour Live/Install"
iso_version="2026.11.10"
install_dir="myflavour"
bootmodes=('bios.syslinux' 'uefi.grub')
pacman_conf="pacman.conf"
airootfs_image_type="squashfs"
airootfs_image_tool_options=('-comp' 'zstd' '-Xcompression-level' '19' '-b' '1M')
Two things to know about install_dir: it must be lowercase letters and digits only, and for
an ISO build it must be 30 characters or fewer. It is the directory your files live in on the finished
disc, and the boot menu points at it.
4. Pinning your mirrors
This is the step most people get wrong, and the failure is confusing. The upstream profiles inherit
/etc/pacman.d/mirrorlist — the build machine's mirror list. That makes the build
depend on the machine rather than on the profile, and if that machine's mirror list is wrong the build
fails after the work directory is already full, with an error that reads like a network fault.
Write your mirrors into the profile instead:
[core]
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch
[extra]
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch
Include = mirrorlist. pacman resolves a relative
Include against the directory you are standing in, not against the directory of the file
that contains it — so a profile with a sidecar mirror list builds from one directory and fails from
another, with error: config file mirrorlist could not be read.
5. The image's own pacman configuration
The profile's pacman.conf governs the build. The image has its own configuration
at /etc/pacman.conf inside it, and that one is what your users' pacman commands
will read.
To control it, put a pacman.conf in airootfs/etc/. It survives the build
because /etc/pacman.conf is a backup file of the pacman package: when a
backup file already exists and differs from the packaged one, pacman installs the packaged version as
.pacnew and leaves yours alone.
6. Building
./archiso/mkarchiso -w ~/my-profile/work -o ~/my-profile/out ~/my-profile
The build does not need root. mkarchiso uses user namespaces for the parts that need
privileges, so it works as an ordinary user as long as unprivileged user namespaces are enabled.
Your image lands in out/, named
<iso_name>-<iso_version>-<arch>.iso.
7. Testing it
A build that succeeds is not a build that works. At minimum, boot it:
./scripts/run_archiso.sh -i ~/my-profile/out/myflavour-2026.11.10-x86_64.iso
For a headless check, add console=ttyS0,115200 to the kernel command line in your boot menu
and boot it under QEMU with -display none -serial stdio. Then check that it reached a login
prompt.
8. Errors you will meet
mksquashfs: Unrecognised compressor option -Xbcj
The -X options belong to the compressor, not to mksquashfs. -Xbcj is
an xz option; zstd accepts only -Xcompression-level. Copying an option list
from one compressor to another fails at the rootfs step. mksquashfs -help-comp <compressor>
lists what yours takes.
error: config file mirrorlist could not be read
A relative Include in the profile's pacman.conf. Write the servers out in full.
The image boots, but pacman cannot install anything
The image needs two systemd units, not one:
airootfs/etc/systemd/system/etc-pacman.d-gnupg.mount
airootfs/etc/systemd/system/pacman-init.service
airootfs/etc/systemd/system/multi-user.target.wants/pacman-init.service
The first mounts a tmpfs over /etc/pacman.d/gnupg; the second runs
pacman-key --init and pacman-key --populate. Ship only the service and systemd
drops it without a word in the boot log, because a missing Requires=
dependency is a failed dependency. The image boots, the login prompt appears, and pacman inside it cannot
install a single package.
The mount is also why a key shipped in airootfs/etc/pacman.d/gnupg/ is masked at boot: that
directory is a fresh tmpfs every time. Add your own key after the mount, not before it.
[mkarchiso] ERROR: Failed to set permissions on '…'
A file_permissions entry in profiledef.sh names a path that does not exist in the
image. Files copied out of airootfs/ arrive as mode 644 owned by root, so
file_permissions is the only way to give a script an executable bit — but the path has to be
real.
9. Where to go next
- The wiki guides for the rest of the system.
- The beginner guide if you are new to Arch itself.
- The changelog for what changed.