Install a Linux distribution into a target directory using distribution-specific package managers and bootstrap wrappers.
Table of Contents#
- Overview
- Prerequisites
- Bootstrap by Distribution
- Post-Bootstrap Configuration
- systemd-nspawn as an Alternative
- Troubleshooting
- See Also
- Sources
1. Overview#
Bootstrapping is the process of installing a minimal Linux base system into a target directory. This is the foundation of Linux installation: disk partitions are created, formatted, and mounted (for example to /mnt), then the distribution's package manager installs packages into that mount point.
Most distributions provide specialized wrappers to simplify this process:
| Distribution | Package Manager | Bootstrap Wrapper |
|---|---|---|
| Alpine | apk | None (direct apk invocation) |
| Arch Linux | pacman | pacstrap |
| Debian/Ubuntu | apt | debootstrap |
| RHEL/Fedora/Alma | dnf | None (direct dnf --installroot) |
| Void Linux | xbps | xbps-install -R <repo> -r <root> |
| Gentoo | emerge | Stage3 tarball extraction |
These tools can create either chroot environments (for development, testing, or containers) or fully bootable systems.
2. Prerequisites#
- A functional Linux environment (live USB, existing installation, or another distribution)
- An active internet connection
- The relevant package manager or bootstrap wrapper installed
- A target partition or directory, mounted and ready
3. Bootstrap by Distribution#
3.1 Alpine Linux#
Alpine uses apk directly with mirror URLs and the --initdb flag. There is no official bootstrap wrapper.
apk -X "http://ftp.halifax.rwth-aachen.de/alpine/latest-stable/main" \
-X "http://ftp.halifax.rwth-aachen.de/alpine/latest-stable/community" \
-U --allow-untrusted -p /mnt --initdb add alpine-baseTo install a minimal base suitable for containers, replace alpine-base with alpine-baselayout.
3.2 Arch Linux#
Arch uses pacstrap, which wraps pacman for bootstrapping into a target directory.
pacstrap -K /mnt base linux linux-firmwareThe -K flag initializes an empty pacman keyring in the target. Add extra packages as needed (e.g., base-devel, networkmanager, vim).
3.3 Debian / Ubuntu#
Debian uses debootstrap, which downloads and installs a minimal Debian system.
debootstrap stable /mnt http://deb.debian.org/debian/- Replace
stablewith a specific codename:bookworm(stable),trixie(testing),sid(unstable), ornoblefor Ubuntu. - The
--variant=option controls the package set:- Default: full base including the Linux kernel
--variant=minbase: minimal base (smaller, suitable for containers)--variant=fakechroot: for unprivileged chroot environments
- For Ubuntu, use a Ubuntu mirror:
http://archive.ubuntu.com/ubuntu/
3.4 RHEL / Fedora / AlmaLinux#
RHEL-based systems use dnf with --installroot directly. There is no official bootstrap wrapper.
dnf --releasever=9 --best --repo=alma-baseos \
--installroot=/mnt --setopt=install_weak_deps=False \
groupinstall -y base core- Repository configuration is sourced from
/etc/yum.repos.d/on the host. - Group names vary by distribution:
base core(RHEL/Alma),critical-path-base core(Fedora). - For Fedora, use
--releasever=41(or current version) and--repo=fedora.
4. Post-Bootstrap Configuration#
After bootstrapping, additional configuration is needed before the system is bootable.
4.1 Generate fstab#
# Arch Linux (genfstab from arch-install-scripts)
genfstab -U /mnt >> /mnt/etc/fstab
# Other distributions (manual)
blkid /dev/<partition> | awk '{print $2}' # get UUID
# Then add entries to /mnt/etc/fstab manuallyExample /mnt/etc/fstab entry:
UUID=<partition-uuid> / ext4 defaults,noatime 0 1
UUID=<efi-uuid> /boot vfat defaults 0 2
UUID=<swap-uuid> none swap defaults 0 04.2 Enter the Chroot#
# Arch Linux
arch-chroot /mnt
# Other distributions (manual bind mounts)
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
mount --bind /run /mnt/run
chroot /mnt /bin/bash4.3 Basic System Configuration#
Run these commands inside the chroot:
# Set timezone
ln -sf /usr/share/zoneinfo/<Region>/<City> /etc/localtime
hwclock --systohc
# Set locale (uncomment desired locale in /etc/locale.gen first)
locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
# Set hostname
echo "<hostname>" > /etc/hostname
# Set root password
passwd4.4 Install and Configure the Bootloader#
GRUB (UEFI)#
# Install GRUB
pacman -S grub efibootmgr # Arch
apt install grub-efi-amd64 # Debian
# Install to EFI partition
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
# Generate config
grub-mkconfig -o /boot/grub/grub.cfgsystemd-boot (UEFI, simpler alternative)#
bootctl install
# Create /boot/loader/entries/arch.conf
cat > /boot/loader/entries/arch.conf << 'EOF'
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=UUID=<root-uuid> rw
EOF4.5 Install the Kernel (if not already included)#
# Arch
pacman -S linux linux-firmware
# Debian (usually included by debootstrap)
apt install linux-image-amd64 linux-headers-amd64
# RHEL/Alma
dnf install kernel kernel-core4.6 Network Configuration#
# systemd-networkd (minimal)
cat > /etc/systemd/network/20-wired.network << 'EOF'
[Match]
Name=en*
[Network]
DHCP=yes
EOF
systemctl enable systemd-networkd systemd-resolved
# Or install NetworkManager
pacman -S networkmanager # Arch
systemctl enable NetworkManager4.7 Unmount and Reboot#
exit # leave chroot
umount -R /mnt # recursive unmount
reboot5. systemd-nspawn as an Alternative#
systemd-nspawn provides a lightweight container environment that is more isolated than a plain chroot. It automatically sets up /dev, /proc, and /sys without manual bind mounts.
Quick Start#
# Boot into the bootstrapped system as a container
systemd-nspawn -bD /mnt
# Or get an interactive shell without booting init
systemd-nspawn -D /mntPersistent Containers with machinectl#
# Move bootstrapped directory to /var/lib/machines/
mv /mnt /var/lib/machines/<name>
# Start and enable the container
machinectl start <name>
machinectl enable <name>
# Get a shell inside
machinectl shell <name>Advantages over chroot#
- Automatic
/proc,/sys,/devsetup - Process isolation (PID namespace)
- Optional network isolation (
--network-veth) - Managed by
machinectlfor persistent containers - Supports boot into full init system (
-bflag)
Troubleshooting#
| Issue | Cause | Solution |
|---|---|---|
debootstrap fails with GPG errors | Missing keyring for target release | Install debian-archive-keyring on host, or use --no-check-gpg (insecure) |
pacstrap cannot resolve mirrors | No DNS in target | Ensure /etc/resolv.conf exists on host; pacstrap inherits host networking |
dnf --installroot missing groups | Wrong --releasever or repo name | Verify with dnf --releasever=<ver> group list on host first |
| Chroot fails with "exec format error" | Architecture mismatch (e.g., ARM on x86) | Install qemu-user-static and binfmt-support for cross-arch chroot |
| System boots to emergency shell | Missing or incorrect /etc/fstab | Boot from live USB, mount root, fix fstab UUIDs with blkid |
| GRUB error: "no such device" | EFI partition not mounted during grub-install | Mount EFI partition to /boot or /boot/efi and rerun grub-install |
| No network after first boot | Network service not enabled | Enable NetworkManager or systemd-networkd inside chroot before rebooting |