Disclaimer: Nanas OS is an independent, community-led open-source project. It is not affiliated with, endorsed by, or sponsored by the Government of Malaysia or the Malaysia MADANI policy framework.
Note: This is a fork of upstream/project. It contains custom changes for Nanas OS use and is not intended for upstream contribution.
Nanas OS Builder is a specialized command-line tool designed to build lightweight Linux distributions optimized for low-end machines with pre-built AI stack capabilities. Using a simple toolchain, it creates mutable or immutable Nanas OS images from pre-built packages sourced from various OS distribution repositories.
Developed in Go, the tool specializes in building custom Nanas OS images optimized for efficient AI workload execution on resource-constrained hardware. The tool's versatile architecture also supports building images for other Linux distributions including Ubuntu, Wind River eLxr, Azure Linux, and Intel EMT.
- Overview
- Download Pre-built Images
- System Requirements
- Quick Start Guide
- Testing with the OS Raw Image
- Advanced Topics
- Configuration
- Operations Requiring Sudo Access
- Usage
- Image Template Format
- Template Examples
- Resources
- Legal
If you prefer to use pre-built Nanas OS images instead of building from source, you can download them directly:
-
Raw Image (Disk Image): Direct deployment to physical hardware or virtual machines
-
ISO Image (Installation Media): Bootable installation media for setting up Nanas OS
Note: These pre-built images are ready-to-use versions of Nanas OS with optimized configurations for AI workloads on resource-constrained hardware.
Recommended Operating System for Building: Ubuntu 24.04
Note: These requirements are for building Nanas OS images, not for running the final OS. Nanas Team has validated and recommends using Ubuntu OS version 24.04 for the build process. Other Linux distributions have not been validated. Future releases will include a containerized version for enhanced portability.
Target Hardware: The built Nanas OS is optimized for low-end machines and has been successfully tested on:
- 2017 Intel Kaby Lake PCs
- Other resource-constrained hardware with minimal system requirements
Note: The final Nanas OS images are designed to run efficiently on much lower specifications than what's required for building them.
For Windows users who want to run Nanas OS Builder in WSL:
Use the provided automated setup script to configure Ubuntu 24.04 in WSL with all required dependencies:
# Download and run the setup script
setup-wsl.batWhat the script does:
- Installs Ubuntu 24.04 in WSL (if not already installed)
- Sets up Go programming language (v1.25.5)
- Creates
/datadirectory for the project - Clones the repository to
/data/nanas-os-builder - Configures proper permissions and PATH variables
After running the script:
- The script will automatically launch WSL
- Navigate to the project directory:
cd /data/nanas-os-builder - Continue with step 3 of the Quick Start Guide
Note: If prompted to create a username/password during Ubuntu installation, complete the setup and return to the batch script window.
git clone https://github.com/yockgen/nanas-os-builder/
cd nanas-os-builder
git checkout $(git describe --tags --abbrev=0)Install Go programming language version 1.22.12 or later. See the Go installation instructions for your Linux distribution.
sudo go build -buildmode=pie -ldflags "-s -w" ./cmd/os-image-composersudo -E ./os-image-composer build --cache-dir ./cache/ -v image-templates/nanas24-x86_64-minimal-raw.yml 2>&1 | tee yockgen-nanas.txtls ./workspace/nanas-nanas24-x86_64/imagebuild/minimal/minimal-os-image-nanas-24.04.raw.gzNote: The
minimal-os-image-nanas-24.04.raw.gzfile is a compressed raw disk image containing the complete Nanas OS.
⚠️ Warning: Copy the raw image to another location before running this command if you need to preserve it.
sudo rm -rf ./tmp/ ./build ./cache/ ./workspace/The raw image file can be deployed on various platforms:
- Physical machines: Flash directly to a disk or USB drive for bare-metal installation
- Virtual Machines: Import into virtualization platforms (VirtualBox, VMware, etc.)
- QEMU: Boot directly using QEMU emulator
- Cloud instances: Deploy to cloud providers that support raw disk images
gzip -dc ./workspace/nanas-nanas24-x86_64/imagebuild/minimal/minimal-os-image-nanas-24.04.raw.gz > /data/raw/test-nanas-final.rawsudo qemu-system-x86_64 \
-machine q35 \
-m 2048 \
-cpu max \
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \
-drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS_4M.fd \
-device virtio-scsi-pci \
-drive if=none,id=drive0,file=test-nanas-final.raw,format=raw \
-device scsi-hd,drive=drive0 \
-netdev user,id=net0,hostfwd=tcp::2223-:22,hostfwd=tcp::8081-:80 \
-device virtio-net-pci,netdev=net0 \
-nographic \
-serial mon:stdioFor Windows WSL users:
# Install QEMU and setup permissions
sudo apt install qemu-system-x86 ovmf
sudo usermod -aG kvm $USER && newgrp kvm
sudo chmod 666 /dev/kvm
# Prepare VM files
cd /data/raw
chmod 777 test-nanas-final.raw
cp /usr/share/OVMF/OVMF_VARS_4M.fd ./my_vars.fd
chmod 644 ./my_vars.fd
# Run QEMU with GUI
qemu-system-x86_64 \
-machine q35 \
-m 4G \
-smp 4,cores=4,threads=1 \
-cpu host,migratable=no,+invtsc \
-accel kvm \
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \
-drive if=pflash,format=raw,file=./my_vars.fd \
-device virtio-scsi-pci \
-drive if=none,id=drive0,file=test-nanas-final.raw,format=raw,cache=none,aio=native \
-device scsi-hd,drive=drive0 \
-netdev user,id=net0,hostfwd=tcp::2223-:22,hostfwd=tcp::8081-:80 \
-device virtio-net-pci,netdev=net0 \
-vga virtio \
-display gtk,gl=onTroubleshooting: If no GUI appears, ensure X11 server is running on Windows or use WSLg (Windows 11 22H2+).
⚠️ Warning: Flashing this image will overwrite all existing data on the target device. Ensure you have selected the correct destination and have backed up any important data.
The ISO image is a bootable installation media that can be used to install Nanas OS on a physical machine or virtual machine. It provides a live installer environment for setting up the OS on a target disk.
Build the ISO image using the appropriate template:
# Using go run for development
go run ./cmd/os-image-composer/ build -v --cache-dir ./cache/ image-templates/nanas24-x86_64-minimal-iso.yml
# Or using the compiled binary
sudo -E ./os-image-composer build -v --cache-dir ./cache/ image-templates/nanas24-x86_64-minimal-iso.ymlNote: ISO images include
installer-gui.pyas the graphical installer, which is automatically bundled during the build process.
The ISO image can be used to install Nanas OS to a virtual disk. This example creates a 20GB installation target:
# Create a virtual disk for installation
qemu-img create -f qcow2 os-install-disk.qcow2 20G
# Boot from ISO and install to the virtual disk
sudo qemu-system-x86_64 \
-m 8192 \
-enable-kvm \
-cpu host \
-bios /usr/share/OVMF/OVMF_CODE.fd \
-device virtio-scsi-pci \
-drive if=none,id=drive0,file=minimal-os-image-nanas-24.04.iso,format=raw \
-device scsi-hd,drive=drive0 \
-drive if=none,id=drive1,file=os-install-disk.qcow2,format=qcow2 \
-device scsi-hd,drive=drive1 \
-display gtk \
-serial mon:stdioParameters explained:
-m 8192: Allocates 8GB of RAM (adjust based on your system)-enable-kvm: Enables hardware virtualization for better performance-cpu host: Uses host CPU features for optimal performance-bios /usr/share/OVMF/OVMF_CODE.fd: Uses UEFI firmwaredrive0: The ISO image (boot media)drive1: The virtual disk where the OS will be installed-display gtk: Shows a graphical window-serial mon:stdio: Provides console access via terminal
Note: After installation completes, you can boot from the installed disk by removing the ISO drive or changing the boot order.
For development and testing purposes:
# Build the tool
go build -buildmode=pie -ldflags "-s -w" ./cmd/os-image-composer
# Or run it directly
go run ./cmd/os-image-composer --helpNote: Development builds using
go buildshow default version information (e.g.,Version: 0.1.0,Build Date: unknown). This is expected during development.
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")
COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
BUILD_DATE=$(date -u '+%Y-%m-%d')
go build -buildmode=pie \
-ldflags "-s -w \
-X 'github.com/open-edge-platform/os-image-composer/internal/config/version.Version=$VERSION' \
-X 'github.com/open-edge-platform/os-image-composer/internal/config/version.Toolname=Image-Composer' \
-X 'github.com/open-edge-platform/os-image-composer/internal/config/version.Organization=Open Edge Platform' \
-X 'github.com/open-edge-platform/os-image-composer/internal/config/version.BuildDate=$BUILD_DATE' \
-X 'github.com/open-edge-platform/os-image-composer/internal/config/version.CommitSHA=$COMMIT'" \
./cmd/os-image-composerFor production and release builds with reproducible builds:
# Default build (uses latest Git tag for version)
earthly +build
# Build with custom version metadata
earthly +build --VERSION=1.2.0# Build with default parameters (latest git tag, amd64)
earthly +deb
# Build with custom version and architecture
earthly +deb --VERSION=1.2.0 --ARCH=amd64
# Build for ARM64
earthly +deb --VERSION=1.0.0 --ARCH=arm64The package is created in the dist/ directory as os-image-composer_<VERSION>_<ARCH>.deb.
# Install using apt (recommended - automatically resolves dependencies)
sudo apt install <PATH TO FILE>/os-image-composer_1.0.0_amd64.deb
# Or using dpkg (requires manual dependency installation)
sudo apt-get update
sudo apt-get install -y bash coreutils unzip dosfstools xorriso grub-common
sudo dpkg -i dist/os-image-composer_1.0.0_amd64.deb
# Optionally install bootstrap tools:
sudo apt-get install -y mmdebstrap || sudo apt-get install -y debootstrap# Check if package is installed
dpkg -l | grep os-image-composer
# View installed files
dpkg -L os-image-composer
# Verify the binary works
os-image-composer versionThe Debian package installs:
- Binary:
/usr/local/bin/os-image-composer- Main executable file - Configuration:
/etc/os-image-composer/- Default configuration and OS variant configurations/etc/os-image-composer/config.yml- Global configuration with system paths/etc/os-image-composer/config/- OS variant configuration files
- Examples:
/usr/share/os-image-composer/examples/- Sample image templates - Documentation:
/usr/share/doc/os-image-composer/- README, LICENSE, and CLI specification - Cache Directory:
/var/cache/os-image-composer/- Package cache storage
Required Dependencies:
bash- Shell for script executioncoreutils- Core GNU utilitiesunzip- Archive extraction utilitydosfstools- FAT filesystem utilitiesxorriso- ISO image creation toolgrub-common- Bootloader utilities
Recommended Dependencies:
mmdebstrap- Debian bootstrap tool (preferred, version 1.4.3+ required)debootstrap- Alternative Debian bootstrap tool
Important:
mmdebstrapversion 0.8.x (included in Ubuntu 22.04) has known issues. For Ubuntu 22.04 users, you must installmmdebstrapversion 1.4.3+ manually.
# Remove the package but keep configuration files
sudo dpkg -r os-image-composer
# Remove the package and configuration files
sudo dpkg --purge os-image-composerBefore composing an OS image, install additional prerequisites:
Required Tools:
-
ukify- Combines kernel, initrd, and UEFI boot stub to create signed Unified Kernel Images (UKI)- Ubuntu 23.04+:
sudo apt install systemd-ukify - Ubuntu 22.04 and earlier: Must be installed manually from systemd source
- See detailed ukify installation instructions
- Ubuntu 23.04+:
-
mmdebstrap- Downloads and installs Debian packages to initialize a chroot- Ubuntu 23.04+: Automatically installed with the Debian package (version 1.4.3+)
- Ubuntu 22.04: The version in repositories (0.8.x) has known bugs
- Required: Manually install version 1.4.3+. See mmdebstrap installation instructions
- Alternative: Can use
debootstrapfor Debian-based images
# Build an image from template
sudo -E ./os-image-composer build image-templates/azl3-x86_64-edge-raw.yml
# If installed via Debian package, use system paths:
sudo os-image-composer build /usr/share/os-image-composer/examples/azl3-x86_64-edge-raw.yml
# Validate a template:
./os-image-composer validate image-templates/azl3-x86_64-edge-raw.ymlAfter the image is built, check your output directory:
/os-image-composer/tmp/os-image-composer/azl3-x86_64-edge-raw/imagebuild/Minimal_Raw
The OS Image Composer tool supports global configuration files for setting tool-level parameters that apply across all image builds.
The tool searches for configuration files in the following order:
os-image-composer.yaml(current directory)os-image-composer.yml(current directory).os-image-composer.yaml(hidden file in current directory)~/.os-image-composer/config.yaml(user home directory)~/.config/os-image-composer/config.yaml(XDG config directory)/etc/os-image-composer/config.yaml(system-wide)
# Core tool settings
workers: 12 # Number of concurrent download workers (1-100, default: 8)
cache_dir: "/var/cache/os-image-composer" # Package cache directory (default: ./cache)
work_dir: "/tmp/os-image-composer" # Working directory for builds (default: ./workspace)
temp_dir: "" # Temporary directory (empty = system default)
# Logging configuration
logging:
level: "info" # Log level: debug, info, warn, error (default: info)# Create a new configuration file
./os-image-composer config init
# Create configuration file at specific location
./os-image-composer config init /path/to/config.yaml
# Show current configuration
./os-image-composer config show
# Use specific configuration file
./os-image-composer --config /path/to/config.yaml build template.ymlThe OS Image Composer performs several system-level operations that require elevated privileges (sudo access).
The following system directories require root access for OS Image Composer operations:
/etc/directory operations: Writing system configuration files, modifying network configurations, updating system settings/dev/device access: Block device operations, loop device management, and hardware access/sys/filesystem access: System parameter modification and kernel interface access/proc/filesystem modification: Process and system state changes/boot/directory: Boot loader and kernel image management/var/system directories: System logs, package databases, and runtime state/usr/sbin/and/sbin/: System administrator binaries
OS Image Composer typically requires sudo access for:
- Block device management: Creating loop devices, partitions, and filesystem
- Mount/unmount operations: Mounting filesystems and managing mount points
- Chroot environment setup: Creating and managing isolated build environments
- Package installation: System-wide package management operations
- Boot configuration: Installing bootloaders and managing EFI settings
- Security operations: Secure boot signing and cryptographic operations
# Show help
./os-image-composer --help
# Build command with template file as positional argument
sudo -E ./os-image-composer build image-templates/azl3-x86_64-edge-raw.yml
# Override config settings with command-line flags
sudo -E ./os-image-composer build --workers 16 --cache-dir /tmp/cache image-templates/azl3-x86_64-edge-raw.yml
# Validate a template file against the schema
./os-image-composer validate image-templates/azl3-x86_64-edge-raw.yml
# Display version information
./os-image-composer version
# Install shell completion for your current shell
./os-image-composer completion installBuilds a Linux distribution image based on the specified image template file:
sudo -E ./os-image-composer build [flags] TEMPLATE_FILEFlags:
--workers, -w: Number of concurrent download workers (overrides the configuration file)--cache-dir, -d: Package cache directory (overrides the configuration file)--work-dir: Working directory for builds (overrides the configuration file)--verbose, -v: Enable verbose output--config: Path to the configuration file--log-level: Log level (debug, info, warn, and error)--log-file: Override the log file path defined in the configuration
Example:
sudo -E ./os-image-composer build --workers 12 --cache-dir ./package-cache image-templates/azl3-x86_64-edge-raw.ymlManages the global configuration:
# Show current configuration
./os-image-composer config show
# Initialize new configuration file
./os-image-composer config init [config-file]Validates a YAML template file against the schema without building an image:
./os-image-composer validate TEMPLATE_FILEDisplays the tool's version number, build date, and Git commit SHA:
./os-image-composer versionGenerates and installs shell completion scripts for various shells.
Prerequisites: The os-image-composer binary must be accessible in your system's $PATH.
# Generate completion script for bash (output to stdout)
os-image-composer completion bash
# Generate completion script for other shells
os-image-composer completion zsh
os-image-composer completion fish
os-image-composer completion powershell# Auto-detect shell and install completion file
os-image-composer completion install
# Specify shell type
os-image-composer completion install --shell bash
os-image-composer completion install --shell zsh
os-image-composer completion install --shell fish
os-image-composer completion install --shell powershell
# Force overwrite existing completion files
os-image-composer completion install --forceBash:
# Add to your ~/.bashrc
echo "source ~/.bash_completion.d/os-image-composer.bash" >> ~/.bashrc
source ~/.bashrcZsh:
# Ensure completion directory is in fpath (add to ~/.zshrc if needed)
echo 'fpath=(~/.zsh/completion $fpath)' >> ~/.zshrc
source ~/.zshrcFish: (Works automatically after restart)
PowerShell:
# May need to allow script execution
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
. $PROFILETest the completion:
os-image-composer [TAB]
os-image-composer b[TAB]
os-image-composer build --[TAB]Written in YAML format, templates define the requirements for building an OS image. The template structure enables you to define key parameters, such as the OS distribution, version, architecture, software packages, output format, and kernel configuration.
image:
name: azl3-x86_64-edge
version: "1.0.0"
target:
os: azure-linux # Target OS name
dist: azl3 # Target OS distribution
arch: x86_64 # Target OS architecture
imageType: raw # Image type: raw, iso
systemConfigs:
- name: edge
description: Default configuration for edge image
# Package Configuration
packages:
# Additional packages beyond the base system
- openssh-server # Remote access
- docker-ce # Container runtime
- vim # Text editor
- curl # HTTP client
- wget # File downloader
# Kernel Configuration
kernel:
version: "6.12"
cmdline: "quiet splash"Basic image identification and metadata:
name: Name of the resulting imageversion: Version for tracking and naming
Defines the target OS and image configuration:
os: Target OS (azure-linux,emt, andelxr)dist: Distribution identifier (azl3,emt3, andelxr12)arch: Target architecture (x86_64andaarch64)imageType: Output format (rawandiso)
Array of system configurations that define what goes into the image:
name: Configuration namedescription: Human-readable descriptionpackages: List of packages to include in the OS buildkernel: Kernel configuration with version and command-line parameters
| OS | Distribution | Version | Provider |
|---|---|---|---|
| azure-linux | azl3 | 3 | AzureLinux3 |
| emt | emt3 | 3.0 | EMT3.0 |
| wind-river-elxr | elxr12 | 12 | eLxr12 |
| ubuntu | ubuntu24 | ubuntu24 | |
| nanas | nanas24 | nanas24 |
cloud-init: For initializing cloud instancespython3: The Python 3 programming language interpreterrsyslog: A logging system for Linux OSopenssh-server: SSH server for remote accessdocker-ce: Docker container runtime
image:
name: minimal-edge
version: "1.0.0"
target:
os: azure-linux
dist: azl3
arch: x86_64
imageType: raw
systemConfigs:
- name: minimal
description: Minimal edge device configuration
packages:
- openssh-server
- ca-certificates
kernel:
version: "6.12"
cmdline: "quiet"image:
name: dev-environment
version: "1.0.0"
target:
os: azure-linux
dist: azl3
arch: x86_64
imageType: raw
systemConfigs:
- name: development
description: Development environment with tools
packages:
- openssh-server
- git
- docker-ce
- vim
- curl
- wget
- python3
kernel:
version: "6.12"
cmdline: "quiet splash"image:
name: emt-edge-device
version: "1.0.0"
target:
os: emt
dist: emt3
arch: x86_64
imageType: raw
systemConfigs:
- name: edge
description: Edge Microvisor Toolkit configuration
packages:
- openssh-server
- docker-ce
- edge-runtime
- telemetry-agent
kernel:
version: "6.12"
cmdline: "quiet splash systemd.unified_cgroup_hierarchy=0"- Run
./os-image-composer --helpfor all commands and options - CLI Specification and Reference
- Complete Documentation
- Build Process Documentation
- Creating and Reusing Image Templates
See License.