OS Development
ApexOS Operating System is a Buildroot project. If you are new to embedded Linux builds, it is worth reading up on Buildroot first — the OS repository is a standard Buildroot external tree (buildroot-external/) layered on top of a Buildroot submodule.
Repository layout
.
├── buildroot/ # Buildroot (git submodule, project LTS branch)
├── buildroot-external/ # The ApexOS external tree
│ ├── configs/ # One <target>_defconfig per supported board
│ ├── board/ # Per-board-family files
│ │ ├── raspberrypi/ # rpi3-64, rpi4-64, rpi5-64
│ │ ├── pc/ # generic-x86-64, ova
│ │ └── arm-uefi/ # generic-aarch64
│ ├── kernel/ # Kernel config fragments (per kernel series)
│ ├── bootloader/ # Shared bootloader bits (U-Boot config, MBR images)
│ ├── ota/ # RAUC system config + bundle manifest templates
│ ├── package/ # Extra Buildroot packages (incl. the apexos package)
│ ├── rootfs-overlay/ # Files overlaid onto the target root filesystem
│ ├── patches/ # Global patches
│ └── scripts/ # post-build / post-image scripts
├── Makefile # Top-level convenience wrapper
└── scripts/enter.sh # Containerized build environment
After cloning, initialize the Buildroot submodule:
git submodule update --init
Building a target
The top-level Makefile wraps Buildroot. make help lists the supported targets — one per defconfig in buildroot-external/configs/:
rpi3_64 rpi4_64 rpi5_64 generic_aarch64 generic_x86_64 ova
To configure and build in one step:
make rpi4_64
This is equivalent to loading the defconfig and then building:
make rpi4_64_defconfig # falls through to Buildroot with BR2_EXTERNAL set
make
You can run only the configuration step with make <target>-config. Any Makefile target the wrapper does not know is forwarded to Buildroot (make menuconfig, make linux-rebuild, and so on — see make buildroot-help).
:::warning One output directory per target
The build output directory (output/ by default; override with O=<dir>) holds the configuration for a single target. If you switch targets, run make distclean first — the wrapper warns you if the output directory was configured for a different board.
:::
Containerized builds
Building needs a Linux host with Docker and loop-device support. scripts/enter.sh builds a Debian-based build container from the repository's Dockerfile, mounts the source tree and a cache directory (~/apexos-cache by default, holding downloads and ccache), and drops you into a shell where the make commands above work reproducibly. Run it as a regular user with sudo privileges.
Note that the image build itself needs Docker inside the build step: the data partition is assembled by loading the preinstalled container images (Supervisor, plug-ins, landing page) through a Docker-in-Docker instance.
Where images land
Buildroot places final artifacts in output/images/. For each target you get:
apexos_<board>-<version>.img.xz— the flashable disk image (e.g.apexos_rpi4-64-<version>.img.xz)- a RAUC OTA bundle for the same build, used for over-the-air and offline updates
- intermediate artifacts (
rootfs.erofs,data.ext4, boot files)
The ova target additionally produces .ova, .vmdk, .vhdx, .vdi (zipped), and .qcow2 (xz) virtual disk images.
Version numbers come from buildroot-external/meta (VERSION_MAJOR/VERSION_MINOR, plus an optional VERSION_SUFFIX for development builds).
Kernel and bootloader layout
Kernel configuration is assembled from shared fragments in buildroot-external/kernel/<series>/ (base config, Docker requirements, device support, wireless, …) plus a per-board-family kernel.config:
- Raspberry Pi family (
board/raspberrypi/): Raspberry Pi kernel fork pinned to a specific commit tarball, board device trees selected per target, sharedconfig.txt/cmdline.txt, and U-Boot boot scripts. The Pi 3 and Pi 4 boot through U-Boot; the Pi 5 uses the firmware'strybootslot mechanism, integrated with RAUC via a custom handler. - PC family (
board/pc/): mainline LTS kernel, GRUB on UEFI with an A/B-awaregrub.cfg(boot slot selection and automatic fallback after three failed attempts). Coversgeneric-x86-64andova. - ARM UEFI family (
board/arm-uefi/): mainline LTS kernel with GRUB on UEFI forgeneric-aarch64.
Each board directory has a meta file declaring its identity (board ID and name, bootloader type, kernel image file, partition table type, boot partition size) which drives the shared image-assembly scripts and RAUC compatibility string.
Build channels
The channel an image follows (dev, beta, or stable) is a Buildroot option of the apexos package. It decides which channel manifest is consulted for the preinstalled container image versions, which AppArmor profile set is fetched, and which channel the Supervisor's updater is seeded with. Development builds are published to the public build index at https://ota.apexinfosys.in/index.html.