Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
16 changes: 16 additions & 0 deletions linux-from-kernel-scratch/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM --platform=linux/amd64 ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
git vim make gcc libncurses-dev flex bison bc cpio \
libelf-dev libssl-dev syslinux isolinux dosfstools \
xorriso mtools grub-pc-bin grub-efi-amd64-bin bzip2 \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /build

COPY build.sh /build/
RUN chmod +x /build/build.sh

CMD ["/build/build.sh"]
45 changes: 45 additions & 0 deletions linux-from-kernel-scratch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Minimal Linux Distro

A bootable x86_64 Linux ISO built from scratch using Docker.

## What's Inside

- **Linux Kernel** - Latest mainline kernel (defconfig)
- **BusyBox** - Static userspace with common utilities
- **ISOLINUX** - Bootloader

## Files

```
├── Dockerfile # x86_64 Ubuntu build environment
├── build.sh # Full build (kernel + busybox + iso)
├── build-busybox-iso.sh # Partial build (reuses existing kernel)
└── output/
├── bzImage # Compiled kernel
├── initramfs.gz # Root filesystem
└── minimal-linux.iso # Bootable ISO (16MB)
```

## Build

```bash
# Build Docker image
docker build --platform linux/amd64 -t linux-builder .

# Full build (~25 min on ARM Mac)
docker run --platform linux/amd64 --rm -v "$(pwd)/output:/output" linux-builder

# If kernel exists, build only busybox + iso (~3 min)
docker run --platform linux/amd64 --rm \
-v "$(pwd)/output:/output" \
-v "$(pwd)/build-busybox-iso.sh:/build/build-busybox-iso.sh" \
linux-builder bash /build/build-busybox-iso.sh
```

## Test

```bash
qemu-system-x86_64 -cdrom output/minimal-linux.iso -m 512
```

Boots to a shell with `ls`, `vi`, `grep`, `awk`, `sed`, `bc`, and more.
81 changes: 81 additions & 0 deletions linux-from-kernel-scratch/build-busybox-iso.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/bin/bash
set -e

echo "=== Building BusyBox and ISO (kernel already built) ==="

# Check kernel exists
if [ ! -f /output/bzImage ]; then
echo "ERROR: bzImage not found in /output"
exit 1
fi
echo ">>> Found existing kernel: $(ls -lh /output/bzImage | awk '{print $5}')"

# Build BusyBox
echo ">>> Cloning BusyBox from GitHub mirror..."
git clone --depth 1 https://github.com/mirror/busybox.git busybox
cd busybox

echo ">>> Configuring BusyBox (static build)..."
make defconfig
sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
make oldconfig

echo ">>> Building BusyBox..."
make -j$(nproc) 2>&1 | tail -5

mkdir -p /output/initramfs
make CONFIG_PREFIX=/output/initramfs install
cd ..

# Create init script
echo ">>> Creating init script..."
cd /output/initramfs
cat > init << 'INITEOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev

echo "Welcome to Minimal Linux!"
echo "Type 'poweroff' to shutdown."
echo ""

exec /bin/sh
INITEOF
chmod +x init
mkdir -p proc sys dev

# Create initramfs
echo ">>> Creating initramfs..."
find . | cpio -o -H newc 2>/dev/null | gzip > /output/initramfs.gz
cd /output

# Create ISO
echo ">>> Creating bootable ISO..."
mkdir -p iso/boot/isolinux

cp /usr/lib/ISOLINUX/isolinux.bin iso/boot/isolinux/
cp /usr/lib/syslinux/modules/bios/ldlinux.c32 iso/boot/isolinux/
cp bzImage iso/boot/
cp initramfs.gz iso/boot/

cat > iso/boot/isolinux/isolinux.cfg << 'CFGEOF'
DEFAULT linux
LABEL linux
KERNEL /boot/bzImage
APPEND initrd=/boot/initramfs.gz
CFGEOF

xorriso -as mkisofs \
-o /output/minimal-linux.iso \
-b boot/isolinux/isolinux.bin \
-c boot/isolinux/boot.cat \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \
iso/

echo ""
echo "=== BUILD COMPLETE ==="
ls -lh /output/minimal-linux.iso
100 changes: 100 additions & 0 deletions linux-from-kernel-scratch/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/bash
set -e

echo "=== Building Minimal Linux Distro ==="

# 1. Build Linux Kernel (minimal config for faster build)
echo ">>> Cloning Linux kernel..."
git clone --depth 1 https://github.com/torvalds/linux.git
cd linux

echo ">>> Configuring kernel (minimal x86_64)..."
make defconfig
# Enable initramfs support
scripts/config --enable CONFIG_BLK_DEV_INITRD
scripts/config --enable CONFIG_RD_GZIP
scripts/config --enable CONFIG_RD_BZIP2
scripts/config --enable CONFIG_RD_LZMA
scripts/config --enable CONFIG_RD_XZ
scripts/config --enable CONFIG_RD_LZO
scripts/config --enable CONFIG_RD_LZ4
scripts/config --enable CONFIG_RD_ZSTD
make olddefconfig

echo ">>> Building kernel (this takes a while)..."
make -j$(nproc) bzImage 2>&1 | tail -20

mkdir -p /output
cp arch/x86/boot/bzImage /output/
cd ..

# 2. Build BusyBox
echo ">>> Cloning BusyBox..."
git clone --depth 1 https://github.com/mirror/busybox.git busybox
cd busybox

echo ">>> Configuring BusyBox (static build)..."
make defconfig
sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
make oldconfig

echo ">>> Building BusyBox..."
make -j$(nproc) 2>&1 | tail -10

mkdir -p /output/initramfs
make CONFIG_PREFIX=/output/initramfs install
cd ..

# 3. Create init script
echo ">>> Creating init script..."
cd /output/initramfs
cat > init << 'INITEOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev

echo "Welcome to Minimal Linux!"
echo "Type 'poweroff' to shutdown."
echo ""

exec /bin/sh
INITEOF
chmod +x init
mkdir -p proc sys dev

# 4. Create initramfs
echo ">>> Creating initramfs..."
find . | cpio -o -H newc 2>/dev/null | gzip > /output/initramfs.gz
cd /output

# 5. Create ISO with ISOLINUX
echo ">>> Creating bootable ISO..."
mkdir -p iso/boot/isolinux

cp /usr/lib/ISOLINUX/isolinux.bin iso/boot/isolinux/
cp /usr/lib/syslinux/modules/bios/ldlinux.c32 iso/boot/isolinux/
cp bzImage iso/boot/
cp initramfs.gz iso/boot/

cat > iso/boot/isolinux/isolinux.cfg << 'CFGEOF'
DEFAULT linux
LABEL linux
KERNEL /boot/bzImage
APPEND initrd=/boot/initramfs.gz
CFGEOF

xorriso -as mkisofs \
-o /output/minimal-linux.iso \
-b boot/isolinux/isolinux.bin \
-c boot/isolinux/boot.cat \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin \
iso/

echo ""
echo "=== BUILD COMPLETE ==="
ls -lh /output/minimal-linux.iso
echo "ISO ready at /output/minimal-linux.iso"
Binary file added linux-from-kernel-scratch/output/bzImage
Binary file not shown.
Binary file added linux-from-kernel-scratch/output/initramfs.gz
Binary file not shown.
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/arch
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/ash
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/base32
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/base64
Binary file not shown.
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/cat
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/chattr
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/chgrp
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/chmod
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/chown
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/conspy
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/cp
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/cpio
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/cttyhack
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/date
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/dd
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/df
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/dmesg
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/dumpkmap
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/echo
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/ed
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/egrep
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/false
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/fatattr
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/fdflush
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/fgrep
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/fsync
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/getopt
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/grep
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/gunzip
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/gzip
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/hostname
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/hush
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/ionice
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/iostat
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/ipcalc
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/kbd_mode
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/kill
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/link
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/linux32
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/linux64
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/ln
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/login
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/ls
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/lsattr
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/lzop
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/makemime
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/mkdir
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/mknod
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/mktemp
1 change: 1 addition & 0 deletions linux-from-kernel-scratch/output/initramfs/bin/more
Loading