# Building a Minimal Linux Distro from Scratch

**Author:** kelexine  
**Date:** 2025-12-05  
**Category:** Linux  
**Tags:** Linux, OS Development, Kernel, System Design  
**URL:** https://kelexine.is-a.dev/blog/minimal-linux-distro

---

# Why Build Your Own Distro?

"Use Arch, btw." "Just install Ubuntu." Sure, those work. But have you ever wondered what actually happens when you boot a Linux system? Building your own distro answers that question definitively.

## What We're Building

A minimal bootable Linux system with:
- Custom compiled kernel
- BusyBox for core utilities
- A simple init process
- Bootable from USB

Total size: Under 20MB.

## Prerequisites

```bash
# Build essentials
sudo apt install build-essential flex bison libncurses-dev \
    libssl-dev libelf-dev bc wget cpio

# Create workspace
mkdir -p ~/distro/{kernel,busybox,rootfs,iso}
cd ~/distro
```

## Step 1: Compile the Kernel

```bash
cd kernel
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.tar.xz
tar xf linux-6.12.tar.xz
cd linux-6.12

# Use default config, then customize
make defconfig
make menuconfig
```

Key config options:
```
General setup --->
    [*] Initial RAM filesystem support
    
Device Drivers --->
    [*] Block devices
    [*] SCSI device support
    
File systems --->
    [*] Second extended fs support
    [*] Ext4 journaling file system
    
Executable file formats --->
    [*] Kernel support for ELF binaries
```

```bash
# Compile (grab coffee)
make -j$(nproc)

# The kernel image
ls arch/x86/boot/bzImage
```

## Step 2: Build BusyBox

BusyBox provides all core Unix utilities in a single binary:

```bash
cd ~/distro/busybox
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1

make defconfig
make menuconfig
```

Critical setting:
```
Settings --->
    [*] Build static binary (no shared libs)
```

```bash
make -j$(nproc)
make install CONFIG_PREFIX=~/distro/rootfs
```

## Step 3: Create the Root Filesystem

```bash
cd ~/distro/rootfs

# Create directory structure
mkdir -p {dev,proc,sys,etc,tmp,root,var/run}

# Create device nodes
sudo mknod -m 622 dev/console c 5 1
sudo mknod -m 666 dev/null c 1 3
sudo mknod -m 666 dev/zero c 1 5
sudo mknod -m 666 dev/tty c 5 0
```

## Step 4: Write the Init Script

The init process is PID 1—the first userspace process:

```bash
cat > init << 'EOF'
#!/bin/sh

# Mount virtual filesystems
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev

# Set hostname
hostname minimal-linux

# Clear screen
clear

# Display banner
echo "=================================="
echo "   Minimal Linux Distribution"
echo "   Built from scratch"
echo "=================================="
echo ""

# Drop to shell
exec /bin/sh
EOF

chmod +x init
```

## Step 5: Create the Initramfs

```bash
cd ~/distro/rootfs

# Pack everything into a cpio archive
find . | cpio -o -H newc | gzip > ../initramfs.cpio.gz
```

## Step 6: Create Bootable ISO

```bash
cd ~/distro/iso

# Copy kernel and initramfs
cp ~/distro/kernel/linux-6.12/arch/x86/boot/bzImage .
cp ~/distro/initramfs.cpio.gz .

# Create GRUB config
mkdir -p boot/grub
cat > boot/grub/grub.cfg << 'EOF'
set timeout=5
set default=0

menuentry "Minimal Linux" {
    linux /bzImage
    initrd /initramfs.cpio.gz
}
EOF

# Create ISO
grub-mkrescue -o ../minimal-linux.iso .
```

## Step 7: Test It!

```bash
# Run in QEMU
qemu-system-x86_64 -cdrom ../minimal-linux.iso -m 512M

# Or write to USB
sudo dd if=../minimal-linux.iso of=/dev/sdX bs=4M status=progress
```

## Adding More Features

### Networking

Add to init:
```bash
# Bring up loopback
ip link set lo up

# DHCP (requires dhcpcd in BusyBox)
ip link set eth0 up
dhcpcd eth0
```

### Package Management

Create a simple package format:
```bash
# Package structure
mypackage/
├── PKGINFO
├── bin/
│   └── myprogram
└── etc/
    └── myconfig

# Install script
tar -C / -xf package.tar.gz
```

### Persistent Storage

```bash
# Mount a disk partition
mount /dev/sda1 /mnt

# Add to fstab
echo "/dev/sda1 /mnt ext4 defaults 0 0" >> /etc/fstab
```

## Understanding Boot Sequence

```
BIOS/UEFI
    │
    ▼
Bootloader (GRUB)
    │ loads kernel + initramfs
    ▼
Linux Kernel
    │ extracts initramfs
    │ runs /init
    ▼
Init Process (PID 1)
    │ mounts filesystems
    │ starts services
    ▼
Shell
```

## Common Issues

### Kernel Panic
- Missing drivers for your hardware
- Init script not executable
- Wrong path to init

### No Shell
- BusyBox not built statically
- Missing /bin/sh symlink

### No Network
- Missing network drivers
- Firmware not included

## Going Further

Once you have a minimal system:

1. **Add a real init system**: OpenRC, runit, or s6
2. **Build a package manager**: Write scripts to manage software
3. **Add X11**: For a graphical system
4. **Cross-compile**: Build for ARM, RISC-V

## Conclusion

Building your own distro is the ultimate Linux education. You'll understand every component because you built it yourself.

It's not practical for daily use, but the knowledge transfers to everything you do with Linux.

---

**Resources**:
- [Linux From Scratch](https://www.linuxfromscratch.org/)
- [Kernel Newbies](https://kernelnewbies.org/)
- [BusyBox Documentation](https://busybox.net/downloads/BusyBox.html)

---

*This content is available at [kelexine.is-a.dev/blog/minimal-linux-distro](https://kelexine.is-a.dev/blog/minimal-linux-distro)*
