A minimal, customizable Linux distribution built from scratch using the Linux kernel, BusyBox, and Syslinux bootloader. This project demonstrates how to build a bootable Linux system with full control over every component.
- Features
- Prerequisites
- Quick Start
- Building from Source
- Usage
- Project Structure
- Configuration
- Advanced Usage
- Troubleshooting
- Contributing
- License
- Minimal footprint: Only essential components included
- From scratch: Built directly from kernel and BusyBox sources
- Multi-stage Docker build: Optimized build process with caching
- Bootable ISO: Creates a bootable ISO image
- Custom init system: Simple, transparent init process
- QEMU ready: Easy testing with QEMU emulator
- Configurable: Customize kernel and BusyBox configurations
- Fast builds: Parallel compilation with caching
- Docker 20.10 or later
- Docker Compose (optional)
- 4GB free disk space
- 2GB RAM minimum
-
Linux system (Debian/Ubuntu recommended)
-
Build tools:
gcc,make,bison,flex -
Additional packages:
sudo apt-get install build-essential libncurses-dev bison flex \ libssl-dev libelf-dev bc cpio git wget curl syslinux \ dosfstools genisoimage qemu-system-x86
-
Clone the repository
git clone https://github.com/ehsanghaffar/handbuilt-linux.git cd handbuilt-linux -
Build the distribution
docker build -t handbuilt-linux . -
Extract the ISO
docker run --rm handbuilt-linux cat /distro/output.iso > output.iso -
Test with QEMU
qemu-system-x86_64 -cdrom output.iso -m 512M
docker-compose up --buildThe multi-stage Dockerfile handles all build steps:
# Build the complete image
docker build -t handbuilt-linux .
# Or build specific stages
docker build --target kernel-builder -t linux-kernel .
docker build --target busybox-builder -t busybox-build .
docker build --target iso-builder -t linux-iso .# Extract ISO
docker run --rm handbuilt-linux cat /distro/output.iso > output.iso
# Extract kernel
docker run --rm handbuilt-linux cat /distro/bzImage > bzImage
# Extract initramfs
docker run --rm handbuilt-linux cat /distro/initramfs > initramfs# Replace /dev/sdX with your USB device (BE CAREFUL!)
sudo dd if=output.iso of=/dev/sdX bs=4M status=progress
sudo syncBoot from ISO:
qemu-system-x86_64 -cdrom output.iso -m 512MBoot from kernel and initramfs directly:
qemu-system-x86_64 \
-kernel bzImage \
-initrd initramfs \
-append "console=ttyS0" \
-nographic \
-m 512MWith networking:
qemu-system-x86_64 \
-cdrom output.iso \
-m 512M \
-netdev user,id=net0 \
-device e1000,netdev=net0Use the enhanced build.sh script to create a bootable disk image:
# Basic usage
./build.sh
# Custom size
./build.sh --size 100
# Custom output name
./build.sh --output my-boot.img
# Verbose output
./build.sh --verbose
# Show help
./build.sh --helpOnce booted, you have access to BusyBox utilities:
# List all available commands
busybox --list
# File operations
ls, cat, cp, mv, rm, mkdir, rmdir, touch
# System utilities
ps, top, free, df, mount, umount, hostname
# Network utilities
ifconfig, ping, wget, nc
# Text processing
grep, sed, awk, sort, uniq, head, tailhandbuilt-linux/
βββ Dockerfile # Multi-stage Docker build
βββ docker-compose.yml # Docker Compose configuration
βββ Makefile # Build automation
βββ README.md # This file
βββ LICENSE # Project license
βββ .gitignore # Git ignore rules
β
βββ build.sh # Boot image builder script
βββ init.sh # Init system script (PID 1)
βββ syslinux.cfg # Bootloader configuration
β
βββ linux.config # Linux kernel configuration
βββ busybox.config # BusyBox configuration
β
βββ scripts/ # Helper scripts
β βββ test.sh # Testing script
β βββ extract.sh # Extract artifacts from Docker
β βββ clean.sh # Cleanup build artifacts
β
βββ docs/ # Additional documentation
β βββ BUILDING.md # Detailed build instructions
β βββ CUSTOMIZING.md # Customization guide
β βββ TROUBLESHOOTING.md # Common issues and solutions
β
βββ .github/
βββ workflows/
βββ build.yml # CI/CD pipelineTo customize the kernel:
# Start configuration menu
docker run -it --rm -v $(pwd):/work handbuilt-linux bash
cd /opt/mydistro/linux
make menuconfig
# Save configuration
cp .config /work/linux.configTo customize BusyBox:
# Start configuration menu
docker run -it --rm -v $(pwd):/work handbuilt-linux bash
cd /opt/mydistro/busybox
make menuconfig
# Save configuration
cp .config /work/busybox.configModify init.sh to customize:
- Hostname
- Mounted filesystems
- Network configuration
- Startup services
- Environment variables
Modify syslinux.cfg to customize:
- Boot timeout
- Kernel parameters
- Boot menu options
- Default boot entry
Add custom software to the initramfs:
# In Dockerfile, add after BusyBox installation:
RUN cd /build/initramfs && \
wget https://example.com/package.tar.gz && \
tar xzf package.tar.gz && \
rm package.tar.gzBuild for different architectures:
# ARM64
docker build --build-arg ARCH=arm64 -t handbuilt-linux-arm64 .
# ARM
docker build --build-arg ARCH=arm -t handbuilt-linux-arm .Mount a persistent volume:
qemu-system-x86_64 \
-cdrom output.iso \
-m 512M \
-drive file=data.img,format=rawExtract kernel and initramfs for network booting:
# Extract files
docker run --rm handbuilt-linux cat /distro/bzImage > /tftpboot/bzImage
docker run --rm handbuilt-linux cat /distro/initramfs > /tftpboot/initramfs
# Configure PXE
cat > /tftpboot/pxelinux.cfg/default << EOF
DEFAULT linux
LABEL linux
KERNEL bzImage
APPEND initrd=initramfs
EOFBuild fails with "out of space" error:
# Increase Docker disk space or clean up
docker system prune -aQEMU shows black screen:
# Use serial console
qemu-system-x86_64 -cdrom output.iso -nographicKernel panic on boot:
# Check initramfs was created correctly
file initramfs
# Should show: "gzip compressed data"Permission denied when mounting:
# Run build.sh with sudo
sudo ./build.shEnable verbose logging:
# Build script
./build.sh --verbose
# QEMU with debug output
qemu-system-x86_64 -cdrom output.iso -d guest_errors,cpu_resetContributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Linux Kernel - The core of the operating system
- BusyBox - The Swiss Army Knife of Embedded Linux
- Syslinux - Lightweight bootloader
- QEMU - Emulator for testing
- Create an issue for bug reports
- Start a discussion for questions
- Check existing issues before creating new ones