This was way harder than it should have been. You would imagine if you just have a bootloader, a kernel, and a filesystem you’d be ready to go.

Most of the “minimal linux build tutorials” are really dated.

In fact, I think because Linux From Scratch is around, most people just point to that and think we don’t really need tutorial for building a simple working system.

Well LFS is certainly not ‘minimal’. It’s a monster, at over several hundred megabytes. Not to mention it takes a good deal of time. I want something I can do pretty quickly.

For the longest time, I was stuck with a working chroot environment, but It was not easy getting it to boot.

Then I came across this blog. At first it looked like it was made just for me. The only posts are about putting together a minimal bootable environment and it’s recent — 2012!

Well it was a bummer. It stopped just before booting the environment.

But I actually got it to work. A working, super minimal, Busybox environment. Here’s my story.


  1. Virtualbox
  2. Debian

In particular, you want to have a Virtualbox hard disk installed with Debian. It can actually be any Linux, but in case you’re wishy washy, Debian is pretty good for playing around with, especially because when you install it, tasksel comes up and asks you what you want, and you can unmark the desktop and base utils. As far as I can tell,  I don’t think Ubuntu let’s you opt out of things too easily.

Furthermore, you might want to get Virtualbox Guest Additions — not only is it nice to have the additions, but you will also need the build tools.

Step 1: Add A hard disk

A picture is worth a thousand words:

Add hard disk on Virtualbox settings

It if this isn’t clear, add a comment saying so. But it should be.

Once you get there, choose to add “A New Hard disk”. And you’ll get the standard hard disk creation dialogue you get when you create a new virtual machine.

Well this is going to be where we’re going to build our new minimal Linux distro.

Yea you know most other tutorials about this stuff wants you to make a separate partition. Ugh!! It’s actually not that bad, but with modern technology (i.e. Virtualbox) we can avoid it pretty easily.

Step 2: Build a kernel

Since our new disk has nothing in it, you should boot into Debian. I know it’s usually bad advice to do things as root when you don’t need to, but I just found it convenient to stay root throughout this tutorial, so I’m going to (If you’re like me, and you just made this a spare Debian install so you could mess around with things, it really shouldn’t be a problem — I set up my Debian box half expecting something to go terribly wrong). If you’re not logged in as root, you can just su or sudo when appropriate.

to get the kernel source type (you can check which one’s the most recent on


to build the kernel:

tar jxf linux-3.2.7.tar.bz2
cd linux-3.2.7/
make defconfig && make

If you were really out to make a minimal kernel you could follow Nasir’s bit on kernel building, but quite frankly, your kernel will probably not be over a dozen megabytes at most even if you use defconfig. However, if you do it Nasir’s way you might also get shorter compile time. Pick your poison.

Once the compilation finishes (it could take a while, but probably not more than half an hour on a reasonably modern machine), you will find your kernel at arch/x86/boot/bzImage. In fact, It will even tell you at the end of the build.

Step 3: Get Busybox

You can download a statically linked Busybox executable from:


This is probably another place you could hail modern technology. For those of you who don’t know what Busybox is, the Busybox multiplexer is a single program that can be called and used as many different programs.

For instance, try

./busybox-i686 ls

It gets even better:

ln busybox ls

Before Busybox you probably had to fetch all the different executables and libraries to get all the essential software to work (you would have to get core-utils and required libraries). Busybox is a single executable that can be used as a shell (ash), ls, ps, mkdir, cd, etc. You can also follow Nasir’s build method, but as far as I can tell, I don’t really see the benefit. The static Busybox executable is small enough for me to begin with, so it’s all good.

Also you should note that we got the static Busybox executable. In case you don’t know what a static executable is, a dynamic (i.e. non-static) executable depends on external libraries, so if we want a dynamic executable to work in a different hard disk, or even a different partition, we often need to copy over the libraries. If you build Busybox from source, by default it is set to build dynamically.

Step 4: Build the root file system

Actually here, I’m just gonna stick to Nasir’s method, so you could probably just follow the instructions there.

For completeness I’ll list the directions here.

We’re gonna build the initrd system. Most of the following should be self explanatory. I might post about mknod later, but it probably isn’t too hard to find the info on Google.

Btw, make sure you’re not still in the kernel source directory. There’s nothing wrong with doing it there, but it isn’t a pleasant thought for me.

mkdir rootfs
cd rootfs
mkdir dev proc sys tmp
mknod dev/console c 5 1
cat >> init << EOF #!/bin/ash mount -t proc none /proc mount -t sysfs none /sys /bin/ash EOF chmod +x init 

Now that we have our file system pretty much set up, we want to package it.

 find . | cpio -H newc -o | gzip > ../rootfs.cpio.gz
cd ..

Step 5: Format the Disk

Your disk is probably on /dev/sdb.



and create a single partition taking up the entire disk.
Also mark the partition bootable.

Now the file /dev/sdb1 should exist. You should be able to run:

mkfs.ext3 /dev/sdb1

to format the partition.

Step 6: Get Grub

Almost there!! — After this step, you get to boot into your personally assembled Linux environment!

Now we actually want to put stuff into our other disk, /dev/sdb1. Run

mount /dev/sdb1 /mnt

So that we mount the /dev/sdb1 partition on /mnt. Now we can put stuff in sdb1 by putting stuff in /mnt.

You probably have grub installed. I’m also going to take a reasonable leap of faith and say you have grub2 installed.


grub-install --root-directory=/mnt /dev/sdb

For more info on Grub2 see this post.

Step 7: Boot!!

Lol. There’s actually little more work to be done.

Create a new virtual machine, except this time, instead of creating a new virtual hard drive, choose to use an existing one, and pick the one that you’ve been working on.

Now boot!!

You’re going to see the grub boot prompt.

Type in

set root=(hd0,msdos1)
linux /bzImage
initrd /rootfs.cpio.gz

And after the messages seem to stop, type enter.

Now type in a command (e.g. ls).

Doesn’t Busybox ls look nicer than with barebone Debian?
Now you’re in a personally assembled Linux environment!!


There’s a lot that could improve. For one, I could get grub.cfg set up so that you don’t have to type in boot info everytime you boot. Another thing — we’re really only in the initrd filesystem. An improved version of this tutorial should really cover how to at least access the real file system.

If you liked this tutorial, and fix it up a little, give me the link so I can link to your post — I believe in multiple versions of similar posts. That way we can choose.

6 responses »

  1. David Stoker says:

    Excellent! Thanks for the write-up!

  2. Max says:

    The links to nasir’s blog don’t work anymore.. They even don’t exist in as if the site never existed. But next to it , its a good guideline..

  3. BC says:

    Great post; helped me a lot. After playing around with this, I landed up using buildroot to add additional packages. Anyways, I was able to find Nasir’s blog on

  4. Persson Fredrik says:

    The only unclear thing is where to put the kernel and wich files to use.

  5. krisdav says:

    when trying to input linux /bzImage in grub i get the following error: File not found.. ?

    and the system won’t go any further.

    I’ve never done anything like this before and it strikes me that there seems to be holes in the tutorial on how to-do certain things as I’ve had to refer and google a few parts that have failed to work as instructed.

  6. mdd says:

    I think you should point Nasir’s blog to version, since the blog is no longer active.

    If you have more time to spend, could you update this guide so that it is working on 2016?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s