Compare commits

...
Author SHA1 Message Date
David Heinemeier Hansson efd01e815a Revert "Exclude install media from disk picker (#73)"
This reverts commit eadb1c05d4.
2026-04-28 11:57:07 +02:00
Michael Placzek eadb1c05d4 Exclude install media from disk picker (#73)
* Exclude install media from disk picker

* Document boot-disk exclusion in configurator
2026-04-24 22:22:30 +02:00
mijuny 94494c8837 Disable xe Panel Replay on live boot for Panther Lake compatibility (#77) 2026-04-24 22:21:46 +02:00
David Heinemeier Hansson ed4536cab4 Need to clear out old packages even just on regular make 2026-04-16 22:35:39 +02:00
David Heinemeier Hansson dc8242c8c7 Expand patch for python 3.14 issue with archinstall 4.2 2026-04-16 22:33:21 +02:00
David Heinemeier Hansson c43841c827 Batch archinstall 4.2 regression 2026-04-16 22:18:31 +02:00
David Heinemeier Hansson b341fa6eea Add --rc option 2026-04-16 16:10:50 +02:00
David Heinemeier Hansson f73062e156 Clear out packages that might conflict on build 2026-04-03 19:18:57 +02:00
David Heinemeier Hansson 0ace44e96e Include workaround for panther lake audio issue on 6.19 kernel 2026-03-16 22:13:11 +01:00
David Heinemeier Hansson 78af4402e4 Ensure all indicators are executable 2026-02-21 17:40:49 +01:00
David Heinemeier Hansson 6aff2b3e20 Give better information for the drive selection
Model/vendor + known partitions
2026-02-21 17:06:20 +01:00
David Heinemeier Hansson 772d4e2813 Plan revisions 2026-02-21 15:20:44 +01:00
David Heinemeier Hansson 0cbe625343 Add plans for dual boot and OEM installs 2026-02-21 09:39:17 +01:00
Ryan Hughes 5756f35844 Update pacman conf to use for build 2026-02-19 12:44:54 -05:00
Ryan Hughes 83a54e7fd5 Use offline for boot 2026-02-19 12:15:39 -05:00
David Heinemeier Hansson 716e118c81 Need the list for offline install? 2026-02-19 17:43:41 +01:00
David Heinemeier Hansson 9cf9cd1612 Use rc mirror and stable mirror fixed 2026-02-19 15:12:15 +01:00
David Heinemeier Hansson fba9fb3758 Use correct pacman conf 2026-02-19 12:44:56 +01:00
David Heinemeier Hansson 72b7a1f245 Simplify the options here 2026-02-18 18:58:59 +01:00
David Heinemeier Hansson 1f465cfeac rc just uses edge 2026-02-18 18:02:51 +01:00
David Heinemeier Hansson 6cd3702c27 Need bigger disk for testing 2026-02-05 16:45:53 +01:00
David Heinemeier Hansson bba89468f1 Need the rc conf too 2026-02-05 16:42:43 +01:00
David Heinemeier Hansson 5ba771dc1b Prepare for making RC ISOs 2026-02-04 18:17:10 +01:00
David Heinemeier Hansson 54991588e9 Make the mirror available during install 2026-01-07 20:13:20 +01:00
David Heinemeier Hansson 9d9a69e0c4 Set the mirror as we have it 2026-01-07 20:05:56 +01:00
David Heinemeier Hansson a202c81a0c Allow ISOs to be build against the edge mirror/package repository 2026-01-05 15:31:30 +01:00
David Heinemeier Hansson e5152cd7b2 Automatically add missing packages 2026-01-05 14:54:44 +01:00
Ryan Hughes e3cb89d712 Add missing steps for rclone setup 2025-12-16 15:12:41 -05:00
David Heinemeier Hansson 4188411b9b This might already have been removed upstream 2025-12-15 08:55:35 -08:00
Ryan Hughes 26805d9dd2 Skip wifi check 2025-11-26 01:33:03 -05:00
Ryan Hughes 1a886cb5de Update archiso 2025-11-26 01:29:16 -05:00
David Heinemeier Hansson a1ce189cbb Use stable pkg repository 2025-11-21 15:13:27 +01:00
David Heinemeier Hansson 4ded01b207 Explain cli flags 2025-11-11 08:55:52 +01:00
David Heinemeier Hansson 872c8fb03f Allow building the ISO from local source and replace dev build binstub with --dev 2025-11-11 08:47:04 +01:00
David Heinemeier Hansson 5c2d06c5fc Automate the rclone config 2025-11-10 14:01:25 +01:00
David Heinemeier Hansson cab0c5b50a Use stable mirror to build ISO 2025-11-10 10:14:41 +01:00
David Heinemeier Hansson 35036bdd62 Only use our own mirror 2025-11-10 10:12:58 +01:00
David Heinemeier Hansson 3afa6b63ff Update instructions 2025-11-09 09:30:47 +01:00
David Heinemeier Hansson 9e2d0ac204 Just focus release on the master iso 2025-10-28 08:40:48 +01:00
David Heinemeier Hansson c9f7b80d3d Output the SHAs 2025-10-28 08:38:48 +01:00
Ryan Hughes 09913880e6 Add omarchy-keyring and keys 2025-10-27 17:04:20 -04:00
Ryan Hughes aa75d85d14 Add prompt to boot an iso 2025-10-27 17:04:10 -04:00
Ryan Hughes ec1405625f Fix error display when failing during early archinstall 2025-10-27 11:15:53 -04:00
Ryan Hughes 82f854054e Merge pull request #52 from dakshesh14/fix/password_opensll
fix: iso setup failing when password starts with dash(-)
2025-10-27 11:11:35 -04:00
Ryan Hughes 27b332c64f Merge pull request #57 from omacom-io/revert-54-patch-1
Revert "Harden ingest of user-provided passphrase"
2025-10-27 01:56:26 -04:00
Ryan Hughes 9ad1706ce3 Revert "Harden ingest of user-provided passphrase" 2025-10-27 01:55:54 -04:00
Ryan Hughes 401446dac0 Merge pull request #54 from wolfgangw/patch-1
Harden ingest of user-provided passphrase
2025-10-25 16:35:07 -04:00
Wolfgang Woehl 9e7841ccd2 Harden ingest of user-provided passphrase 2025-10-20 16:55:27 +02:00
David Heinemeier Hansson b502d26326 Pass in the version instead for now 2025-10-19 09:35:43 +02:00
David Heinemeier Hansson e81016a476 Fix busted param 2025-10-19 09:34:13 +02:00
David Heinemeier Hansson 6fe6353185 Bump version
We should be pulling it dynamically from the repo!
2025-10-19 09:30:09 +02:00
dakshesh14 880d8c57af fix: iso setup failing when password starts with dash(-) 2025-10-19 11:01:38 +05:30
David Heinemeier Hansson b9e6462c9f Expand the keyboard list so it's not insane to diff when we need to fix things in it 2025-10-18 20:50:14 +02:00
Ryan Hughes 18f728a42e Add node package to install by default 2025-10-18 14:28:52 -04:00
David Heinemeier Hansson 18b7c4bcb6 Revise ISO download link and creation instructions
Updated download link and instructions for creating the ISO.
2025-10-18 11:54:16 +02:00
Ryan Hughes fd964ceaf5 Add loopback.cfg 2025-10-15 13:36:07 -04:00
Ryan Hughes 1fdccb2546 Update archiso 2025-10-15 13:00:35 -04:00
Ryan Hughes 220dbda602 Add omarchy-vm 2025-10-08 21:16:51 -04:00
Ryan Hughes 8f844655b7 Fix ownership issues 2025-10-08 20:42:06 -04:00
Ryan Hughes 59a17acf88 Reboot when signaled by installer 2025-10-08 20:41:29 -04:00
Ryan Hughes 7598e58d0b Add French (Switzerland) 2025-09-28 16:17:23 -04:00
Ryan Hughes 26daaaa625 Update keyboard options to be valid 2025-09-28 16:14:18 -04:00
Ryan Hughes 02a9d48312 Update profiledef 2025-09-28 15:42:21 -04:00
Ryan Hughes f2fb26ad7d Archiso update 2025-09-28 14:15:09 -04:00
Ryan Hughes c23e0e7b3d Config updates 2025-09-21 23:47:10 -04:00
Ryan Hughes 5b9bf620ff Use grub 2025-09-21 23:47:05 -04:00
Ryan Hughes 3e37f6d28a Fix hooks that were missing 2025-09-21 23:46:36 -04:00
Ryan Hughes 5adefedad2 Add ability to ssh into client + easier boot menu access 2025-09-21 23:46:18 -04:00
Ryan Hughes e50bad3672 Add alsa-firmware 2025-09-20 15:36:06 -04:00
Ryan Hughes bb8ba99edc Remove ruby mount 2025-09-17 16:48:47 -04:00
David Heinemeier Hansson a88b8a2e7a Versioned releases 2025-09-17 20:38:47 +02:00
David Heinemeier Hansson b5fbc6fc4e Remove precompiled Ruby for now 2025-09-17 14:20:44 +02:00
David Heinemeier Hansson 194dbbef33 If there's a sig 2025-09-15 21:12:16 +02:00
Ryan Hughes 0638855a5b Change ISO kernel to T2 patched for E2E support 2025-09-14 14:36:26 -04:00
Ryan Hughes 234b54c0de Change T2 upstream to the github mirror for now 2025-09-14 14:35:27 -04:00
Tim auf der Landwehr a80e9b3050 Fix typo in README.md (#37) 2025-09-14 10:38:14 +02:00
David Heinemeier Hansson 7a735fd7b6 Simplify README.md installation description 2025-09-14 10:37:58 +02:00
David Heinemeier Hansson a57aaec4b8 It'll just be straight offline ISOs 2025-09-13 21:33:04 +02:00
David Heinemeier Hansson 9d9bd79120 No longer needing URL 2025-09-13 21:32:44 +02:00
David Heinemeier Hansson 7d44602dc1 Fix the necessary chmods 2025-09-13 21:22:11 +02:00
David Heinemeier Hansson 2e0c4e55d6 Unnecessary packages for archinstall as we use it 2025-09-13 21:19:52 +02:00
David Heinemeier Hansson 5f66f47061 We don't need to show that cursor 2025-09-13 21:00:51 +02:00
David Heinemeier Hansson 3c82950d07 No need to repeat the logo 2025-09-13 21:00:22 +02:00
David Heinemeier Hansson 27c64f7a72 No longer relevant 2025-09-13 20:59:19 +02:00
David Heinemeier Hansson b7d610731e Prevents the flash of this installing when transitioning from archinstall to isntaller 2025-09-13 20:46:06 +02:00
David Heinemeier Hansson e8f53c52ee Spacing 2025-09-13 20:44:36 +02:00
David Heinemeier Hansson 5869d3e83d Not needed, we don't run boot directly 2025-09-13 20:44:33 +02:00
David Heinemeier Hansson 771cf68d0b Files might not be there 2025-09-13 20:44:23 +02:00
David Heinemeier Hansson 8a887cee3a We did also need this 2025-09-13 20:32:44 +02:00
David Heinemeier Hansson 4720d62095 Do need those exports for the helper 2025-09-13 20:25:07 +02:00
David Heinemeier Hansson 9e9cf2f576 Let's do it up front 2025-09-13 20:13:24 +02:00
David Heinemeier Hansson 7f5e5460f0 Better organization 2025-09-13 20:12:22 +02:00
David Heinemeier Hansson ebe7ab1f51 tzupdate may be available but without internet 2025-09-13 20:08:42 +02:00
David Heinemeier Hansson acc5e0b274 Need the export now that its in a function 2025-09-13 20:06:16 +02:00
David Heinemeier Hansson bfa6a95bcf Factor it all out a bit 2025-09-13 20:05:20 +02:00
David Heinemeier Hansson 56d5de017d Slim down to just what we need 2025-09-13 20:00:56 +02:00
David Heinemeier Hansson a5884b546f Revert the package setup for a second 2025-09-13 19:32:10 +02:00
David Heinemeier Hansson 89063e4fee Shorter 2025-09-13 19:12:12 +02:00
David Heinemeier Hansson d9d8dc50c6 No longer used 2025-09-13 19:10:38 +02:00
David Heinemeier Hansson c018159aa5 Slim down the build script 2025-09-13 19:08:28 +02:00
David Heinemeier Hansson 7f83f7488d We are not using tte up front any more 2025-09-13 18:48:15 +02:00
David Heinemeier Hansson 045db5b028 Inline the configurator 2025-09-13 18:39:45 +02:00
David Heinemeier Hansson cccdf1b235 Doing this double 2025-09-13 18:39:28 +02:00
David Heinemeier Hansson 628b46950d No longer used 2025-09-13 18:39:22 +02:00
David Heinemeier Hansson 2427a177f5 Yank out the online builder option
Offline is the way
2025-09-13 18:23:31 +02:00
David Heinemeier Hansson 6165c8935b No magic side effects 2025-09-13 17:24:17 +02:00
David Heinemeier Hansson 56e2339432 Explained by conditional 2025-09-13 17:24:06 +02:00
David Heinemeier Hansson 87674f471e This has already been set for the overall script 2025-09-13 17:22:30 +02:00
David Heinemeier Hansson 8bb9193c02 Merge branch 'offline-iso' 2025-09-13 17:18:14 +02:00
David Heinemeier Hansson d9e17d4e50 Work with the big refactoring 2025-09-13 17:16:37 +02:00
David Heinemeier Hansson 8c92fdd0e0 No need for nesting 2025-09-13 16:54:45 +02:00
David Heinemeier Hansson 62c47b06f4 We have built it now, so who cares 2025-09-13 16:54:34 +02:00
David Heinemeier Hansson 0d79d27e02 Didnt need gum to build the iso itself 2025-09-13 16:42:26 +02:00
36 changed files with 1528 additions and 312 deletions

No files matched your search

+1
View File
@@ -1 +1,2 @@
release/**
vm-saves/**
+4 -6
View File
@@ -1,21 +1,19 @@
# Omarchy ISO
The Omarchy ISO streamlines [the installation of Omarchy](https://learn.omacom.io/2/the-omarchy-manual/50/getting-started). It includes the [Omarchy Configurator](https://github.com/omacom-io/omarchy-configurator) as a front-end to archinstall and automatically launches the [Omarchy Installer](https://github.com/basecamp/omarchy) after base arch has been setup.
The Omarchy ISO streamlines [the installation of Omarchy](https://learn.omacom.io/2/the-omarchy-manual/50/getting-started). It includes the Omarchy Configurator as a front-end to archinstall and automatically launches the [Omarchy Installer](https://github.com/basecamp/omarchy) after base arch has been setup.
## Downloading the latest ISO
[Download Omarchy Online ISO](https://iso.omarchy.org/omarchy-online.iso) (1.4GB)
See the ISO link on [omarchy.org](https://omarchy.org).
## Creating the ISO
Run `./bin/omarchy-iso-make` and the output goes into `./release`.
Run `./bin/omarchy-iso-make` and the output goes into `./release`. You can build from your local $OMARCHY_PATH for testing by using `--local-source` or from a checkout of the dev branch (instead of master) by using `--dev`.
### Environment Variables
You can customize the repositories used during the build process by passing in variables:
- `OMARCHY_CONFIGURATOR_REPO` - GitHub repository for the configurator (default: `omacom-io/omarchy-configurator`)
- `OMARCHY_CONFIGURATOR_REF` - Git ref (branch/tag) for the configurator (default: `master`)
- `OMARCHY_INSTALLER_REPO` - GitHub repository for the installer (default: `basecamp/omarchy`)
- `OMARCHY_INSTALLER_REF` - Git ref (branch/tag) for the installer (default: `master`)
@@ -38,4 +36,4 @@ Run `./bin/omarchy-iso-upload [release/omarchy.iso]`. This requires you've confi
## Full release of the ISO
Run `./bin/omarchy-iso-make` to create, test, sign, and upload the ISO in one flow.
Run `./bin/omarchy-iso-release VERSION` to create, test, sign, and upload the ISO in one flow. Add `--rc` to release an RC build instead.
+1 -1
Submodule archiso updated: 69047bdc03...424e78130d.
+18 -8
View File
@@ -2,18 +2,27 @@
set -e
ISO="$1"
REUSE="$2"
if [ $# -eq 0 ]; then
ISO=$(ls -t release/*.iso 2>/dev/null | gum choose --header "Select ISO to boot")
if gum confirm --default=false "Reuse existing disk?"; then
REUSE="reuse"
fi
fi
if [ -z "$ISO" ]; then
echo "Usage: omarchy-iso-boot [release/omarchy.iso] [reuse]"
echo " SSH available at: ssh -p 2222 root@localhost (after installing openssh)"
exit 1
fi
if ! pacman -Q qemu-full >/dev/null || ! pacman -Q edk2-ovmf >/dev/null; then
sudo pacman -S --noconfirm --needed --quiet qemu-full edk2-ovmf
fi
omarchy-pkg-add qemu-full edk2-ovmf
DISK="/tmp/omarchy-iso-boot.qcow2"
if [[ ! -f $DISK || $2 != "reuse" ]]; then
qemu-img create -f qcow2 "$DISK" 20G
if [[ ! -f $DISK || $REUSE != "reuse" ]]; then
qemu-img create -f qcow2 "$DISK" 40G
cp /usr/share/edk2/x64/OVMF_VARS.4m.fd /tmp/OVMF_VARS.4m.fd
fi
@@ -26,10 +35,11 @@ qemu-system-x86_64 \
-drive if=pflash,format=raw,file=/tmp/OVMF_VARS.4m.fd \
-drive file="$DISK",format=qcow2,if=none,id=drive0 \
-device virtio-blk-pci,drive=drive0,bootindex=1 \
-drive file="$1",media=cdrom,if=none,format=raw,id=cdrom0 \
-drive file="$ISO",media=cdrom,if=none,format=raw,id=cdrom0 \
-device ide-cd,drive=cdrom0,bootindex=2 \
-device virtio-vga-gl \
-display gtk,gl=on \
-usb -device usb-tablet \
-netdev user,id=net0 \
-device virtio-net-pci,netdev=net0
-netdev user,id=net0,hostfwd=tcp::2222-:22 \
-device virtio-net-pci,netdev=net0 \
-boot menu=on
+30 -21
View File
@@ -4,18 +4,9 @@
set -e
# Parse command line arguments
BUILD_MODE="offline"
NO_CACHE=""
while [[ $# -gt 0 ]]; do
case $1 in
--online)
BUILD_MODE="online"
shift
;;
--offline)
BUILD_MODE="offline"
shift
;;
--no-cache)
NO_CACHE=1
shift
@@ -24,14 +15,32 @@ while [[ $# -gt 0 ]]; do
NO_BOOT_OFFER=1
shift
;;
--local-source)
LOCAL_SOURCE=1
OMARCHY_MIRROR=edge
shift
;;
--dev)
OMARCHY_INSTALLER_REF=dev
OMARCHY_MIRROR=edge
shift
;;
--rc)
OMARCHY_MIRROR=rc
OMARCHY_INSTALLER_REF=rc
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [--online|--offline] [--no-cache] [--no-boot-offer]"
echo "Usage: $0 [--no-cache] [--no-boot-offer] [--local-source] [--dev] [--rc]"
exit 1
;;
esac
done
# Clear out old packages
sudo rm -rf /var/cache/pacman/pkg/*
# Ensure we have the submodule checked out
git submodule update --init --recursive --jobs=8
@@ -41,22 +50,18 @@ BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
BUILD_RELEASE_PATH="$BUILD_ROOT/release"
mkdir -p "$BUILD_RELEASE_PATH"
OMARCHY_CONFIGURATOR_REPO="${OMARCHY_CONFIGURATOR_REPO:-omacom-io/omarchy-configurator}"
OMARCHY_CONFIGURATOR_REF="${OMARCHY_CONFIGURATOR_REF:-master}"
OMARCHY_INSTALLER_REPO="${OMARCHY_INSTALLER_REPO:-basecamp/omarchy}"
OMARCHY_INSTALLER_REF="${OMARCHY_INSTALLER_REF:-master}"
OMARCHY_INSTALLER_URL="${OMARCHY_INSTALLER_URL:-https://omarchy.org/install}"
OMARCHY_MIRROR="${OMARCHY_MIRROR:-stable}"
DOCKER_ARGS=(
--rm
--privileged
-e "OMARCHY_CONFIGURATOR_REPO=$OMARCHY_CONFIGURATOR_REPO"
-e "OMARCHY_CONFIGURATOR_REF=$OMARCHY_CONFIGURATOR_REF"
-e "OMARCHY_INSTALLER_REPO=$OMARCHY_INSTALLER_REPO"
-e "OMARCHY_INSTALLER_REF=$OMARCHY_INSTALLER_REF"
-e "OMARCHY_INSTALLER_URL=$OMARCHY_INSTALLER_URL"
-e "OMARCHY_BUILD_MODE=$BUILD_MODE"
-e "OMARCHY_MIRROR=$OMARCHY_MIRROR"
-e "HOST_UID=$(id -u)"
-e "HOST_GID=$(id -g)"
-v "$BUILD_RELEASE_PATH/:/out/"
-v "$BUILD_ROOT/$BUILD_SCRIPT:/$BUILD_SCRIPT:ro"
-v "$BUILD_ROOT/archiso:/archiso:ro"
@@ -64,14 +69,18 @@ DOCKER_ARGS=(
-v "$BUILD_ROOT/configs:/configs:ro"
)
# Use local source of Omarchy from $OMARCHY_PATH instead of git checkout
if [[ -n "${LOCAL_SOURCE-}" ]]; then
DOCKER_ARGS+=(-v "$OMARCHY_PATH:/omarchy:ro")
fi
# Use local pacman cache if you already have one on host to speed up repeat runs
if [ -d "/var/cache/pacman/pkg" ]; then
DOCKER_ARGS+=(-v "/var/cache/pacman/pkg:/var/cache/pacman/pkg")
fi
# Mount the build cache directory where packages are downloaded for the offline repo
# Only applicable for offline builds and when --no-cache is not specified
if [[ "$BUILD_MODE" == "offline" && -z "$NO_CACHE" ]]; then
# Mount the build cache directory where packages are downloaded
if [[ -z "$NO_CACHE" ]]; then
# using a dated dir on the host to refresh daily if building multiple times
BUILD_DATE=$(date +%Y-%m-%d)
OFFLINE_REPO_BUILD_CACHE_DIR="$HOME/.cache/omarchy/iso_${BUILD_DATE}/airootfs/var/cache/omarchy"
-5
View File
@@ -1,5 +0,0 @@
#!/bin/bash
OMARCHY_INSTALLER_REF=dev \
OMARCHY_INSTALL_URL=https://omarchy.org/install-dev \
omarchy-iso-make
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
omarchy-pkg-add rclone
mkdir -p ~/.config/rclone
access_key=$(op read "op://Shared/Cloudflare Buckets/iso.omarchy.org/access_key_id" --account Omarchy)
secret_access_key=$(op read "op://Shared/Cloudflare Buckets/iso.omarchy.org/secret_access_key" --account Omarchy)
endpoint=$(op read "op://Shared/Cloudflare Buckets/iso.omarchy.org/endpoint" --account Omarchy)
cat > ~/.config/rclone/rclone.conf << EOF
[Omarchy]
type = s3
provider = Cloudflare
access_key_id = $access_key
secret_access_key = $secret_access_key
endpoint = $endpoint
EOF
+51 -19
View File
@@ -1,30 +1,62 @@
#!/bin/bash
MAKE_ARGS=()
INSTALLER_REF=master
RELEASE_SUFFIX=""
while [[ $# -gt 0 ]]; do
case $1 in
--no-make)
MAKE_ARGS+=("$1")
shift
;;
--rc)
MAKE_ARGS+=("$1")
INSTALLER_REF=rc
RELEASE_SUFFIX="-rc"
shift
;;
-*)
echo "Unknown option: $1"
echo "Usage: omarchy-iso-release [--no-make] [--rc] [version]"
exit 1
;;
*)
if [[ -n "${BUILD_VERSION-}" ]]; then
echo "Usage: omarchy-iso-release [--no-make] [--rc] [version]"
exit 1
fi
BUILD_VERSION="$1"
shift
;;
esac
done
if [[ -z "${BUILD_VERSION-}" ]]; then
echo "Usage: omarchy-iso-release [--no-make] [--rc] [version]"
exit 1
fi
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
BUILD_RELEASE_PATH="$BUILD_ROOT/release"
# Make ISOs
if [[ $1 != "--no-make" ]]; then
echo -e "\e[32mMaking master ISO\e[0m"
OMARCHY_INSTALLER_REF=master omarchy-iso-make --no-boot-offer
echo -e "\e[32m\nMaking dev ISO\e[0m"
OMARCHY_INSTALLER_REF=dev OMARCHY_INSTALL_URL=https://omarchy.org/install-dev omarchy-iso-make --no-boot-offer
if [[ ! " ${MAKE_ARGS[*]} " =~ " --no-make " ]]; then
echo -e "\e[32mMaking $INSTALLER_REF ISO\e[0m"
omarchy-iso-make --no-cache --no-boot-offer "${MAKE_ARGS[@]}"
else
echo -e "\e[31mSkipping remaking ISOs\e[0m"
fi
# Sign and upload master ISO
latest_master_iso=$(\ls -t "$BUILD_RELEASE_PATH"/*x86_64-master.iso | head -n1)
release_master_iso="$BUILD_RELEASE_PATH/omarchy-online.iso"
cp "$latest_master_iso" "$release_master_iso"
echo -e "\e[32mSigning master ISO\e[0m"
omarchy-iso-sign "$release_master_iso"
omarchy-iso-upload "$release_master_iso"
# Sign and upload ISO
latest_iso=$(\ls -t "$BUILD_RELEASE_PATH"/*x86_64-"$INSTALLER_REF".iso | head -n1)
release_iso="$BUILD_RELEASE_PATH/omarchy-$BUILD_VERSION$RELEASE_SUFFIX.iso"
cp "$latest_iso" "$release_iso"
# Sign and upload dev ISO
latest_dev_iso=$(\ls -t "$BUILD_RELEASE_PATH"/*x86_64-dev.iso | head -n1)
release_dev_iso="$BUILD_RELEASE_PATH/omarchy-online-dev.iso"
cp "$latest_dev_iso" "$release_dev_iso"
echo -e "\e[32mSigning dev ISO\e[0m"
omarchy-iso-sign "$release_dev_iso"
omarchy-iso-upload "$release_dev_iso"
echo -e "\e[32mSigning $INSTALLER_REF ISO\e[0m"
omarchy-iso-sign "$release_iso"
iso_sha=$(sha256sum "$release_iso")
echo -e "\e[32mSHA256 for $INSTALLER_REF ISO: $iso_sha\e[0m"
omarchy-iso-upload "$release_iso"
+2 -2
View File
@@ -6,8 +6,8 @@ if [ $# -eq 0 ]; then
fi
if ! pacman -Q gnupg >/dev/null; then
sudo pacman -s --noconfirm --needed --quiet gnupg
echo "you'll need to generate a new key with: gpg --full-generate-key"
sudo pacman -S --noconfirm --needed --quiet gnupg
echo "You'll need to import key with: gpg --import path/to/signing-key.asc"
fi
gnupg_user_key=$(gpg --list-secret-keys --keyid-format=long | awk '/^[[:space:]]/{print $1; exit}')
+5 -2
View File
@@ -6,9 +6,12 @@ if [ $# -eq 0 ]; then
fi
if [[ ! -f ~/.config/rclone/rclone.conf ]]; then
echo "You must first configure rclone with the R2 credentials: rclone config"
echo "You must first configure rclone with the R2 credentials: omarchy-iso-rclone-config"
exit 1
fi
rclone copy $1 Omarchy:omarchy/ -P
rclone copy $1.sig Omarchy:omarchy/ -P
if [[ -f $1.sig ]]; then
rclone copy $1.sig Omarchy:omarchy/ -P
fi
Executable
+111
View File
@@ -0,0 +1,111 @@
#!/bin/bash
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VM_DIR="$(dirname "$SCRIPT_DIR")/vm-saves"
TMP_DISK="/tmp/omarchy-iso-boot.qcow2"
TMP_OVMF="/tmp/OVMF_VARS.4m.fd"
mkdir -p "$VM_DIR"
save_vm() {
local name="$1"
if [[ -z "$name" ]]; then
name=$(gum input --placeholder "Enter VM snapshot name")
[[ -z "$name" ]] && exit 1
fi
if [[ ! -f "$TMP_DISK" || ! -f "$TMP_OVMF" ]]; then
echo "Error: No active VM found in /tmp"
echo "Boot a VM first with: omarchy-iso-boot [iso]"
exit 1
fi
local vm_path="$VM_DIR/$name"
if [[ -d "$vm_path" ]]; then
if ! gum confirm "VM '$name' exists. Overwrite?"; then
exit 0
fi
fi
mkdir -p "$vm_path"
echo "Saving VM snapshot '$name'..."
cp "$TMP_DISK" "$vm_path/omarchy-iso-boot.qcow2"
cp "$TMP_OVMF" "$vm_path/OVMF_VARS.4m.fd"
gum style --foreground 212 "✓ Saved to $vm_path"
}
list_vms() {
if [[ ! -d "$VM_DIR" ]] || [[ -z "$(ls -A "$VM_DIR")" ]]; then
echo "No VM snapshots found"
return 1
fi
echo "Available VM snapshots:"
for vm in "$VM_DIR"/*; do
[[ -d "$vm" ]] && echo " • $(basename "$vm")"
done
}
boot_vm() {
local name="$1"
if [[ -z "$(ls -A "$VM_DIR" 2>/dev/null)" ]]; then
echo "No VM snapshots available"
exit 1
fi
if [[ -z "$name" ]]; then
name=$(ls -1 "$VM_DIR" | gum choose --header "Select VM to boot:")
[[ -z "$name" ]] && exit 0
fi
local vm_path="$VM_DIR/$name"
if [[ ! -d "$vm_path" ]]; then
echo "Error: VM '$name' not found"
list_vms
exit 1
fi
if [[ -f "$TMP_DISK" ]] && ! gum confirm "Override existing /tmp VM?"; then
exit 0
fi
echo "Copying VM '$name' to /tmp..."
cp "$vm_path/omarchy-iso-boot.qcow2" "$TMP_DISK"
cp "$vm_path/OVMF_VARS.4m.fd" "$TMP_OVMF"
gum style --foreground 212 "✓ VM ready. Booting..."
exec omarchy-iso-boot /dev/null reuse
}
case "${1:-}" in
save)
save_vm "$2"
;;
boot)
boot_vm "$2"
;;
list)
list_vms
;;
*)
gum style --border rounded --padding "0 1" --border-foreground 212 \
"$(gum style --bold 'omarchy-vm') - VM snapshot manager" \
"" \
"$(gum style --foreground 245 'Commands:')" \
" save [name] Save current VM from /tmp" \
" boot [name] Boot saved VM (interactive if no name)" \
" list List available VMs" \
"" \
"$(gum style --foreground 245 'Current VMs:')"
list_vms 2>/dev/null || echo " None"
;;
esac
+14
View File
@@ -0,0 +1,14 @@
alsa-firmware
amd-ucode
base
base-devel
efibootmgr
intel-ucode
linux-firmware
linux
limine
omarchy-keyring
openssh
pipewire
snapper
sof-firmware
+64 -118
View File
@@ -2,98 +2,43 @@
set -e
# Build mode: offline (default) or online │ │
OMARCHY_BUILD_MODE="${OMARCHY_BUILD_MODE:-offline}"
# Note that these are packages installed to the Arch container
# used to build the ISO.
# Note that these are packages installed to the Arch container used to build the ISO.
pacman-key --init
pacman --noconfirm -Sy archlinux-keyring
pacman --noconfirm -Sy archiso git python-pip sudo base-devel jq
pacman --noconfirm -Sy archiso git sudo base-devel jq grub
# Install omarchy-keyring for package verification during build
# The [omarchy] repo is defined in /configs/pacman-online.conf with SigLevel = Optional TrustAll
pacman --config /configs/pacman-online-${OMARCHY_MIRROR}.conf --noconfirm -Sy omarchy-keyring
pacman-key --populate omarchy
# Setup build locations
build_cache_dir="/var/cache"
offline_mirror_dir="$build_cache_dir/airootfs/var/cache/omarchy/mirror/offline"
offline_ruby_dir="$build_cache_dir/airootfs/var/cache/omarchy/ruby"
# We need to fiddle with pip settings
# in order to install to the correct place
# as well as ignore some errors to make this less verbose
export PIP_ROOT="$build_cache_dir/airootfs/"
export PIP_ROOT_USER_ACTION="ignore"
export PIP_NO_WARN_SCRIPT_LOCATION=1
export PIP_BREAK_SYSTEM_PACKAGES=1
# These packages will be installed **into** the ISO, and
# won't be available to either archinstall or omarchy installer.
python_packages=(
terminaltexteffects
)
arch_packages=(
git
gum
jq
openssl
plymouth
tzupdate # This is technically an AUR package
)
prepare_offline_mirror() {
# Certain packages in omarchy.packages are AUR packages.
# These needs to be pre-built and placed in https://pkgs.omarchy.org/$arch
echo "Reading and combining packages from all package files..."
# Combine all packages into one array
# Start with base ISO packages (including our arch_packages already appended)
all_packages=($(cat "$build_cache_dir/packages.x86_64"))
# Add packages from the omarchy installer's unified package list
all_packages+=($(grep -v '^#' "$build_cache_dir/airootfs/root/omarchy/install/omarchy-base.packages" | grep -v '^$'))
all_packages+=($(grep -v '^#' "$build_cache_dir/airootfs/root/omarchy/install/omarchy-other.packages" | grep -v '^$'))
# Add archinstall needed packages
all_packages+=($(grep -v '^#' /builder/packages/archinstall.packages | grep -v '^$'))
if [ ${#all_packages[@]} -gt 0 ]; then
mkdir -p /tmp/offlinedb
# Download all the packages to the offline mirror inside the ISO
echo "Downloading all packages (including AUR) to offline mirror: ${all_packages[@]}"
pacman --config /configs/pacman-online.conf \
--noconfirm -Syw "${all_packages[@]}" \
--cachedir $offline_mirror_dir/ \
--dbpath /tmp/offlinedb
repo-add --new "$offline_mirror_dir/offline.db.tar.gz" "$offline_mirror_dir/"*.pkg.tar.zst
rm "$build_cache_dir/airootfs/etc/pacman.d/hooks/uncomment-mirrors.hook"
fi
}
disable_reflector() {
# Avoid using reflector for mirror identification as we are relying on the global CDN
rm "$build_cache_dir/airootfs/etc/systemd/system/multi-user.target.wants/reflector.service"
rm -rf "$build_cache_dir/airootfs/etc/systemd/system/reflector.service.d"
rm -rf "$build_cache_dir/airootfs/etc/xdg/reflector"
}
#######################
# Build process start
#######################
mkdir -p $build_cache_dir/
mkdir -p $offline_mirror_dir/
mkdir -p $offline_ruby_dir/
# We base our ISO on the official arch ISO (releng) config
cp -r /archiso/configs/releng/* $build_cache_dir/
rm "$build_cache_dir/airootfs/etc/motd"
disable_reflector
# Avoid using reflector for mirror identification as we are relying on the global CDN
rm -rf "$build_cache_dir/airootfs/etc/systemd/system/multi-user.target.wants/reflector.service"
rm -rf "$build_cache_dir/airootfs/etc/systemd/system/reflector.service.d"
rm -rf "$build_cache_dir/airootfs/etc/xdg/reflector"
# Bring in our configs
cp -r /configs/* $build_cache_dir/
# Clone Omarchy itself
git clone -b $OMARCHY_INSTALLER_REF https://github.com/$OMARCHY_INSTALLER_REPO.git "$build_cache_dir/airootfs/root/omarchy"
# Persist OMARCHY_MIRROR so it's available at install time
echo "$OMARCHY_MIRROR" > "$build_cache_dir/airootfs/root/omarchy_mirror"
# Setup Omarchy itself
if [[ -d /omarchy ]]; then
cp -rp /omarchy "$build_cache_dir/airootfs/root/omarchy"
else
git clone -b $OMARCHY_INSTALLER_REF https://github.com/$OMARCHY_INSTALLER_REPO.git "$build_cache_dir/airootfs/root/omarchy"
fi
# Make log uploader available in the ISO too
mkdir -p "$build_cache_dir/airootfs/usr/local/bin/"
@@ -103,55 +48,56 @@ cp "$build_cache_dir/airootfs/root/omarchy/bin/omarchy-upload-log" "$build_cache
mkdir -p "$build_cache_dir/airootfs/usr/share/plymouth/themes/omarchy"
cp -r "$build_cache_dir/airootfs/root/omarchy/default/plymouth/"* "$build_cache_dir/airootfs/usr/share/plymouth/themes/omarchy/"
# Download the configurator
mkdir -p "$build_cache_dir/airootfs/root"
curl -fsSL -o "$build_cache_dir/airootfs/root/configurator" \
"https://raw.githubusercontent.com/$OMARCHY_CONFIGURATOR_REPO/$OMARCHY_CONFIGURATOR_REF/configurator"
# Download and verify Node.js binary for offline installation
NODE_DIST_URL="https://nodejs.org/dist/latest"
if [ "$OMARCHY_BUILD_MODE" = "online" ]; then
echo "$OMARCHY_INSTALLER_REPO" >$build_cache_dir/airootfs/root/omarchy_installer_repo.txt
echo "$OMARCHY_INSTALLER_REF" >$build_cache_dir/airootfs/root/omarchy_installer_ref.txt
echo "$OMARCHY_INSTALLER_URL" >$build_cache_dir/airootfs/root/omarchy_installer_url.txt
echo "online" >$build_cache_dir/airootfs/root/omarchy_install_mode.txt
else
echo "offline" >$build_cache_dir/airootfs/root/omarchy_install_mode.txt
fi
# Get checksums and parse filename and SHA
NODE_SHASUMS=$(curl -fsSL "$NODE_DIST_URL/SHASUMS256.txt")
NODE_FILENAME=$(echo "$NODE_SHASUMS" | grep "linux-x64.tar.gz" | awk '{print $2}')
NODE_SHA=$(echo "$NODE_SHASUMS" | grep "linux-x64.tar.gz" | awk '{print $1}')
# Download the tarball
curl -fsSL "$NODE_DIST_URL/$NODE_FILENAME" -o "/tmp/$NODE_FILENAME"
# Verify SHA256 checksum
echo "$NODE_SHA /tmp/$NODE_FILENAME" | sha256sum -c - || {
echo "ERROR: Node.js checksum verification failed!"
exit 1
}
# Copy to ISO
mkdir -p "$build_cache_dir/airootfs/opt/packages/"
cp "/tmp/$NODE_FILENAME" "$build_cache_dir/airootfs/opt/packages/"
# Add our additional packages to packages.x86_64
arch_packages=(linux-t2 git gum jq openssl plymouth tzupdate omarchy-keyring)
printf '%s\n' "${arch_packages[@]}" >>"$build_cache_dir/packages.x86_64"
if [ "$OMARCHY_BUILD_MODE" = "offline" ]; then
prepare_offline_mirror
# Build list of all the packages needed for the offline mirror
all_packages=($(cat "$build_cache_dir/packages.x86_64"))
all_packages+=($(grep -v '^#' "$build_cache_dir/airootfs/root/omarchy/install/omarchy-base.packages" | grep -v '^$'))
all_packages+=($(grep -v '^#' "$build_cache_dir/airootfs/root/omarchy/install/omarchy-other.packages" | grep -v '^$'))
all_packages+=($(grep -v '^#' /builder/archinstall.packages | grep -v '^$'))
# Download Ruby tarball if not already cached
ruby_tarball="ruby-3.4.5-rails-8.0.2.1-x86_64.tar.gz"
if [ ! -f "$offline_ruby_dir/$ruby_tarball" ]; then
echo "Downloading Ruby tarball..."
curl -fsSL -o "$offline_ruby_dir/$ruby_tarball" \
"https://pkgs.omarchy.org/ruby/$ruby_tarball"
else
echo "Ruby tarball already cached, skipping download"
fi
# Download all the packages to the offline mirror inside the ISO
mkdir -p /tmp/offlinedb
pacman --config /configs/pacman-online-${OMARCHY_MIRROR}.conf --noconfirm -Syw "${all_packages[@]}" --cachedir $offline_mirror_dir/ --dbpath /tmp/offlinedb
repo-add --new "$offline_mirror_dir/offline.db.tar.gz" "$offline_mirror_dir/"*.pkg.tar.zst
# Create a symlink to the offline mirror instead of duplicating it.
# mkarchiso needs packages at /var/cache/omarchy/mirror/offline in the container,
# but they're actually in $build_cache_dir/airootfs/var/cache/omarchy/mirror/offline
mkdir -p /var/cache/omarchy/mirror
ln -s "$offline_mirror_dir" "/var/cache/omarchy/mirror/offline"
fi
# Create a symlink to the offline mirror instead of duplicating it.
# mkarchiso needs packages at /var/cache/omarchy/mirror/offline in the container,
# but they're actually in $build_cache_dir/airootfs/var/cache/omarchy/mirror/offline
mkdir -p /var/cache/omarchy/mirror
ln -s "$offline_mirror_dir" "/var/cache/omarchy/mirror/offline"
# Install Python packages for the installer into the ISO
# file system.
pip install "${python_packages[@]}"
if [ "$OMARCHY_BUILD_MODE" = "online" ]; then
# Copy the online version so we use it for build and ISO boot
cp $build_cache_dir/pacman-online.conf $build_cache_dir/pacman.conf
fi
# Copy the pacman.conf to the ISO's /etc directory so the live environment uses our
# same config when booted
cp $build_cache_dir/pacman.conf "$build_cache_dir/airootfs/etc/pacman.conf"
# Copy the offline pacman.conf to the ISO's /etc directory so the live environment uses our
# same config when booted.
cp $build_cache_dir/pacman-offline.conf "$build_cache_dir/airootfs/etc/pacman.conf"
# Finally, we assemble the entire ISO
mkarchiso -v -w "$build_cache_dir/work/" -o "/out/" "$build_cache_dir/"
# Fix ownership of output files to match host user
if [ -n "$HOST_UID" ] && [ -n "$HOST_GID" ]; then
chown -R "$HOST_UID:$HOST_GID" /out/
fi
-40
View File
@@ -1,40 +0,0 @@
nano
vim
openssh
htop
wireless_tools
wpa_supplicant
smartmontools
xdg-utils
dunst
kitty
dolphin
wofi
qt5-wayland
qt6-wayland
polkit-kde-agent
grim
xorg-server
xorg-xinit
mesa
xf86-video-amdgpu
xf86-video-ati
xf86-video-nouveau
libva-mesa-driver
libva-intel-driver
vulkan-radeon
vulkan-intel
vulkan-nouveau
sddm
efibootmgr
intel-media-driver
amd-ucode
intel-ucode
sof-firmware
base
base-devel
linux-firmware
linux
limine
pipewire
snapper
@@ -1,2 +1,2 @@
# Configuration for archiso with Plymouth
HOOKS=(base udev plymouth modconf archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs archiso_kms block filesystems keyboard)
HOOKS=(base udev microcode modconf kms memdisk archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs plymouth block filesystems keyboard)
@@ -0,0 +1,9 @@
# mkinitcpio preset file for the 'linux' package on archiso
PRESETS=('archiso')
ALL_kver='/boot/vmlinuz-linux-t2'
archiso_config='/etc/mkinitcpio.conf.d/archiso.conf'
archiso_image="/boot/initramfs-linux-t2.img"
@@ -0,0 +1,14 @@
# Fix Panther Lake audio: blacklist SOF modules that conflict with HDA drivers
# (prevents boot issues on Dell XPS 2026 and similar Panther Lake systems)
blacklist snd_sof_pci_intel_ptl
blacklist snd_sof_pci_intel_lnl
blacklist snd_sof_pci_intel_mtl
blacklist snd_sof_intel_hda_generic
blacklist snd_sof_intel_hda_common
blacklist snd_sof_intel_hda
blacklist snd_sof_pci
blacklist snd_sof
blacklist soundwire_intel
blacklist snd_soc_cs35l56_sdw
blacklist snd_soc_cs35l56
blacklist snd_soc_skl_hda_dsp
+68 -64
View File
@@ -1,6 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail
use_omarchy_helpers() {
export OMARCHY_PATH="/root/omarchy"
export OMARCHY_INSTALL="/root/omarchy/install"
export OMARCHY_INSTALL_LOG_FILE="/var/log/omarchy-install.log"
export OMARCHY_MIRROR="$(cat /root/omarchy_mirror)"
source /root/omarchy/install/helpers/all.sh
}
run_configurator() {
set_tokyo_night_colors
./configurator
export OMARCHY_USER="$(jq -r '.users[0].username' user_credentials.json)"
}
install_arch() {
clear_logo
gum style --foreground 3 --padding "1 0 0 $PADDING_LEFT" "Installing..."
echo
touch /var/log/omarchy-install.log
start_log_output
# Set CURRENT_SCRIPT for the trap to display better when nothing is returned for some reason
CURRENT_SCRIPT="install_base_system"
install_base_system > >(sed -u 's/\x1b\[[0-9;]*[a-zA-Z]//g' >>/var/log/omarchy-install.log) 2>&1
unset CURRENT_SCRIPT
stop_log_output
}
install_omarchy() {
chroot_bash -lc "sudo pacman -S --noconfirm --needed gum" >/dev/null
chroot_bash -lc "source /home/$OMARCHY_USER/.local/share/omarchy/install.sh || bash"
# Reboot if requested by installer
if [[ -f /mnt/var/tmp/omarchy-install-completed ]]; then
reboot
fi
}
# Set Tokyo Night color scheme for the terminal
set_tokyo_night_colors() {
if [[ $(tty) == "/dev/tty"* ]]; then
@@ -28,26 +68,11 @@ set_tokyo_night_colors() {
fi
}
run_configurator() {
set -euo pipefail
# Check if this is an online or offline build
if [ "${OMARCHY_INSTALL_MODE:-offline}" = "online" ]; then
./configurator
else
NETWORK_NOT_NEEDED=true ./configurator
fi
# Get username from installer config for reliable error recovery
export OMARCHY_USER="$(jq -r '.users[0].username' user_credentials.json)"
}
install_base_system() {
set -euo pipefail
# Initialize and populate the keyring
pacman-key --init
pacman-key --populate archlinux
pacman-key --populate omarchy
# Sync the offline database so pacman can find packages
pacman -Sy --noconfirm
@@ -55,6 +80,19 @@ install_base_system() {
# Ensure that no mounts exist from past install attempts
findmnt -R /mnt >/dev/null && umount -R /mnt
# Workarounds for archinstall 4.2 regressions under Python 3.14:
# 1. sync_log_to_install_medium: `self.target / absolute_logfile` drops
# self.target because the RHS is absolute, so Path.copy() raises EINVAL
# (source == target).
# 2. _add_limine_bootloader: `Path.copy(efi_dir_path)` raises IsADirectoryError
# because 3.14's Path.copy treats target as a literal path, not a directory
# (shutil.copy used to auto-append the source filename).
sed -i \
-e 's|logfile_target = self\.target / absolute_logfile$|logfile_target = self.target / absolute_logfile.relative_to("/")|' \
-e 's|(limine_path / file)\.copy(efi_dir_path)|(limine_path / file).copy(efi_dir_path / file)|' \
-e "s|(limine_path / 'limine-bios.sys')\.copy(boot_limine_path)|(limine_path / 'limine-bios.sys').copy(boot_limine_path / 'limine-bios.sys')|" \
/usr/lib/python3.14/site-packages/archinstall/lib/installer.py
# Install using files generated by the ./configurator
# Skip NTP and WKD sync since we're offline (keyring is pre-populated in ISO)
archinstall \
@@ -62,7 +100,8 @@ install_base_system() {
--creds user_credentials.json \
--silent \
--skip-ntp \
--skip-wkd
--skip-wkd \
--skip-wifi-check
# After archinstall sets up the base system but before our installer runs,
# we need to ensure the offline pacman.conf is in place
@@ -72,9 +111,9 @@ install_base_system() {
mkdir -p /mnt/var/cache/omarchy/mirror/offline
mount --bind /var/cache/omarchy/mirror/offline /mnt/var/cache/omarchy/mirror/offline
# Mount the ruby directory so it's accessible in the chroot
mkdir -p /mnt/var/cache/omarchy/ruby
mount --bind /var/cache/omarchy/ruby /mnt/var/cache/omarchy/ruby
# Mount the packages dir so it's accessible in the chroot
mkdir -p /mnt/opt/packages
mount --bind /opt/packages /mnt/opt/packages
# No need to ask for sudo during the installation (omarchy itself responsible for removing after install)
mkdir -p /mnt/etc/sudoers.d
@@ -90,65 +129,30 @@ EOF
cp -r /root/omarchy /mnt/home/$OMARCHY_USER/.local/share/
chown -R 1000:1000 /mnt/home/$OMARCHY_USER/.local/
# Ensure all scripts in bin directories are executable
# Ensure all necessary scripts are executable
find /mnt/home/$OMARCHY_USER/.local/share/omarchy -type f -path "*/bin/*" -exec chmod +x {} \;
# Ensure boot.sh is executable
chmod +x /mnt/home/$OMARCHY_USER/.local/share/omarchy/boot.sh 2>/dev/null || true
chmod +x /mnt/home/$OMARCHY_USER/.local/share/omarchy/default/waybar/indicators/screen-recording.sh 2>/dev/null || true
chmod +x /mnt/home/$OMARCHY_USER/.local/share/omarchy/default/waybar/indicators/idle.sh 2>/dev/null || true
chmod +x /mnt/home/$OMARCHY_USER/.local/share/omarchy/default/waybar/indicators/notification-silencing.sh 2>/dev/null || true
}
chroot_bash() {
HOME=/home/$OMARCHY_USER \
arch-chroot -u $OMARCHY_USER /mnt/ \
env OMARCHY_CHROOT_INSTALL=1 \
OMARCHY_INSTALL_MODE="${OMARCHY_INSTALL_MODE:-offline}" \
OMARCHY_USER_NAME="$(<user_full_name.txt)" \
OMARCHY_USER_EMAIL="$(<user_email_address.txt)" \
OMARCHY_MIRROR="$OMARCHY_MIRROR" \
USER="$OMARCHY_USER" \
HOME="/home/$OMARCHY_USER" \
OMARCHY_REPO="$(<omarchy_installer_repo.txt)" \
OMARCHY_REF="$(<omarchy_installer_ref.txt)" \
/bin/bash "$@"
}
if [[ $(tty) == "/dev/tty1" ]]; then
# Set log file to pull from in trap
export OMARCHY_INSTALL_LOG_FILE="/var/log/omarchy-install.log"
export OMARCHY_PATH="/root/omarchy"
export OMARCHY_INSTALL="/root/omarchy/install"
# Set install mode based on build mode file, default to offline
if [ -f /root/omarchy_install_mode.txt ]; then
export OMARCHY_INSTALL_MODE="$(cat /root/omarchy_install_mode.txt)"
else
export OMARCHY_INSTALL_MODE="offline"
fi
source "$OMARCHY_INSTALL/preflight/set-size-vars.sh"
source "$OMARCHY_INSTALL/helpers/logo.sh"
source "$OMARCHY_INSTALL/preflight/gum.sh"
source "$OMARCHY_INSTALL/helpers/tail-log-output.sh"
source "$OMARCHY_INSTALL/helpers/trap-errors.sh"
set_tokyo_night_colors
use_omarchy_helpers
run_configurator
clear_logo
gum style --foreground 3 --padding "1 0 0 $PADDING_LEFT" "Installing Omarchy..."
touch "$OMARCHY_INSTALL_LOG_FILE"
start_log_output
install_base_system 2>&1 | sed -u 's/\x1b\[[0-9;]*[a-zA-Z]//g' >>"$OMARCHY_INSTALL_LOG_FILE"
cleanup
# Get username from the config file after installation
OMARCHY_USER="$(jq -r '.users[0].username' user_credentials.json)"
# Install gum early so we have it for formatting
chroot_bash -lc "sudo pacman -S --noconfirm --needed gum" >/dev/null
# Run Omarchy installer directly (skip boot.sh since it would try to clone again)
chroot_bash -lc "source /home/$OMARCHY_USER/.local/share/omarchy/install.sh || bash"
install_arch
install_omarchy
fi
+433
View File
@@ -0,0 +1,433 @@
#!/bin/bash
# Rely on Omarchy for styling and error handling
source "$OMARCHY_INSTALL/helpers/all.sh"
# Ensure tzupdate is available for guessing timezone
command -v tzupdate >/dev/null || sudo pacman -Sy --noconfirm tzupdate
abort() {
gum style "${1:-Aborted installation}"
echo
gum style "You can retry later by running: ./.automated_script.sh"
exit 1
}
step() {
clear_logo
echo
gum style "$1"
echo
}
notice() {
clear_logo
echo
gum spin --spinner "pulse" --title "$1" -- sleep "${2:-2}"
echo
}
# STEP 1: KEYBOARD LAYOUT
keyboard_form() {
step "Let's setup your machine..."
keyboards=$'Azerbaijani|azerty
Belarusian|by
Belgian|be-latin1
Bosnian|ba
Bulgarian|bg-cp1251
Croatian|croat
Czech|cz
Danish|dk-latin1
Dutch|nl
English (UK)|uk
English (US)|us
English (US, Dvorak)|dvorak
Estonian|et
Finnish|fi
French|fr
French (Canada)|cf
French (Switzerland)|fr_CH
Georgian|ge
German|de
German (Switzerland)|de_CH-latin1
Greek|gr
Hebrew|il
Hungarian|hu
Icelandic|is-latin1
Irish|ie
Italian|it
Japanese|jp106
Kazakh|kazakh
Khmer (Cambodia)|khmer
Kyrgyz|kyrgyz
Lao|la-latin1
Latvian|lv
Lithuanian|lt
Macedonian|mk-utf
Norwegian|no-latin1
Polish|pl
Portuguese|pt-latin1
Portuguese (Brazil)|br-abnt2
Romanian|ro
Russian|ru
Serbian|sr-latin
Slovak|sk-qwertz
Slovenian|slovene
Spanish|es
Spanish (Latin American)|la-latin1
Swedish|sv-latin1
Tajik|tj_alt-UTF8
Turkish|trq
Ukrainian|ua'
choice=$(printf '%s\n' "$keyboards" | cut -d'|' -f1 | gum choose --height 10 --selected "English (US)" --header "Select keyboard layout") || abort
keyboard=$(printf '%s\n' "$keyboards" | awk -F'|' -v c="$choice" '$1==c{print $2; exit}')
# Only attempt to load keyboard layout if we're on a real console
# loadkeys only works on Linux virtual consoles (tty), not in terminal emulators
if [[ $(tty 2>/dev/null) == "/dev/tty"* ]]; then
loadkeys "$keyboard" 2>/dev/null
fi
}
keyboard_form
# STEP 2: USER
user_form() {
step "Let's setup your user account..."
while true; do
username=$(gum input --placeholder "Alphanumeric without spaces (like dhh)" --prompt.foreground="#845DF9" --prompt "Username> ") || abort
if [[ "$username" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]]; then
break
else
notice "Username must be alphanumeric with no spaces" 1
fi
done
while true; do
password=$(gum input --placeholder "Used for user + root + encryption" --prompt.foreground="#845DF9" --password --prompt "Password> ") || abort
password_confirmation=$(gum input --placeholder "Must match the password you just typed" --prompt.foreground="#845DF9" --password --prompt "Confirm> ") || abort
if [[ -n "$password" && "$password" == "$password_confirmation" ]]; then
break
elif [[ -z "$password" ]]; then
notice "Your password can't be blank!" 1
else
notice "Passwords didn't match!" 1
fi
done
# Hash the password using yescrypt
password_hash=$(printf '%s' "$password" | openssl passwd -6 -stdin)
full_name=$(gum input --placeholder "Used for git authentication (hit return to skip)" --prompt.foreground="#845DF9" --prompt "Full name> ")
email_address=$(gum input --placeholder "Used for git authentication (hit return to skip)" --prompt.foreground="#845DF9" --prompt "Email address> ")
while true; do
hostname=$(gum input --placeholder "Alphanumeric without spaces (or return for 'omarchy')" --prompt.foreground="#845DF9" --prompt "Hostname> ")
if [[ "$hostname" =~ ^[A-Za-z_][A-Za-z0-9_-]*\$?$ ]]; then
break
elif [[ -z $hostname ]]; then
hostname="omarchy"
break
else
notice "Hostname must be alphanumeric using dashes or underscores but no spaces" 1
fi
done
# Pick timezone
geo_guessed_timezone=$(tzupdate -p 2>/dev/null)
if [[ -n $geo_guessed_timezone ]]; then
timezone=$(timedatectl list-timezones | gum choose --height 10 --selected "$geo_guessed_timezone" --header "Timezone") || abort
else
timezone=$(timedatectl list-timezones | gum filter --height 10 --header "Timezone") || abort
fi
}
user_form
while true; do
# Add manual padding since gum table -p doesn't respect padding
echo -e "Field,Value
Username,$username
Password,$(printf "%${#password}s" | tr ' ' '*')
Full name,${full_name:-[Skipped]}
Email address,${email_address:-[Skipped]}
Hostname,$hostname
Timezone,$timezone
Keyboard,$keyboard" |
gum table -s "," -p | sed "s/^/${PADDING_LEFT_SPACES}/"
echo
if gum confirm --negative "No, change it" "Does this look right?"; then
break
else
keyboard_form
user_form
fi
done
# STEP 3: DISK
get_disk_info() {
local device="$1"
local size vendor model label
# Get basic disk information
size=$(lsblk -dno SIZE "$device" 2>/dev/null)
vendor=$(lsblk -dno VENDOR "$device" 2>/dev/null | sed 's/ *$//')
model=$(lsblk -dno MODEL "$device" 2>/dev/null | sed 's/ *$//')
# Combine vendor and model, avoiding duplication
label=""
if [[ -n $vendor && -n $model ]]; then
if [[ $model == *$vendor* ]]; then
label="$model"
else
label="$vendor $model"
fi
elif [[ -n $model ]]; then
label="$model"
elif [[ -n $vendor ]]; then
label="$vendor"
fi
# Format display string
local display="$device"
[[ -n $size ]] && display="$display ($size)"
[[ -n $label ]] && display="$display - $label"
# Append compact partition summary
local part_summary
part_summary=$(lsblk -nro TYPE,NAME,FSTYPE,MOUNTPOINT "$device" 2>/dev/null | \
awk '$1=="part" { printf "%s%s%s", s, ($3==""?"unknown":$3), ($4==""?"":"("$4")"); s=", " }')
[[ -n $part_summary ]] && display+=" [$part_summary]"
echo "$display"
}
disk_form() {
step "Let's select where to install Omarchy..."
# Don't offer the install media as an option (Arch ISO mounts it here)
local exclude_disk
exclude_disk=$(findmnt -no SOURCE /run/archiso/bootmnt 2>/dev/null || true)
# List all installable disks, excluding the boot device if present
local available_disks
available_disks=$(
lsblk -dpno NAME,TYPE |
awk '$2=="disk"{print $1}' |
grep -E '/dev/(sd|hd|vd|nvme|mmcblk|xv)' |
{ if [[ -n "$exclude_disk" ]]; then grep -Fvx "$exclude_disk"; else cat; fi; }
)
# Get available disks and format them with info
local disk_options=""
while IFS= read -r device; do
if [[ -n "$device" ]]; then
disk_info=$(get_disk_info "$device")
disk_options="$disk_options$disk_info"$'\n'
fi
done <<<"$available_disks"
selected_display=$(echo "$disk_options" | gum choose --header "Select install disk") || abort
disk=$(echo "$selected_display" | awk '{print $1}')
}
disk_form
while true; do
gum style "Everything will be overwritten. There is no recovery possible."
echo
if gum confirm --affirmative "Yes, format disk" --negative "No, change it" "Confirm overwriting ${disk}"; then
break
else
disk_form
fi
done
clear
# Save user full name and email address, so the autostart can
# set them as OMARCHY_USER_NAME and OMARCHY_USER_EMAIL
echo "$full_name" >user_full_name.txt
echo "$email_address" >user_email_address.txt
# Escape username and password for safe inclusion
password_escaped=$(echo -n "$password" | jq -Rsa)
password_hash_escaped=$(echo -n "$password_hash" | jq -Rsa)
username_escaped=$(echo -n "$username" | jq -Rsa)
cat <<-_EOF_ >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_
# Setup partition layout
disk_size=$(lsblk -bdno SIZE "$disk")
mib=$((1024 * 1024))
gib=$((mib * 1024))
disk_size_in_mib=$((disk_size / mib * mib)) # Rounds to nearest MiB
gpt_backup_reserve=$((mib))
boot_partition_start=$((mib))
boot_partition_size=$((2 * gib))
main_partition_start=$((boot_partition_size + boot_partition_start))
main_partition_size=$((disk_size_in_mib - main_partition_start - gpt_backup_reserve))
# Detect T2 Mac and set appropriate kernel
if lspci -nn 2>/dev/null | grep -q "106b:180[12]"; then
kernel_choice="linux-t2"
else
kernel_choice="linux"
fi
cat <<-_EOF_ >user_configuration.json
{
"app_config": null,
"archinstall-language": "English",
"auth_config": {},
"audio_config": { "audio": "pipewire" },
"bootloader": "Limine",
"custom_commands": [],
"disk_config": {
"btrfs_options": {
"snapshot_config": {
"type": "Snapper"
}
},
"config_type": "default_layout",
"device_modifications": [
{
"device": "$disk",
"partitions": [
{
"btrfs": [],
"dev_path": null,
"flags": [ "boot", "esp" ],
"fs_type": "fat32",
"mount_options": [],
"mountpoint": "/boot",
"obj_id": "ea21d3f2-82bb-49cc-ab5d-6f81ae94e18d",
"size": {
"sector_size": { "unit": "B", "value": 512 },
"unit": "B",
"value": $boot_partition_size
},
"start": {
"sector_size": { "unit": "B", "value": 512 },
"unit": "B",
"value": $boot_partition_start
},
"status": "create",
"type": "primary"
},
{
"btrfs": [
{ "mountpoint": "/", "name": "@" },
{ "mountpoint": "/home", "name": "@home" },
{ "mountpoint": "/var/log", "name": "@log" },
{ "mountpoint": "/var/cache/pacman/pkg", "name": "@pkg" }
],
"dev_path": null,
"flags": [],
"fs_type": "btrfs",
"mount_options": [ "compress=zstd" ],
"mountpoint": null,
"obj_id": "8c2c2b92-1070-455d-b76a-56263bab24aa",
"size": {
"sector_size": { "unit": "B", "value": 512 },
"unit": "B",
"value": $main_partition_size
},
"start": {
"sector_size": { "unit": "B", "value": 512 },
"unit": "B",
"value": $main_partition_start
},
"status": "create",
"type": "primary"
}
],
"wipe": true
}
],
"disk_encryption": {
"encryption_type": "luks",
"lvm_volumes": [],
"iter_time": 2000,
"partitions": [ "8c2c2b92-1070-455d-b76a-56263bab24aa" ],
"encryption_password": $password_escaped
}
},
"hostname": "$hostname",
"kernels": [ "$kernel_choice" ],
"network_config": { "type": "iso" },
"ntp": true,
"parallel_downloads": 8,
"script": null,
"services": [],
"swap": true,
"timezone": "$timezone",
"locale_config": {
"kb_layout": "$keyboard",
"sys_enc": "UTF-8",
"sys_lang": "en_US.UTF-8"
},
"mirror_config": {
"custom_repositories": [],
"custom_servers": [
{"url": "https://mirror.omarchy.org/\$repo/os/\$arch"},
{"url": "https://mirror.rackspace.com/archlinux/\$repo/os/\$arch"},
{"url": "https://geo.mirror.pkgbuild.com/\$repo/os/\$arch"}
],
"mirror_regions": {},
"optional_repositories": []
},
"packages": [
"base-devel",
"git",
"omarchy-keyring"
],
"profile_config": {
"gfx_driver": null,
"greeter": null,
"profile": {}
},
"version": "3.0.9"
}
_EOF_
if [[ $1 == "dry" ]]; then
echo -e "User Configuration:"
cat user_configuration.json
echo -e "\n\nUser Credentials:"
cat user_credentials.json
echo -e "\n\nUser Full Name:"
cat user_full_name.txt
echo -e "\nUser Email Address:"
cat user_email_address.txt
rm user_configuration.json user_credentials.json user_full_name.txt user_email_address.txt
fi
@@ -1,5 +1,5 @@
title Arch Linux install medium (x86_64, UEFI)
title Omarchy (x86_64, UEFI)
sort-key 01
linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% quiet splash
linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-t2
initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-t2.img
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% quiet splash xe.enable_panel_replay=0
+8 -7
View File
@@ -9,11 +9,12 @@ insmod exfat
insmod udf
# Use graphics-mode output
insmod font
if loadfont "${prefix}/fonts/unicode.pf2" ; then
insmod all_video
set gfxmode="auto"
terminal_input console
terminal_output console
terminal_output gfxterm
fi
# Enable serial console
@@ -51,16 +52,16 @@ timeout_style=hidden
# Menu entries
menuentry "Arch Linux install medium (%ARCH%, ${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' {
menuentry "Omarchy (%ARCH%, ${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' {
set gfxpayload=keep
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% quiet splash
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-t2 archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% quiet splash xe.enable_panel_replay=0
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-t2.img
}
menuentry "Arch Linux install medium with speakup screen reader (%ARCH%, ${archiso_platform})" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'archlinux-accessibility' {
menuentry "Omarchy with speakup screen reader (%ARCH%, ${archiso_platform})" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'archlinux-accessibility' {
set gfxpayload=keep
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-t2 archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on xe.enable_panel_replay=0
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-t2.img
}
+80
View File
@@ -0,0 +1,80 @@
# https://www.supergrubdisk.org/wiki/Loopback.cfg
# Search for the ISO volume
search --no-floppy --set=archiso_img_dev --file "${iso_path}"
probe --set archiso_img_dev_uuid --fs-uuid "${archiso_img_dev}"
# Get a human readable platform identifier
if [ "${grub_platform}" == 'efi' ]; then
archiso_platform='UEFI'
if [ "${grub_cpu}" == 'x86_64' ]; then
archiso_platform="x64 ${archiso_platform}"
elif [ "${grub_cpu}" == 'i386' ]; then
archiso_platform="IA32 ${archiso_platform}"
else
archiso_platform="${grub_cpu} ${archiso_platform}"
fi
elif [ "${grub_platform}" == 'pc' ]; then
archiso_platform='BIOS'
else
archiso_platform="${grub_cpu} ${grub_platform}"
fi
# Set default menu entry
default=archlinux
timeout=0
timeout_style=hidden
# Menu entries
menuentry "Omarchy (%ARCH%, ${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' {
set gfxpayload=keep
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-t2 archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" quiet splash xe.enable_panel_replay=0
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-t2.img
}
menuentry "Omarchy with speakup screen reader (%ARCH%, ${archiso_platform})" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'archlinux-accessibility' {
set gfxpayload=keep
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-t2 archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" accessibility=on xe.enable_panel_replay=0
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-t2.img
}
if [ "${grub_platform}" == 'efi' -a "${grub_cpu}" == 'x86_64' -a -f '/boot/memtest86+/memtest.efi' ]; then
menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool {
set gfxpayload=800x600,1024x768
linux /boot/memtest86+/memtest.efi
}
fi
if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then
menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool {
set gfxpayload=800x600,1024x768
linux /boot/memtest86+/memtest
}
fi
if [ "${grub_platform}" == 'efi' ]; then
if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then
menuentry 'UEFI Shell' --class efi {
chainloader /shellx64.efi
}
elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then
menuentry 'UEFI Shell' --class efi {
chainloader /shellia32.efi
}
fi
menuentry 'UEFI Firmware Settings' --id 'uefi-firmware' {
fwsetup
}
fi
menuentry 'System shutdown' --class shutdown --class poweroff {
echo 'System shutting down...'
halt
}
menuentry 'System restart' --class reboot --class restart {
echo 'System rebooting...'
reboot
}
File renamed without changes.
@@ -15,26 +15,20 @@ LocalFileSigLevel = Optional
[core]
Server = https://mirror.omarchy.org/$repo/os/$arch
Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[extra]
Server = https://mirror.omarchy.org/$repo/os/$arch
Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[multilib]
Server = https://mirror.omarchy.org/$repo/os/$arch
Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[omarchy]
SigLevel = Optional TrustAll
Server = https://pkgs.omarchy.org/$arch
Server = https://pkgs.omarchy.org/edge/$arch
[arch-mact2]
Server = https://mirror.omarchy.org/$repo/$arch
Server = https://github.com/NoaHimesaka1873/arch-mact2-mirror/releases/download/release
SigLevel = Never
+34
View File
@@ -0,0 +1,34 @@
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
[options]
HoldPkg = pacman glibc
Architecture = auto
ParallelDownloads = 5
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
[core]
Server = https://rc-mirror.omarchy.org/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[extra]
Server = https://rc-mirror.omarchy.org/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[multilib]
Server = https://rc-mirror.omarchy.org/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[omarchy]
SigLevel = Optional TrustAll
Server = https://pkgs.omarchy.org/edge/$arch
[arch-mact2]
Server = https://github.com/NoaHimesaka1873/arch-mact2-mirror/releases/download/release
SigLevel = Never
+34
View File
@@ -0,0 +1,34 @@
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
[options]
HoldPkg = pacman glibc
Architecture = auto
ParallelDownloads = 5
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
[core]
Server = https://stable-mirror.omarchy.org/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[extra]
Server = https://stable-mirror.omarchy.org/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[multilib]
Server = https://stable-mirror.omarchy.org/$repo/os/$arch
Include = /etc/pacman.d/mirrorlist
[omarchy]
SigLevel = Optional TrustAll
Server = https://pkgs.omarchy.org/stable/$arch
[arch-mact2]
Server = https://github.com/NoaHimesaka1873/arch-mact2-mirror/releases/download/release
SigLevel = Never
+3 -6
View File
@@ -2,17 +2,15 @@
# shellcheck disable=SC2034
iso_name="omarchy"
iso_label="ARCH_$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y%m)"
iso_label="OMARCHY_$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y%m)"
iso_publisher="Omarchy <https://omarchy.org>"
iso_application="Omarchy Installer"
iso_version="$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y.%m.%d)"
install_dir="arch"
buildmodes=('iso')
bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito'
'uefi-ia32.systemd-boot.esp' 'uefi-x64.systemd-boot.esp'
'uefi-ia32.systemd-boot.eltorito' 'uefi-x64.systemd-boot.eltorito')
bootmodes=('bios.syslinux' 'uefi.grub')
arch="x86_64"
pacman_conf="pacman.conf"
pacman_conf="pacman-offline.conf"
airootfs_image_type="squashfs"
airootfs_image_tool_options=('-comp' 'xz' '-Xbcj' 'x86' '-b' '1M' '-Xdict-size' '1M')
bootstrap_tarball_compression=('zstd' '-c' '-T0' '--auto-threads=logical' '--long' '-19')
@@ -24,6 +22,5 @@ file_permissions=(
["/usr/local/bin/choose-mirror"]="0:0:755"
["/root/configurator"]="0:0:755"
["/var/cache/omarchy/mirror/offline/"]="0:0:775"
["/usr/bin/tte"]="0:0:755"
["/usr/local/bin/omarchy-upload-log"]="0:0:755"
)
+28
View File
@@ -0,0 +1,28 @@
SERIAL 0 115200
UI vesamenu.c32
MENU TITLE Omarchy
MENU BACKGROUND splash.png
MENU WIDTH 78
MENU MARGIN 4
MENU ROWS 7
MENU VSHIFT 10
MENU TABMSGROW 14
MENU CMDLINEROW 14
MENU HELPMSGROW 16
MENU HELPMSGENDROW 29
# Refer to https://wiki.syslinux.org/wiki/index.php/Comboot/menu.c32
MENU COLOR border 30;44 #40ffffff #a0000000 std
MENU COLOR title 1;36;44 #9033ccff #a0000000 std
MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
MENU COLOR unsel 37;44 #50ffffff #a0000000 std
MENU COLOR help 37;40 #c0ffffff #a0000000 std
MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
MENU COLOR msg07 37;40 #90ffffff #a0000000 std
MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
MENU CLEAR
MENU IMMEDIATE
+32
View File
@@ -0,0 +1,32 @@
LABEL arch64_nbd
TEXT HELP
Boot the Omarchy install medium using NBD.
It allows you to install Omarchy or perform system maintenance.
ENDTEXT
MENU LABEL Omarchy install medium (x86_64, NBD)
LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-t2
INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux-t2.img
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% archiso_nbd_srv=${pxeserver} cms_verify=y
SYSAPPEND 3
LABEL arch64_nfs
TEXT HELP
Boot the Omarchy live medium using NFS.
It allows you to install Omarchy or perform system maintenance.
ENDTEXT
MENU LABEL Omarchy install medium (x86_64, NFS)
LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-t2
INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux-t2.img
APPEND archisobasedir=%INSTALL_DIR% archiso_nfs_srv=${pxeserver}:/run/archiso/bootmnt cms_verify=y
SYSAPPEND 3
LABEL arch64_http
TEXT HELP
Boot the Omarchy live medium using HTTP.
It allows you to install Omarchy or perform system maintenance.
ENDTEXT
MENU LABEL Omarchy install medium (x86_64, HTTP)
LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-t2
INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux-t2.img
APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ cms_verify=y
SYSAPPEND 3
+5
View File
@@ -0,0 +1,5 @@
INCLUDE archiso_head.cfg
INCLUDE archiso_pxe-linux.cfg
INCLUDE archiso_tail.cfg
+20
View File
@@ -0,0 +1,20 @@
LABEL arch64
TEXT HELP
Boot the Omarchy install medium on BIOS.
It allows you to install Omarchy or perform system maintenance.
ENDTEXT
MENU LABEL Omarchy install medium (x86_64, BIOS)
LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-t2
INITRD /%INSTALL_DIR%/boot/x86_64/initramfs-linux-t2.img
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% quiet splash xe.enable_panel_replay=0
# Accessibility boot option
LABEL arch64speech
TEXT HELP
Boot the Omarchy install medium on BIOS with speakup screen reader.
It allows you to install Omarchy or perform system maintenance with speech feedback.
ENDTEXT
MENU LABEL Omarchy install medium (x86_64, BIOS) with ^speech
LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-t2
INITRD /%INSTALL_DIR%/boot/x86_64/initramfs-linux-t2.img
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on xe.enable_panel_replay=0
+8
View File
@@ -0,0 +1,8 @@
INCLUDE archiso_head.cfg
DEFAULT arch64
TIMEOUT 150
INCLUDE archiso_sys-linux.cfg
INCLUDE archiso_tail.cfg
+35
View File
@@ -0,0 +1,35 @@
LABEL existing
TEXT HELP
Boot an existing operating system.
Press TAB to edit the disk and partition number to boot.
ENDTEXT
MENU LABEL Boot existing OS
COM32 chain.c32
APPEND hd0 0
# https://www.memtest.org/
LABEL memtest
MENU LABEL Run Memtest86+ (RAM test)
LINUX /boot/memtest86+/memtest
# https://wiki.syslinux.org/wiki/index.php/Hdt_(Hardware_Detection_Tool)
LABEL hdt
MENU LABEL Hardware Information (HDT)
COM32 hdt.c32
APPEND modules_alias=hdt/modalias.gz pciids=hdt/pciids.gz
LABEL reboot
TEXT HELP
Reboot computer.
The computer's firmware must support APM.
ENDTEXT
MENU LABEL Reboot
COM32 reboot.c32
LABEL poweroff
TEXT HELP
Power off computer.
The computer's firmware must support APM.
ENDTEXT
MENU LABEL Power Off
COM32 poweroff.c32
+11
View File
@@ -0,0 +1,11 @@
DEFAULT select
LABEL select
COM32 whichsys.c32
APPEND -pxe- pxe -sys- sys -iso- sys
LABEL pxe
CONFIG archiso_pxe.cfg
LABEL sys
CONFIG archiso_sys.cfg
+158
View File
@@ -0,0 +1,158 @@
# Dual-Boot Installation Support for Omarchy ISO
## Context
Currently, the Omarchy installer wipes the entire selected disk (`"wipe": true`) and creates two partitions: a 2GB FAT32 ESP and a LUKS-encrypted Btrfs root. This means users must dedicate an entire disk to Omarchy. Adding dual-boot support lets users install alongside an existing OS (typically Windows) while keeping the Omarchy partition encrypted.
## Core Approach: `pre_mounted_config`
**Do our own partitioning, then hand off to archinstall for package installation only.**
archinstall's `manual_partitioning` mode has a long history of bugs with existing partitions and LUKS (archinstall issues #998, #2072, #2444). Instead, we:
1. Detect existing partitions and free space ourselves (with `sgdisk`/`parted`)
2. Create the LUKS partition and Btrfs subvolumes ourselves (with `cryptsetup`/`mkfs.btrfs`)
3. Mount everything at `/mnt/archinstall`
4. Tell archinstall to use `"config_type": "pre_mounted_config"` — it installs packages into our pre-mounted tree and does zero disk operations
5. Handle encryption config (crypttab, mkinitcpio hooks, bootloader cmdline) in post-install
The existing full-disk path stays completely unchanged. Dual-boot is a parallel code path.
## Implementation Guardrails
- **Run target changes in chroot** — all target-system commands (`mkinitcpio -P`, `limine-scan`, bootloader config updates) must run via `arch-chroot "$INSTALL_ROOT" ...`
- **Edit target files under `$INSTALL_ROOT` only** — write `mkinitcpio` hook config, `limine.conf`, `crypttab`, and related files in `$INSTALL_ROOT/etc` and `$INSTALL_ROOT/boot` (never in the live environment root)
- **Settle kernel partition state** — after creating the new partition, run `partprobe "$DISK"` and `udevadm settle` before `cryptsetup` to avoid device-node races
- **Deterministic fstab** — always generate `/etc/fstab` for dual-boot with overwrite semantics (e.g., `genfstab -U "$INSTALL_ROOT" > "$INSTALL_ROOT/etc/fstab"`) to avoid duplicate entries on retries
- **Hook compatibility** — when updating mkinitcpio hooks, add `encrypt` for busybox initramfs or `sd-encrypt` for systemd initramfs; never assume one universally
- **Safe rollback on failure** — on any dual-boot setup failure: unmount mounts, close LUKS mapping, and surface recovery guidance; optionally delete the just-created partition only if it was created in this run
## Scope Constraints
- **UEFI/GPT only** — dual-boot on MBR/BIOS is too fragile; those users get full-disk only
- **No auto-shrinking** — users must free up space from their existing OS first (e.g., Windows Disk Management). Too risky to shrink partitions automatically
- **Minimum 20GB free space** required for Omarchy
## User Flow
```
Select disk → Detect layout →
If disk has existing OS + ESP + ≥20GB free space:
"How would you like to install?"
→ "Install alongside Windows (use 85GB free space)"
→ "Erase entire disk"
If disk is empty or no free space:
Existing "Confirm overwriting" flow (unchanged)
```
## File Changes
### 1. `configs/airootfs/root/configurator`
**Add after disk selection (line 233), before config generation:**
- `detect_disk_layout()` — examines selected disk for:
- GPT partition table (required for dual-boot)
- Existing ESP partition (via `lsblk` PARTTYPE matching EFI GUID)
- Free unallocated space (via `sgdisk -F`/`-E` or `parted print free`)
- OS detection for installer UX warnings/prompts (not boot correctness): mount ESP read-only, check common vendor paths like `EFI/Microsoft`, `EFI/systemd`, `EFI/ubuntu`, `EFI/fedora`, `EFI/GRUB`
- `install_mode_form()` — shows gum choose with dual-boot vs erase options when conditions are met. Sets `DUAL_BOOT=true/false`.
**Generate different JSON when `DUAL_BOOT=true`:**
```json
{
"disk_config": {
"config_type": "pre_mounted_config",
"mountpoint": "/mnt/archinstall"
}
}
```
No `device_modifications`, no `disk_encryption`, no `btrfs_options` — we handle all of that ourselves. Everything else (hostname, kernels, packages, etc.) stays the same.
**Write `install_mode.sh`** alongside the other config files:
```bash
DUAL_BOOT=true
DISK=/dev/nvme0n1
ESP_PARTITION=/dev/nvme0n1p1
```
### 2. `configs/airootfs/root/.automated_script.sh`
**Source `install_mode.sh`** in `run_configurator()` if it exists.
**Add `setup_dual_boot_partitions()`** — runs before archinstall when `DUAL_BOOT=true`:
1. Select the largest contiguous free region and run `sgdisk` to create new partition there (type 8309 = Linux LUKS)
2. `partprobe "$DISK"` + `udevadm settle` so new partition node is present
3. `cryptsetup luksFormat` + `luksOpen` with user's password
4. `mkfs.btrfs` on `/dev/mapper/omarchy_root`
5. Create Btrfs subvolumes: `@`, `@home`, `@log`, `@pkg`
6. Mount subvolumes at `/mnt/archinstall` with `compress=zstd`
7. Mount existing ESP (untouched) at `/mnt/archinstall/boot`
8. Generate target `/etc/fstab` from mounted filesystems before post-install steps
**Add `configure_dual_boot_post_install()`** — runs after archinstall:
1. Write `/etc/crypttab` entry using LUKS UUID/PARTUUID (stable identifier), e.g. `omarchy_root UUID=<luks-uuid> none luks,discard`
2. Update mkinitcpio hooks before `filesystems`: `encrypt` (busybox) or `sd-encrypt` (systemd)
3. Regenerate initramfs with `arch-chroot "$INSTALL_ROOT" mkinitcpio -P`
4. Configure Limine kernel cmdline to match initramfs mode:
- busybox `encrypt`: `cryptdevice=UUID=<uuid>:omarchy_root root=/dev/mapper/omarchy_root`
- systemd `sd-encrypt`: `rd.luks.name=<uuid>=omarchy_root root=/dev/mapper/omarchy_root` (or equivalent `rd.luks.uuid=` form)
5. Run `arch-chroot "$INSTALL_ROOT" limine-scan` to detect other OS boot entries (Windows, etc.)
6. Preserve current firmware default boot order unless user explicitly chooses to make Limine first (capture and restore `BootOrder` if `efibootmgr` side effects reorder entries)
**Use `$INSTALL_ROOT` variable** — defaults to `/mnt` for full-disk, `/mnt/archinstall` for dual-boot. Post-install steps (offline mirror bind-mount, sudoers, omarchy copy) reference this instead of hardcoded `/mnt`.
### 3. `builder/build-iso.sh` + `builder/archinstall.packages`
Add `parted` to packages available in the live ISO (needed for free space detection).
## Bootloader Coexistence
Limine installs to `ESP/EFI/arch-limine/` and registers via `efibootmgr`. This sits alongside:
- Windows Boot Manager at `ESP/EFI/Microsoft/Boot/bootmgfw.efi`
- Any other bootloader in its own ESP subdirectory
`limine-scan` auto-detects other UEFI boot entries and adds them to `limine.conf`. Users can choose OS at boot.
**Boot order policy**: creating a new EFI entry must not silently change the current default boot target. Keep existing firmware boot order by default and only promote Limine when user opts in.
Implementation note: when registering Limine with `efibootmgr`, do not pass reorder flags by default; if firmware still changes order, explicitly restore prior `BootOrder` unless the user opted to promote Limine.
**ESP size note**: Windows typically creates a 100-260MB ESP. This is enough for Limine + kernel + initramfs, but Snapper boot snapshots (which copy kernels to ESP) will be limited or disabled.
**ESP free-space threshold**:
- If ESP has `<100MB` free at install time: show a strong warning (do not block install)
- If ESP has `<64MB` free: hide dual-boot option and require full-disk install (or user frees space first)
**BitLocker warning**: If Windows is detected, show a warning about having the BitLocker recovery key ready, since modifying ESP/UEFI entries can trigger recovery.
## Edge Cases
| Scenario | Behavior |
|----------|----------|
| Disk is empty | Full-disk install only (current behavior) |
| Existing OS but no free space | Full-disk install only, with note to free space first |
| Free space < 20GB | Dual-boot option not shown |
| MBR/BIOS disk | Dual-boot option not shown |
| ESP < 100MB free after mount | Warn user; continue allowed |
| ESP < 64MB free after mount | Dual-boot option not shown |
| Multiple free regions | Use largest contiguous region |
| Partitioning/setup failure mid-run | Cleanup mounts/LUKS and abort safely |
## Verification
1. **Regression**: Full-disk install in VM with empty disk — must work identically to today
2. **Dual-boot with Windows**: VM with Windows installed + 40GB free space — detect Windows, install alongside, both OSes boot
3. **Dual-boot with Linux**: VM with another Linux + free space — similar test
4. **No free space**: VM with fully partitioned disk — dual-boot option should not appear
5. **Encryption**: After dual-boot install, verify LUKS unlock prompt at boot and encrypted root
6. **Initramfs mode**: Validate both busybox and systemd hook paths boot correctly (`encrypt` vs `sd-encrypt`)
7. **Boot order**: Verify existing default UEFI entry remains unchanged unless user opted to promote Limine
+224
View File
@@ -0,0 +1,224 @@
# OEM Install + First-Boot Setup Plan
## Goal
Create a second ISO flavor for OEM preloading that is installed to internal storage at factory time, then boots into customer setup on first power-on (no external media required), and ends in a fully encrypted Omarchy install.
## Product Requirements
- Factory can preload one image to internal disk.
- Customer first boot launches setup flow automatically (already works: `.automated_script.sh` runs configurator on tty1).
- Customer chooses credentials/settings.
- Final installed OS uses full-disk encryption (LUKS) with customer password (already works: configurator collects password and passes it to archinstall as `encryption_password`).
- Existing consumer ISO behavior remains unchanged.
---
## Chosen Architecture
### Bootstrapping model
- OEM devices ship with an OEM bootstrap ISO image written to internal disk.
- On first boot, `copytoram=y` kernel arg loads the live environment into RAM, freeing the internal disk.
- Bootstrap environment launches existing configurator + installer.
- Installer performs a fresh install to internal disk with LUKS encryption enabled.
- Bootstrap environment is overwritten during install.
### Recovery model: zero-recovery
- No permanent recovery partition.
- Simplest and strongest security story.
- Recovery requires external reinstall media.
---
## Non-Goals
- No on-device recovery workflow.
- No changes to normal installer UX outside explicit OEM mode checks and warnings.
- No factory credential provisioning.
---
## Repo Implementation Plan
## 1) Add OEM build mode
### Files
- `bin/omarchy-iso-make`
- `builder/build-iso.sh`
### Changes
- Add CLI flag `--oem` to `bin/omarchy-iso-make`.
- Pass `OMARCHY_MODE=oem` into Docker build env (default `normal`).
- In `builder/build-iso.sh`, write mode marker `/root/omarchy_mode` containing `oem` or `normal` (same pattern as `omarchy_mirror`).
- Keep OEM on current boot stack (`uefi.grub` + `bios.syslinux`); do not add or depend on systemd-boot paths.
- When `OMARCHY_MODE=oem`, inject `copytoram=y` into all shipped OEM boot entry points before `mkarchiso` runs:
- `grub/grub.cfg`: append to `linux` cmdline entries.
- `grub/loopback.cfg`: append to `linux` cmdline entries.
- `syslinux/archiso_sys-linux.cfg`: append to `APPEND` lines.
- When `OMARCHY_MODE=oem`, remove accessibility/speakup boot entries:
- `grub/grub.cfg`: remove `archlinux-accessibility` menuentry.
- `grub/loopback.cfg`: remove `archlinux-accessibility` menuentry.
- `syslinux/archiso_sys-linux.cfg`: remove `arch64speech` label block.
- When `OMARCHY_MODE=oem`, override `iso_application` in `profiledef.sh` to `"Omarchy OEM Installer"`.
- Rename output ISO with `-oem` suffix (in addition to existing `-$OMARCHY_INSTALLER_REF` suffix).
### Hardening
- Add post-injection build assertion that fails build if any expected boot config does not contain `copytoram=y`.
- Add post-injection build assertion that fails build if any OEM boot config still contains accessibility/speakup entries.
- Make injection idempotent (do not duplicate `copytoram=y` if already present).
### Acceptance criteria
- `./bin/omarchy-iso-make --oem` builds successfully.
- OEM ISO boot entries contain `copytoram=y` in all supported boot paths.
- OEM ISO does not expose accessibility/speakup boot entries.
- Normal build output and behavior remain unchanged.
### Suggested verification commands
- `bsdtar -xOf out/<iso>.iso boot/grub/grub.cfg | rg copytoram=y`
- `bsdtar -xOf out/<iso>.iso boot/grub/loopback.cfg | rg copytoram=y`
- `bsdtar -xOf out/<iso>.iso boot/syslinux/archiso_sys-linux.cfg | rg copytoram=y`
- `bsdtar -xOf out/<iso>.iso boot/grub/grub.cfg | rg 'accessibility|speakup'` (should return no matches)
- `bsdtar -xOf out/<iso>.iso boot/syslinux/archiso_sys-linux.cfg | rg 'speech|accessibility'` (should return no matches)
---
## 2) Add OEM safety guardrails
### Why
OEM image boots from internal disk and later wipes that same disk. Live environment must be fully in RAM before install begins.
### File
- `configs/airootfs/root/.automated_script.sh`
### Changes
- Before `run_configurator`, if `/root/omarchy_mode` is `oem`:
- Verify `/proc/cmdline` contains `copytoram=y`; abort with clear actionable error if missing.
- Verify factory hardware minimum using `MemTotal`:
- Require `MemTotal >= 8 GiB`.
- Abort with clear error if below minimum.
- Verify runtime memory safety using `MemAvailable`:
- Minimum threshold: `1.5 x ISO size + 1 GiB`.
- Abort with clear error if below threshold.
- Verify runtime state indicates live root is in RAM (for example, expected archiso runtime mounts present and boot media not actively mounted as install target path).
### Acceptance criteria
- OEM mode aborts safely if `copytoram=y` missing from cmdline.
- OEM mode aborts safely if `MemTotal < 8 GiB`.
- OEM mode aborts safely if `MemAvailable` below threshold.
- OEM mode aborts safely if runtime state does not confirm RAM-backed live environment.
### Error message requirements
- State exactly what failed.
- State why install is blocked.
- Provide next step (reboot using proper OEM media or use external recovery media).
---
## 3) OEM disk warning
### Why
With `copytoram=y`, archiso copies squashfs to RAM and releases boot device. Existing configurator call `findmnt -no SOURCE /run/archiso/bootmnt` may return empty, so exclusion filter is skipped and all physical disks are shown, including former boot disk. No disk selection logic change is required.
OEM mode still needs an unmistakable warning before destructive install proceeds.
### File
- `configs/airootfs/root/configurator`
### Changes
- Read mode from `/root/omarchy_mode`.
- If mode is `oem`, add OEM-specific warning text before existing destructive confirmation.
- Upgrade confirmation in OEM mode to explicit typed confirmation (for example: `YES, WIPE DISK`) while preserving existing normal-mode flow.
### Acceptance criteria
- Normal ISO behavior is unchanged.
- OEM ISO shows OEM-specific warning before disk wipe confirmation.
- OEM typed confirmation is required before destructive action.
- In VM with `copytoram=y`, former boot disk appears in disk list without exclusion-logic changes.
---
## 4) Documentation
### File
- `README.md`
### Changes
- Document `--oem` build flag and resulting artifact naming.
- Document factory workflow: writing OEM ISO to internal disk and expected first-boot UX.
- Document failure and recovery behavior:
- Missing `copytoram=y`, `MemTotal < 8 GiB`, or low `MemAvailable` causes safe abort.
- Interrupted/failed install requires external reinstall media.
- Add short operator checklist for manufacturing line validation.
---
## 5) Validation
### VM test matrix
1. Build OEM ISO.
2. Write OEM ISO to virtual disk (not external media emulation).
3. Boot from virtual disk and verify:
- `/proc/cmdline` contains `copytoram=y`.
- Guardrail checks pass in healthy case.
- OEM boot menu does not include accessibility/speech entries.
4. Complete setup flow on first boot.
5. Install to same disk.
6. Reboot into installed OS.
7. Verify encryption:
- `lsblk` shows crypt mapping.
- `cryptsetup status` reports active LUKS device.
- Boot requires unlock passphrase.
8. Validate OEM warning + typed confirmation appears and gates destructive action.
### Boot path coverage
- UEFI + GRUB path.
- BIOS/syslinux path (if still shipped).
### Hardware test matrix
- UEFI test on at least two hardware families (Intel + AMD).
- Confirm no external media required.
- Confirm first boot starts setup automatically.
### Negative tests
- OEM boot without `copytoram=y` -> safe abort with clear error.
- `MemTotal < 8 GiB` -> safe abort with clear error.
- Low `MemAvailable` -> safe abort with clear error.
- Runtime state not RAM-backed -> safe abort with clear error.
- Power interruption before installer starts -> deterministic reboot behavior.
- Power interruption during install -> recovery requires external media (documented).
---
## 6) Security hardening checklist
- No factory credentials exist; customer sets all passwords at first boot.
- Clear shell history and transient setup artifacts at end of install.
- Verify no secrets in logs shipped to customer.
- Regenerate host identity on first installed boot as needed:
- `machine-id`
- SSH host keys (if installed/enabled)
- Keep package signature verification and keyring handling intact.
---
## Rollout Plan
1. Implement OEM build flag, mode marker, boot config injection, and build assertions.
2. Implement copytoram, memory, and runtime-state guardrails in `.automated_script.sh`.
3. Add OEM warning text and typed destructive confirmation in configurator.
4. Add docs and operator checklist.
5. Run VM matrix, including negative tests.
6. Run hardware matrix.
7. Cut first OEM preproduction release for manufacturing pilot.
---
## Definition of Done
- `--oem` build exists and is documented.
- Device preloaded with OEM image boots directly to setup.
- Setup installs to internal disk without external media.
- Final installed system is LUKS-encrypted with customer-owned passphrase.
- OEM safety guardrails fail closed with actionable errors.
- Existing non-OEM ISO behavior remains unchanged.
- VM and hardware QA matrix pass.