- Shell 98.2%
- PHP 1.3%
- Dockerfile 0.5%
|
|
||
|---|---|---|
| .github/workflows | ||
| config | ||
| docs | ||
| scripts | ||
| .gitignore | ||
| AGENTS.md | ||
| claude.md | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| runit.sh | ||
mos_builder
What this is
Build system for creating the MOS boot image: a custom Alpine Linux x86_64 initramfs with my_init process management, embedded in a single vmlinuz.efi.
Features
- Alpine Linux miniroot as base system
- my_init process manager (complete OpenRC replacement)
- Rootless containers (Docker/Podman compatible)
- Boot-critical Rust components with musl static linking
- Aggressive optimization (strip + UPX compression)
- Dynamic firmware discovery via WHENCE + modinfo
- Runtime component delivery via S3 flists (built by mos_runtimes)
- Final output:
vmlinuz.efiwith embeddedinitramfs.cpio.xz
Quick Start
Prerequisites
The build runs entirely inside a container — you only need a container runtime on the host.
Host Requirements (for building)
| Tool | Required | Purpose |
|---|---|---|
podman or docker |
Yes | Container runtime for builds |
git |
Yes | Clone and manage repository |
Host Requirements (for testing)
| Tool | QEMU | cloud-hypervisor | Purpose |
|---|---|---|---|
qemu-system-x86_64 |
Yes | - | VM hypervisor |
cloud-hypervisor |
- | Yes | VM hypervisor |
qemu-img |
Yes | Yes | Create disk images |
screen |
- | Yes | Console attachment |
curl, jq |
- | Yes | cloud-hypervisor API |
sudo, ip |
Optional | Yes | TAP/bridge networking |
Ubuntu/Debian
# Minimal (build only)
sudo apt-get update
sudo apt-get install -y git podman
# With QEMU testing
sudo apt-get install -y git podman qemu-system-x86 qemu-utils
# With cloud-hypervisor testing
sudo apt-get install -y git podman qemu-utils screen curl jq iproute2
# Install cloud-hypervisor from releases: https://github.com/cloud-hypervisor/cloud-hypervisor/releases
Arch Linux
# Minimal (build only)
sudo pacman -S git podman
# With QEMU testing
sudo pacman -S git podman qemu-full
# With cloud-hypervisor testing
sudo pacman -S git podman qemu-img screen curl jq iproute2 cloud-hypervisor
Alpine Linux
# Minimal (build only)
apk add --no-cache git podman
# With QEMU testing
apk add --no-cache git podman qemu-system-x86_64 qemu-img
# With cloud-hypervisor testing
apk add --no-cache git podman qemu-img screen curl jq iproute2
# Install cloud-hypervisor from releases
Rootless Container Setup
For rootless Podman support (recommended):
# Configure subuid/subgid (if not already configured)
echo "$(whoami):100000:65536" | sudo tee -a /etc/subuid
echo "$(whoami):100000:65536" | sudo tee -a /etc/subgid
# Verify setup
podman system info
Build
# Clone the repository
git clone <repository-url>
cd mos_builder
# Make scripts executable
chmod +x scripts/build.sh scripts/clean.sh
# Build initramfs
./scripts/build.sh
# Output will be in dist/
ls -la dist/
# vmlinuz.efi - Kernel with embedded initramfs
# initramfs.cpio.xz - Standalone initramfs archive
Build Process
Phase 1: Environment Setup
- Create build directories
- Install build dependencies
- Setup Rust musl target
Phase 2: Alpine Base
- Download Alpine 3.22 miniroot
- Extract to initramfs directory
- Install packages from
config/packages.list - NO OpenRC installation
Phase 3: Component Building
- Parse
config/sources.conf - Download/clone sources to
components/ - Build Rust components with musl:
- my_init: Standard cargo build
- rfs: Standard cargo build
- mycelium: Build in
myceliumd/subdirectory - mosstorage: Build from the storage orchestration component for MOS
- Install binaries to initramfs
Phase 4: System Configuration
- Replace
/sbin/initwith my_init - Copy my_init configuration
- Setup module loading with dependency resolution
- Configure system services
Phase 5: Optimization
- Aggressive cleanup:
- Remove docs, man pages, locales
- Remove headers, development files
- Remove APK cache
- Binary optimization:
- Strip all executables and libraries
- UPX compress all binaries
- Size verification
Phase 6: Packaging
- Create
initramfs.cpio.xzwith XZ compression - Build kernel with embedded initramfs
- Generate
vmlinuz.efi(default kernel) - Generate versioned kernel:
vmlinuz-{VERSION}-{MY_INIT_HASH}.efi - Optionally upload versioned kernel to S3 (set
UPLOAD_KERNEL=true)
Testing
QEMU Testing
# Boot test with QEMU (default)
./runit.sh
# With custom parameters
./runit.sh --hypervisor qemu --memory 2048 --disks 3
cloud-hypervisor Testing
# Boot test with cloud-hypervisor
./runit.sh --hypervisor ch
# With disk reset
./runit.sh --hypervisor ch --reset --disks 5
Advanced Options
# See all options
./runit.sh --help
# Custom disk size and bridge
./runit.sh --disk-size 20G --bridge mosbr --disks 4
# Environment variables
HYPERVISOR=ch NUM_DISKS=5 ./runit.sh
Size Optimization
The build system achieves minimal size through:
Package Selection
- Minimal Alpine packages (~50MB target)
- No OpenRC or systemd
- Essential tools only
Binary Optimization
- strip: Remove debug symbols
- UPX: Maximum compression
- musl static linking: No runtime dependencies
Filesystem Cleanup
- Remove documentation
- Remove locales (except C)
- Remove development headers
- Remove package manager cache
Expected Sizes
- Base Alpine: ~5MB
- With packages: ~25MB
- With components: ~40MB
- After optimization: ~15-20MB
- Final initramfs.cpio.xz: ~8-12MB
GitHub Actions Integration
See GITHUB_ACTIONS.md for complete CI/CD setup.
Basic Workflow
name: Build Mycelium OS
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup rootless containers
run: |
echo "runner:100000:65536" | sudo tee -a /etc/subuid
echo "runner:100000:65536" | sudo tee -a /etc/subgid
- name: Build
run: ./scripts/build.sh
- name: Test
run: ./runit.sh --hypervisor qemu
Advanced Usage
Custom Components
Add custom components to config/sources.conf:
# Custom Git component
git:myapp:https://github.com/user/myapp:v1.0:build_myapp
# Custom release
release:mytool:https://releases.example.com/mytool-x86_64:v2.0:install_mytool
Implement build function in scripts/lib/components.sh:
function build_myapp() {
local name="$1"
local component_dir="$2"
# Custom build logic
export RUSTFLAGS="-C target-feature=+crt-static"
cargo build --release --target x86_64-unknown-linux-musl
# Install binary
cp target/x86_64-unknown-linux-musl/release/myapp "${INSTALL_DIR}/usr/bin/"
}
S3 Uploads (Kernel & RFS Flists)
Automatically upload build artifacts to S3-compatible storage:
Configuration
Create config/rfs.conf:
S3_ENDPOINT="https://s3.example.com:9000"
S3_REGION="us-east-1"
S3_BUCKET="mos"
S3_PREFIX="flists/mos_builder"
S3_ACCESS_KEY="YOUR_ACCESS_KEY"
S3_SECRET_KEY="YOUR_SECRET_KEY"
Upload Kernel
# Enable kernel upload
UPLOAD_KERNEL=true ./scripts/build.sh
# Custom kernel subpath (default: kernel)
KERNEL_SUBPATH=kernels UPLOAD_KERNEL=true ./scripts/build.sh
Uploaded files:
s3://{bucket}/{prefix}/kernel/vmlinuz-{VERSION}-{MY_INIT_HASH}.efi- Versioned kernels3://{bucket}/{prefix}/kernel/kernels.txt- Text index (one kernel per line)s3://{bucket}/{prefix}/kernel/kernels.json- JSON index with metadata
Index files: The build automatically generates and uploads index files listing all available kernels in the S3 bucket. This enables:
- Easy kernel selection in web UIs (dropdown menus)
- Programmatic access without S3 API listing
- Metadata like upload timestamp and kernel count (JSON format)
JSON index format:
{
"kernels": [
"vmlinuz-6.12.44-MyceliumOS-abc1234.efi",
"vmlinuz-6.12.44-MyceliumOS-def5678.efi"
],
"updated": "2025-01-04T12:00:00Z",
"count": 2
}
Upload RFS Flists
# Enable flist uploads
UPLOAD_MANIFESTS=true ./scripts/build.sh
Uploaded as:
s3://{bucket}/{prefix}/manifests/modules-{VERSION}.fls3://{bucket}/{prefix}/manifests/firmware-{TAG}.fl
Requirements
- MinIO Client (
mcliormc) must be installed - Valid S3 credentials in
config/rfs.conf
Container Builds
Build in isolated container:
# Build container image
podman build -t mos-builder .
# Run build in container
podman run --rm \
-v $(pwd):/workspace \
-w /workspace \
mos-builder \
./scripts/build.sh
Cross-Platform Support (totally untested)
The build system supports multiple architectures:
# Build for different targets
export RUST_TARGET="aarch64-unknown-linux-musl"
export ALPINE_ARCH="aarch64"
./scripts/build.sh
Troubleshooting
Common Issues
Build Failures
# Clean and retry
./scripts/clean.sh
./scripts/build.sh
# Check dependencies
./scripts/build.sh --check-deps
Container Issues
# Verify rootless setup
podman system info
# Reset user namespace
podman system reset
Rust Build Issues (inside dev container)
# Enter dev container first
./scripts/dev-container.sh shell
# Verify musl target
rustup target list --installed | grep musl
# Add if missing
rustup target add x86_64-unknown-linux-musl
Note: Rust toolchain issues are rare since the container image includes everything needed.
Debug Mode
# Enable verbose output
export DEBUG=1
./scripts/build.sh
Contributing
- Fork the repository
- Create feature branch
- Test thoroughly with both QEMU and cloud-hypervisor
- Ensure size optimization targets are met
- Submit pull request with detailed description
Development Workflow
# Setup development environment
./scripts/dev-container.sh start
# Run incremental build
./scripts/build.sh
# Test with QEMU
./runit.sh --hypervisor qemu
# Test with cloud-hypervisor
./runit.sh --hypervisor ch
What this repository contains
Project Structure
mos_builder/
├── config/
│ ├── my_init/ # my_init service definitions
│ │ ├── services/ # individual service files
│ │ └── my_init.conf # main my_init configuration
│ ├── packages.list # Alpine packages to install
│ ├── sources.conf # components to build (ThreeFold)
│ ├── kernel.config # Linux kernel configuration
│ └── modules.conf # kernel modules for boot
├── configs/ # existing configurations (migrated)
├── scripts/
│ ├── lib/
│ │ ├── docker.sh # container management
│ │ ├── alpine.sh # Alpine operations
│ │ ├── components.sh # source building
│ │ ├── initramfs.sh # assembly & optimization
│ │ └── kernel.sh # kernel building
│ ├── build.sh # main orchestrator
│ └── clean.sh # cleanup script
├── initramfs/ # build output (generated)
├── components/ # component sources (generated)
├── kernel/ # kernel source (generated)
└── dist/ # final artifacts (generated)
Related Repositories
MOS has a three-repo build infrastructure:
mos_config mos_runtimes mos_builder
(what to deploy) --> (builds runtime flists) --> (builds boot image)
- mos_builder (this repo): builds the boot image with boot-critical components (my_init, myfs, mosnet, mos_volmgr). Produces
vmlinuz.efi. - mos_runtimes: builds per-component flists for post-boot runtime binaries (mycelium, youki, hero_compute, hero_proc, my_hypervisor). Uploads to S3.
- mos_config: per-environment configuration (dev/testing/canary/production) — component versions, service templates, user provisioning.
Boot-Critical vs Runtime
| In initramfs (this repo) | Via flist (mos_runtimes) |
|---|---|
| my_init (PID 1 + supervisor) | mycelium (overlay network) |
| myfs (content-addressed FUSE) | youki (container runtime) |
| mosnet (network bootstrap) | my_hypervisor (VM management) |
| mos_volmgr (storage init) | hero_compute (compute orchestration) |
| hero_proc (process management) |
At boot, the runtime-fetch my_init service downloads a channel manifest from S3 and unpacks runtime binaries to /var/cache/bin/.
Configuration Files
Component Sources (config/sources.conf)
Define components to download and build:
# Format: TYPE:NAME:URL:VERSION:BUILD_FUNCTION[:EXTRA_OPTIONS]
# Git repositories (Rust components with musl)
git my_init https://forge.ourworld.tf/geomind_code/my_init.git development build_my_init
git:mycelium:https://github.com/threefoldtech/mycelium:0.6.1:build_mycelium
git:rfs:https://github.com/threefoldtech/rfs:development:build_rfs
# Pre-built releases
release:corex:https://github.com/threefoldtech/corex/releases/download/2.1.4/corex-2.1.4-amd64-linux-static:2.1.4:install_corex:rename=corex
Package List (config/packages.list)
Alpine packages to install (NO OpenRC):
# Core system
alpine-baselayout
busybox
musl
# Hardware detection & modules
eudev
eudev-hwids
kmod
# Networking
iproute2
ethtool
dhcpcd
# Filesystems
btrfs-progs
dosfstools
# Security & SSH
haveged
openssh-server
# Tools
zellij
tcpdump
bmon
Module Loading (config/modules.conf)
Kernel modules copied to initramfs for boot (one per line):
# Module loading specification for MOS Alpine initramfs
# Format: MODULE_NAME (one per line, comments start with #)
#
# These modules are copied to the initramfs for minimal boot support.
# After network is up, full firmware and modules are RFS-mounted at runtime.
# Storage
libata
ahci
nvme
# Networking
virtio_net
e1000
e1000e
igb
ixgbe
# USB/HID
xhci_pci
usbhid
my_init Configuration (config/my_init/)
Main config (config/my_init/my_init.conf)
log_level: debug
init:
- load-modules
- networking
- services
Service definitions (config/my_init/services/)
Services are migrated from existing configs/my_init/ directory with proper initialization order.
Role in the stack
mos_builder produces the boot image (vmlinuz.efi) that is the foundation of every MyceliumOS node. The initramfs embedded in this kernel contains the minimal set of boot-critical components required to bring a node from power-on to a state where it can download and run the full runtime stack.
The build pipeline is the first stage of a three-repo infrastructure:
- mos_config defines what to deploy (component versions, environment configs)
- mos_runtimes builds post-boot runtime binaries and packages them as flists uploaded to S3
- mos_builder (this repo) assembles the boot-critical initramfs and kernel
At boot, the runtime-fetch my_init service inside the initramfs downloads the channel manifest from S3 and unpacks runtime binaries to /var/cache/bin/. This separation keeps the boot image small and allows runtime components to be updated independently of the kernel.
It relates to:
- my_init — The PID 1 process manager embedded in the initramfs
- mos_runtimes — Supplies post-boot runtime binaries via S3 flists
- MyceliumOS — The operating system whose boot image is produced here
- ThreeFold Grid — The decentralized infrastructure platform where this technology was first deployed
Relation to ThreeFold
This technology is used within the ThreeFold ecosystem and was first deployed on the ThreeFold Grid. The component itself is designed as reusable infrastructure technology and should be understood by its technical function first, independent of any specific deployment.
Ownership
This repository is owned and maintained by TF-Tech NV, a Belgian company responsible for the development and maintenance of this technology.
License
This project is licensed under the Apache License 2.0 — see the LICENSE file for details.