Arch Linux on VirtualBox, Omarchy-style.
// command by command, no installer UI.
This mirrors the Omarchy ISO installer flow: 2 GiB EFI, LUKS, Btrfs subvolumes, and Limine via archinstall JSON files.
# pacman -Sy --noconfirm archinstall jq openssl
install tools in live ISO
# cat > user_configuration.json <
define Omarchy-style disk + boot + fs layout
# archinstall --config user_configuration.json --creds user_credentials.json
// contents
Before you start
VirtualBox settings
Boot live ISO and prep
Set install variables
Build credentials JSON
Build archinstall config JSON
Run install
First boot checks
Optional: install Omarchy layer
Troubleshooting
Sources
Before you start
- This is destructive. It wipes the selected VM disk.
- All commands are for the Arch ISO live shell as
root. - Disk names on VirtualBox are usually
/dev/sdaor/dev/vda. Verify before running. - Goal is to reproduce Omarchy installer structure, but manually.
// wipe warning
If DISK points to the wrong device, your data is gone. Confirm with lsblk every time.
VirtualBox settings
- Type: Linux, Version: Arch Linux (64-bit).
- Enable EFI: Settings -> System -> Motherboard -> Enable EFI.
- RAM: 8192 MB recommended.
- CPU: 2 or more vCPUs.
- Disk: 64 GB dynamic VDI recommended.
- Attach latest Arch ISO as optical drive, then boot it.
Boot live ISO and prep
live environment
timedatectl set-ntp true ip link ping -c 3 archlinux.org lsblk -d -e 7,11 -o NAME,SIZE,MODEL pacman -Sy --noconfirm archinstall jq openssl # If keyring errors appear on an older ISO, reset keyring: killall gpg-agent rm -rf /etc/pacman.d/gnupg pacman-key --init pacman-key --populate archlinux pacman -Sy archlinux-keyring
Set install variables
This is the data Omarchy's configurator normally asks for interactively.
replace values first
export DISK="/dev/sda" export HOSTNAME="archbox" export USERNAME="steven" export TIMEZONE="America/New_York" export KEYBOARD="us" lsblk "$DISK" printf "Set install password: " stty -echo; read PASSWORD; stty echo; echo PASSWORD_HASH=$(printf '%s' "$PASSWORD" | openssl passwd -6 -stdin)
Build credentials JSON
Omarchy passes plaintext encryption password + hashed login passwords to archinstall.
user_credentials.json
password_escaped=$(echo -n "$PASSWORD" | jq -Rsa) password_hash_escaped=$(echo -n "$PASSWORD_HASH" | jq -Rsa) username_escaped=$(echo -n "$USERNAME" | jq -Rsa) cat > user_credentials.json <{ "encryption_password": $password_escaped, "root_enc_password": $password_hash_escaped, "users": [ { "enc_password": $password_hash_escaped, "groups": [], "sudo": true, "username": $username_escaped } ] } EOF
Build archinstall config JSON
This matches the Omarchy disk layout: 2 GiB EFI + encrypted Btrfs root + subvolumes.
size math from Omarchy configurator
disk_size=$(lsblk -bdno SIZE "$DISK") mib=$((1024 * 1024)) gib=$((mib * 1024)) disk_size_in_mib=$((disk_size / mib * mib)) gpt_backup_reserve=$mib boot_partition_start=$mib boot_partition_size=$((2 * gib)) main_partition_start=$((boot_partition_start + boot_partition_size)) main_partition_size=$((disk_size_in_mib - main_partition_start - gpt_backup_reserve))
user_configuration.json
cat > user_configuration.json <
{
"archinstall-language": "English",
"audio_config": { "audio": "pipewire" },
"bootloader": "Limine",
"disk_config": {
"btrfs_options": {
"snapshot_config": { "type": "Snapper" }
},
"config_type": "default_layout",
"device_modifications": [
{
"device": "$DISK",
"partitions": [
{
"flags": ["boot", "esp"],
"fs_type": "fat32",
"mountpoint": "/boot",
"obj_id": "ea21d3f2-82bb-49cc-ab5d-6f81ae94e18d",
"size": { "unit": "B", "value": $boot_partition_size, "sector_size": { "unit": "B", "value": 512 } },
"start": { "unit": "B", "value": $boot_partition_start, "sector_size": { "unit": "B", "value": 512 } },
"status": "create",
"type": "primary"
},
{
"btrfs": [
{ "mountpoint": "/", "name": "@" },
{ "mountpoint": "/home", "name": "@home" },
{ "mountpoint": "/var/log", "name": "@log" },
{ "mountpoint": "/var/cache/pacman/pkg", "name": "@pkg" }
],
"flags": [],
"fs_type": "btrfs",
"mount_options": ["compress=zstd"],
"mountpoint": null,
"obj_id": "8c2c2b92-1070-455d-b76a-56263bab24aa",
"size": { "unit": "B", "value": $main_partition_size, "sector_size": { "unit": "B", "value": 512 } },
"start": { "unit": "B", "value": $main_partition_start, "sector_size": { "unit": "B", "value": 512 } },
"status": "create",
"type": "primary"
}
],
"wipe": true
}
],
"disk_encryption": {
"encryption_type": "luks",
"iter_time": 2000,
"lvm_volumes": [],
"partitions": ["8c2c2b92-1070-455d-b76a-56263bab24aa"],
"encryption_password": $password_escaped
}
},
"hostname": "$HOSTNAME",
"kernels": ["linux"],
"locale_config": {
"kb_layout": "$KEYBOARD",
"sys_enc": "UTF-8",
"sys_lang": "en_US.UTF-8"
},
"mirror_config": {
"custom_repositories": [],
"custom_servers": [
{ "url": "https://geo.mirror.pkgbuild.com/\$repo/os/\$arch" },
{ "url": "https://mirror.rackspace.com/archlinux/\$repo/os/\$arch" }
],
"mirror_regions": {},
"optional_repositories": []
},
"network_config": { "type": "iso" },
"ntp": true,
"packages": ["base-devel", "git", "networkmanager", "snapper", "btrfs-progs"],
"parallel_downloads": 8,
"services": ["NetworkManager"],
"swap": true,
"timezone": "$TIMEZONE"
}
EOF
Run install
install
archinstall --config user_configuration.json --creds user_credentials.json
When it finishes, reboot and remove the ISO from the VM optical drive.
reboot
reboot
First boot checks
inside installed system
systemctl status NetworkManager findmnt -n -o FSTYPE / sudo btrfs subvolume list / lsblk -f
If limine-update exists, run it once after first full update:
boot entries refresh
sudo pacman -Syu --noconfirm command -v limine-update && sudo limine-update
Optional: install Omarchy layer
If you want full Omarchy after base Arch is up, run the official boot script:
optional
curl -fsSL https://raw.githubusercontent.com/basecamp/omarchy/master/boot.sh | bash
// note
This guide gives you the Omarchy installer disk/encryption/layout flow first. The optional command above adds the full Omarchy environment on top.
Troubleshooting
- No boot after install: confirm EFI is enabled in VirtualBox and ISO was detached after install.
- Wrong disk selected: reboot live ISO and verify with
lsblk -d -o NAME,SIZE,MODELbefore rerunning. - archinstall complains about old mounts: run
findmnt -R /mnt &>/dev/null && umount -R /mntfirst. - Timezone not accepted: verify with
timedatectl list-timezones | rg -n "New_York".