OnixOS:Building From Scratch
Building OnixOS
This document covers the complete build lifecycle of the OnixOS Build System — from environment setup and package repository builds to ISO creation, syncing, Docker-based builds, and live build monitoring.
Prerequisites
The build system runs on Arch Linux (or an Arch-based environment). The following packages are required for ISO builds and are installed automatically by build.py:
| Package | Purpose |
|---|---|
archiso |
Core ISO creation tool (mkarchiso)
|
base-devel |
Compiler toolchain |
arch-install-scripts |
pacstrap, arch-chroot
|
squashfs-tools |
SquashFS filesystem creation |
dosfstools |
FAT filesystem creation |
syslinux |
Bootloader |
git / git-lfs |
Source fetching |
rsync |
File synchronisation |
go |
Go language toolchain |
nasm |
Assembler |
ninja |
Build system |
gperf |
Hash function generator |
imagemagick |
Image processing |
python-sphinx / xmlto |
Documentation toolchain |
gnome-shell / qtcreator |
Desktop environment build deps |
sudo |
Privilege escalation |
For repository builds the system additionally uses makepkg (included in base-devel) and the AUR snapshot endpoint:
https://aur.archlinux.org/cgit/aur.git/snapshot
Project Structure
onix-build-system/ ├── build.py # Main build entry point ├── clean.py # Cleans output/ and mounts ├── watcher.py # Terminal build status monitor ├── qemu.py # Launch built ISO in QEMU ├── Makefile # Convenience make targets ├── Dockerfile # Build container image ├── entrypoint.sh # Docker entrypoint ├── docker-compose.yml # Dev shell container ├── docker-compose.iso.yml # Automated ISO build container ├── docker-compose.repos.yml # Automated repo build container ├── onixos/ │ ├── iso.py # ISO build logic (mkarchiso wrapper) │ ├── pkgbuild.py # PKGBUILD / .SRCINFO parser │ ├── proc.py # Subprocess wrapper with logging │ └── repository.py # Repository build logic ├── sources/ │ ├── packages/ # Local package sources (PKGBUILD) │ ├── profiles/ # archiso profiles (core, gnome, xfce, icewm, security) │ ├── packages.list # Local packages to build │ ├── aur.list # AUR packages to build │ ├── profiles.list # ISO profiles to build │ ├── sync/ # Repo upload config │ │ ├── sourceforge.conf │ │ └── local.conf │ └── isosync/ # ISO upload config │ ├── sourceforge.conf │ └── local.conf ├── output/ # All build artefacts (generated) └── logs/ # Build logs (generated)
Build Commands
All commands must be run from the repository root.
Full Build
Builds all repositories and all ISO profiles in sequence:
sudo python build.py
Repository Build
Builds the onix-base (local packages) and onix-aur (AUR packages) repositories:
python build.py repos
The build process:
- Installs build dependencies via
pacman. - Builds local packages listed in
sources/packages.listand generates theonix-baserepo underoutput/base/. - Downloads AUR snapshots for packages listed in
sources/aur.list, builds them, and generates theonix-aurrepo underoutput/aur/.
ISO Build
Builds an ISO image for every profile listed in sources/profiles.list:
sudo python build.py iso
The build process per profile:
- Installs ISO build dependencies via
pacman. - Unmounts any stale mounts from a previous failed build inside the work directory.
- Cleans the work directory (
output/iso/<profile>/work). - Runs
mkarchisowith the matching profile undersources/profiles/<profile>/. - Writes the finished
.isofile tooutput/iso/<profile>/output/.
The underlying mkarchiso command:
sudo mkarchiso -C "sources/profiles/<profile>/pacman.conf" \
-v \
-w "output/iso/<profile>/work/" \
-o "output/iso/<profile>/output" \
-L "ONIXOS" \
"sources/profiles/<profile>"
Upload / Sync
Uploads built repositories to the configured remote server(s):
python build.py upload
Uploads built ISO images:
python build.py iso-sync
Both commands read from the relevant *.conf files under sources/sync/ and sources/isosync/ respectively (see Sync Configuration).
Make Targets
make # clean → repos → iso (full build) make clean # Remove output artefacts and unmount make repos # Repository build only make iso # ISO build only make docker_build # Build the Docker image make docker_publish # Push image to registry (olproject/buildkit) make docker_pull # Pull image from registry make docker_shell # Open interactive shell in container make docker_iso_build # Run ISO build inside Docker, copy output locally make docker_repo_build # Run repo build inside Docker, copy output locally
Docker Builds
The Docker image is based on archlinux and ships with all build dependencies pre-installed. The image tag is olproject/buildkit.
Building the Image
docker build . -t olproject/buildkit # or via make: make docker_build
ISO Build via Docker
docker-compose -f docker-compose.iso.yml up --abort-on-container-exit --build docker cp buildkit:/home/buildkit/builder/output/. ./output/ docker cp buildkit:/home/buildkit/builder/logs/. ./logs/ docker rm buildkit # or via make: make docker_iso_build
Repository Build via Docker
docker-compose -f docker-compose.repos.yml up --abort-on-container-exit --build docker cp buildkit:/home/buildkit/builder/output/. ./output/ docker cp buildkit:/home/buildkit/builder/logs/. ./logs/ docker rm buildkit # or via make: make docker_repo_build
Interactive Shell
Starts a persistent container with output and logs mounted as volumes, useful for manual inspection or debugging:
docker-compose up -d docker exec -it buildkit bash # or via make: make docker_shell
The container mounts:
./output/→/home/buildkit/builder/output./logs/→/home/buildkit/builder/logs
Profiles
ISO profiles are listed in sources/profiles.list, one per line. Each profile corresponds to a directory under sources/profiles/ that contains a complete archiso profile (including pacman.conf, packages.x86_64, airootfs/, etc.).
Available profiles:
| Profile | Description |
|---|---|
core |
Minimal base system |
gnome |
GNOME desktop environment |
xfce |
Xfce desktop environment |
icewm |
IceWM lightweight desktop |
security |
Security-focused variant |
To build only a specific profile, edit sources/profiles.list temporarily or call ISO.mkarchiso() directly.
Packages
Local Packages (onix-base)
Defined in sources/packages.list. Sources live under sources/packages/<name>/:
| Package | Purpose |
|---|---|
olang |
OnixOS language runtime |
onix-base |
Base system metapackage |
onix-graphics |
Graphics stack |
onix-meta |
Meta package |
calamares-onix |
Graphical installer |
linux-onix |
OnixOS kernel |
plymouth-onix-boot |
Boot splash screen |
AUR Packages (onix-aur)
Defined in sources/aur.list. Downloaded from the AUR snapshot endpoint at build time. Output goes to output/aur/.
Sync Configuration
Both repository and ISO sync use SSH (rsync over SSH). Configuration files follow the standard configparser INI format.
Repository Sync
Config files read by build.py upload (both are used if they exist):
sources/sync/sourceforge.conf— SourceForge remotesources/sync/local.conf— Local/internal server
Example:
[sync] server = frs.sourceforge.net user = olproject path = /home/frs/project/onixos/Repo port = 22 keyfile = /home/ted/.ssh/id_ed25519
Uploads output/base/repo → <path>/base and output/aur/repo → <path>/aur.
ISO Sync
Config files read by build.py iso-sync:
sources/isosync/sourceforge.confsources/isosync/local.conf
Uploads output/iso/<profile>/output → <path>/ISO for each profile.
Debug Mode
Append -d to iso or repos subcommands to stream stdout/stderr to the terminal in real time:
sudo python build.py iso -d python build.py repos -d
Without -d, command output is only written to the log files in logs/.
Build Watcher
watcher.py provides a live terminal dashboard that tracks ISO and repository build status, active mounts, and recent log output. It refreshes every 3 seconds.
Standalone (curses UI):
python watcher.py
Press q or Esc to exit.
Attached to a build (GUI overlay):
sudo python build.py iso -gui python build.py repos -gui
The -gui flag starts the watcher in a background thread alongside the build process and stops it automatically when the build finishes.
What the watcher shows:
- ISO Builds — profile name, ISO filename, file size, build timestamp, and status.
- Repositories — repo name, package count, DB update timestamp, and status.
- Active Mounts — any loop/overlay mounts still active inside
output/. - Last Build Log — last 6 lines of
logs/isobuild.logwith colour-coded errors and warnings.
Testing with QEMU
Launch a built ISO in a QEMU virtual machine for quick validation:
python qemu.py <path-to-iso>
Example:
python qemu.py output/iso/gnome/output/onixos-gnome-x86_64.iso
VM parameters (hardcoded defaults):
| Parameter | Value |
|---|---|
| RAM | 4 GB |
| CPU | x86_64 |
| Cores | 1 |
| VGA | qxl |
| Network | User-mode (NAT) |
| Boot | CD-ROM |
qemu-system-x86_64 must be installed and available in PATH.
Cleaning the Build
Removes all build artefacts, clears the pacman package cache, unmounts any stale mounts, and deletes log files:
sudo python clean.py # or via make: make clean
What clean.py does in order:
- Reads
/proc/mountsand unmounts (withumount -l) anything mounted insideoutput/, deepest paths first. - Clears the pacman package cache:
find /var/cache/pacman/pkg/ -name '*.pkg.tar.*' -delete. - Removes all
logs/*.logfiles. - Removes all contents of
output/withsudo rm -rfv output/*.
Output Structure
After a successful full build:
output/
├── base/
│ └── repo/ # onix-base repository (.pkg.tar.zst, .db, .files)
├── aur/
│ └── repo/ # onix-aur repository
└── iso/
├── core/
│ ├── work/ # mkarchiso working directory (temporary)
│ └── output/ # core-*.iso
├── gnome/
│ ├── work/
│ └── output/ # gnome-*.iso
├── xfce/
├── icewm/
└── security/
Logs
Build logs are written to logs/ in the repository root:
| Log file | Contents |
|---|---|
logs/isobuild.log |
mkarchiso command output, timestamps, exit codes
|
logs/pacinst.log |
pacman dependency installation output
|
logs/clean.log |
Clean operation output |
Each log entry records the command, date/time, exit code, stderr, and stdout.
