Gentoo Wiki


Merge-arrows.gifIt has been suggested that this article be Merged into one article with Live USB stick using GRUB.    (Discuss)


What is this?

I've got a 64MB USB flash disk, and I wanted Gentoo on it, but to still have plenty of room for other files. Because there wasn't anything already out there, I figured it out for myself, and this is pretty much a HOWTO make a Tiny Gentoo (under 5MB) using uClibc and busybox (what the embedded guys use). Links to other (larger) projects and pages that were very helpful for me are at the See Also section.

What you need

Getting started

Choose a mirror close to you ( ), then hop into experimental/x86/embedded/stages, if your arch is x86. Download the stage3 file or stage1 or 2 if you want to play around more than what is necessary.

Feel free to be creative with the file and folder names, I'm just using ones that will explain what they are for. Basically we're just following the Gentoo Handbook Chapter 5, but with a few differences, most of the stuff we don't need to do because we'll only be chrooting into it.

A more detailed guide for creating the chroot can be found here.

Entering the chroot

mkdir /mnt/gentoo_uclibc
cd /mnt/gentoo_uclibc
tar xjpf <path to>/stage*
cp -L /etc/resolv.conf etc/resolv.conf
mkdir -p usr/portage

And what you'll need to repeat every time when entering the chroot:

mount --bind /usr/portage /mnt/gentoo_uclibc/usr/portage
mount --bind /dev /mnt/gentoo_uclibc/dev
mount -t proc proc /mnt/gentoo_uclibc/proc
chroot /mnt/gentoo_uclibc/ /bin/bash
env-update && source /etc/profile
Note: You should as well mount bind your distfile directory if on a separate partition, so that you do not need to download files that already are on your computer
Note: Non-gentooers, instead of binding your /usr/portage (that you do not have) into the chroot you will want to download a portage snapshot from the snapshots/ directory on a mirror.
tar xjf <path to>/portage-<timestamp>.tar.bz2 -C /mnt/gentoo_uclibc/usr
Note: If you are installing onto a flash drive, and have sufficient space on your hard drive, you may want to mount bind /var/tmp and /usr/portage/distfiles, to reduce the amount of read/write operations going on to your flash drive, and speed up compilation

Basic setup inside the chroot

We do want all the symlinks for busybox, and ccache, and only minimal versions of packages that support that use flag.

File: /etc/make.conf
# To use previously built packages, use the -k option with emerge 
FEATURES="ccache buildpkg"
# Store .tbz2's in their own directory
Warning: USE="minimal" causes emerge dropbear to fail due to the lack of scp.
Warning: To compile OpenJade successfully, Perl needs to be built with USE="-minimal"!
Note: you can specify the kind of CPU you're going to use with uclibc in the make.conf file with the UCLIBC_CPU directive. Possible values are : 386, 486, ELAN, 586, 586MMX, 686, PENTIUMII, PENTIUMIII, PENTIUM4, K6, K7, CRUSOE, WINCHIPC6, WINCHIP2, CYRIXIII, NEHEMIAH. The uclibc ebuild strongly recommends setting this variable as otherwise only generic (slow) optimisations will be used.

Note: You could as well chose an rsync server and a mirror close to where you are, cf. /etc/make.conf.example

The uclibc stages on the mirrors are quite old, so you will need to change the profile to a newer version. Emerge ccache first so that portage can use it for all the other packages. Then update all the packages, emerge the 2.6 kernel sources and copy the default bash login scripts to root's home directory.

# ln -snf /usr/portage/profiles/uclibc/x86 /etc/make.profile
# emerge ccache
# emerge -au portage
# emerge -auDN world
# emerge vanilla-sources
# cp /etc/skel/.bash_profile /etc/skel/.bashrc /root/ 
# mkdir /tinygentoo

If you get sandbox violation errors when upgrading coreutils just do

FEATURES="-sandbox" emerge coreutils

If you get errors while running the ancient emerge against the new portage tree use the following work-around:

On your parent Gentoo system create a package containing a working portage:

# quickpkg --include-config=y portage

You now have a package file at '/usr/portage/packages/All/portage-#.#.#.#.tbz2'. Chroot back into the subsystem as explained above and type 'cd /' to go to the root. Now extract the working portage over the embedded system chroot by typing:

# tar xvjf /usr/portage/packages/All/portage-#.#.#.#.tbz2

Finally you should emerge portage itself using the new emerge (from the parent system) to make sure everything is fine: 'emerge portage'

If sys-apps/gawk fails, see Bug #195368. Copy /usr/include/netdb.h to /usr/include/netdb.h.orig. Then add the following after line 403 in netdb.h:

File: /usr/include/netdb.h
# define AI_V4MAPPED    0x0008  /* IPv4 mapped addresses are acceptable. */
# define AI_ALL         0x0010  /* Return IPv4 mapped and IPv6 addresses. */
# define AI_ADDRCONFIG  0x0020  /* Use configuration of this host to choose returned address type. */
Note: You won't face the above problems if you upgrade to uclibc-

After a successful emerge world you may want to emerge app-portage/gentoolkit and run revdep-rebuild. If this fails because it wants to emerge an old python that is no longer supported(?), try emerge -pv python to find out which version you have, and then unemerge all old versions by using emerge -C '<python-X.Y.Z'. Replace X.Y.Z by the version you have, and don't forget the single quotes to prevent misinterpretation of the '<' sign by the shell. After this, do rm /root/.revdep* and try the revdep-rebuild again.

If the emerge -auDN world fails on busybox, then first emerge uclibc, then retry emerging world.

If after the above sys-apps/busybox fails with error: '__NR_clock_gettime' undeclared you need to upgrade sys-libs/uclibc. For the current version (1.8.2 as well as 1.7.4) uclibc-0.9.29 is needed, which is not in portage. See Bug #182094 for updated ebuilds.

Alternatively, to work around the busybox problem, you can do the following

FEATURES="keepwork" emerge busybox
# this will fail with the __NR_clock_gettime error
cd /var/tmp/portage/sys-apps/busybox-1.x.y/work/busybox-1.x.y
make menuconfig
  Deselect "BusyBox Settings"->"BusyBox Library Tuning"->"Use Clock Gettime"
  Exit configuration
mkdir -p /etc/portage/savedconfig/sys-apps/busybox
cp .config /etc/portage/savedconfig/sys-apps/busybox
cd $HOME
USE="savedconfig" emerge busybox
Note: You can always add the text "sys-apps/busybox savedconfig" to the file /etc/portage/package.use to retain this setting for future emerges


Everything that will finally be turned into an initramfs will be in /tinygentoo/. Using ROOT=/tinygentoo before emerge commands will emerge the packages into that directory. This way you do not need portage or gcc in there, but only the packages you really want.

Basic setup of /tinygentoo

Emerge the base packages

Note: The previous version of this how-to used baselayout-lite. As of April 2008, this package is no longer in portage. Instead we have to use baselayout-2 (aka openrc) according to the dev who removed it: vapier.

Emerge lines that do not have ROOT=/tinygentoo will be installed into the chroot so that it will be able to compile the other packages without errors. We do not add symlink to /etc/make.conf because that would interfere with later updating the baselayout-2, which will need to be unmasked first. See emerge --help if you're not sure what the options used do. Please note that at the time of writing, baselayout 2.0.0 is the most recent version. You can choose to unmask newer versions (and their dependencies) when needed.

mkdir -p /etc/portage
echo "=sys-apps/baselayout-2.0.0 **" >> /etc/portage/package.keywords
echo "=sys-apps/openrc-0.2.1-r1 **" >> /etc/portage/package.keywords
echo "=sys-fs/udev-118-r2 **" >> /etc/portage/package.keywords
echo "=sys-apps/baselayout-2.0.0" >> /etc/portage/package.unmask
echo "=sys-apps/openrc-0.2.1-r1" >> /etc/portage/package.unmask
ROOT=/tinygentoo USE=make-symlinks emerge -avkN =sys-apps/baselayout-2.0.0 uclibc busybox
Note: When you add INSTALL_MASK="*.h HACKING.gz TODO.gz" to the emerge commandline the given files will not be installed to the target filesystem.
Note: I had problem compiling busybox with gcc 4.1.1. You will need to create this link in order to compile busybox for i686. ln -s /usr/bin/i686-gentoo-linux-uclibc-gcc-4.1.1 /usr/bin/i686-gentoo-linux-uclibc-gcc
Note: If emerge is unable to merge baselayout-2 because it is still masked, update portage (so it understands the "**" keyword).
Note: When trying to install busybox-1.4.2 with gcc-4.1.1 and kernel version 2.6.16 it would not compile. To get it to work, I had to emerge uclibc into the current environment first, then run ROOT=/tinygentoo emerge busybox.
Note: When trying to install busybox-1.9.0 I ran into two problems. First it would not compile due to lack of PAM. This can be solved by adding " sys-apps/busybox -pam" to /etc/portage/package or by using busybox make menuconfig to remove support for PAM. Second problem was the package compiled but did not work on the target system. If I ran /tinygentoo/bin/ash I could get an ash prompt, however if I did 'chroot /tinygentoo /bin/ash' I would receive an error to the effect the program was not found. It turned out the necessary libraries for busybox were not installed in tinygentoo. You can check which libs are required by running 'ldd /tinygentoo/bin/ash'. Rather than copy the libraries into tinygentoo I opted to re-compile busybox as a static linked program. This is another option of the busybox 'make menuconfig'.
Note: In recent versions of busybox, the ebuild use flag for making the symlinks has changed from 'symlink' to 'make-symlinks'.

Setting up users

chroot into /tinygentoo/ and change the root password.
Please note, the shell shipped with busybox is /bin/ash, not /bin/bash:

chroot /tinygentoo /bin/ash

Add a regular user. Change foo to your username:

addgroup -g 100 users
adduser -h /home/foo -s /bin/ash -G users foo

exit the /tinygentoo chroot:


Set the hostname

Replace TinyGentoo if you would like to use some other hostname. /etc/hostname is read by /sbin/init, see /tinygentoo/etc/inittab. echo "TinyGentoo" > /tinygentoo/etc/hostname.

Note: You may also want to modify /tinygentoo/etc/inittab, this is because Busybox does not use runlevels in the inittab.

For more help see Busybox Init Documentation

Writing fstab

The root filesystem will be mounted as ramfs by the kernel. The only downside to this is that unlike tmpfs it does not have a size limit, so writing a lot to / could fill up your ram. Anything that is on tmpfs uses nearly no ram when empty and grows when needed but wont use up all of the ram, leaving room for applications to run.

Feel free to be creative, just remember that flash doesnt like being written to lots and lots, so do not mount / or /var onto it. sda1 is the partiton on the USB stick that will contain the bootloader files, the kernel and the initrd. /dev/sda2 will be the partition that you see when in windows, and you can use it to store any settings/files from TinyGentoo too.

File: /tinygentoo/etc/fstab
none                    /tmp            tmpfs           defaults        0 0
none                    /proc           proc            defaults        0 0
/dev/sda1               /boot           ext2            noauto,ro       0 0
/dev/sda2               /mnt/dongle     vfat            defaults        0 0

Make the two directories that do not yet exist mkdir /tinygentoo/boot /tinygentoo/mnt/dongle

Writing /init

This step is optional. Instead of having this file you could add init=/sbin/init to the grub kernel line.

/init is the file that the kernel executes right after loading the content of the initramfs. If you are using initrd instead of initramfs, rename this file to linuxrc

File: /tinygentoo/init
echo " Welcome to TinyGentoo."

echo " * Setting umask.."
umask 022
echo " * Mounting /proc.."
mount -t proc none /proc
# I also have this in here to successfully populate /dev by using mdev
echo " * Mounting metafilesystems..."
mount -t proc   proc   /proc
mount -t tmpfs  mdev   /dev && mkdir /dev/pts
mount -t devpts devpts /dev/pts
mount -t sysfs  sysfs  /sys
echo " * Populating /dev..."
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s		
echo " * Starting init.."
exec <dev/console >dev/console 2>&1
exec chroot . /sbin/init

echo " *** Starting init failed! ***"
echo " * Trying to start a shell.."
exec /bin/ash

Remember to make it executable chmod +x /tinygentoo/init

If you would like to be able to use the same script with both initrd or initramfs, you can symlink one /init to /linuxrc.

cd /tinygentoo
ln -s init linuxrc

Optional, but if you would like to change the timezone, edit /tinygentoo/etc/TZ. For example, echo UTC > /tinygentoo/etc/TZ.

Emerging the wanted packages into /tinygentoo

Choose what packages you want. esearch foo in your regular Gentoo to easily find out what the packages are. The examples will provide you with an installation that can browse the web (lynx), connect to IRC (scrollz), run and connect to SSH servers (dropbear) and screen, that I don't know how some people live without.

ROOT=/tinygentoo emerge -avk lynx scrollz dropbear screen

That's it for /tinygentoo. chroot back in if you want to get a feel for it.

Note: If you try to emerge coreutils into you tinygentoo and it aborts with sandbox violations (confdir3) please check bug #125701.

You have to set this before you try to emerge coreutils:

export gl_cv_func_getcwd_path_max=yes


In theory you could just use a kernel built outside the uClibc chroot, but that would get confusing.

Kernel configuration

Not very hard really, and because we will be using an initramfs image most things can be compiled as modules if you wish to do so. Disable everything that you don't want or need to keep the size of the kernel image down.

cd /usr/src/linux
make menuconfig
Note: If you don't see your processor and/or architecture in Processor Type and Features, run
make menuconfig SUBARCH=i386
Linux Kernel Configuration: vanilla-sources-2.6.16 for TinyGentoo
Code maturity level options  --->
 [*] Prompt for development and/or incomplete code/drivers
General setup  --->
 [*] Enable 16-bit UID system calls  
 [*] Optimize for size
 [*] Configure standard kernel features (for small systems)  --->  

Note: if you are using uClibc 0.9.28 or older, you need to enable 16bit UID interfaces in the Linux kernel. This has been fixed in svn so newer uclibc's will use the 32 bit interfaces.

You don't want HIGHMEM if you haven't 1G or more RAM.

Processor type and features --->
 (4GB) High Memory Support
 [*] MTRR (Memory Type Range Register) support
 [ ] Symmetric multi-processing support

Enable this if you want normal hard disk support

Device Drivers --->
 ATA/IDE/MFM/RLL support  --->
  < > ATA/IDE/MFM/RLL support

What we need for reading from the USB stick to work:

 SCSI support  --->
  <*> SCSI support
  <*>   SCSI disk support

Of course we need the following because we run with an initrd root filesystem:

 Block devices  --->
 <*> RAM disk support
 (16) Default number of RAM disks
 (4096) Default RAM disk size (kbytes)
 [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

For networking remember to select the driver for the chipset of your NIC. Use lspci to find out what you've got. I have on-board nForce2 and some cheap PCI card with an RTL-8139 chip.

 Network device support  --->
  < > Dummy net driver support
  Ethernet (10 or 100Mbit)  --->
   [*] Ethernet (10 or 100Mbit)
   [*]   EISA, VLB, PCI and on board controllers
    <m>     nForce Ethernet support (EXPERIMENTAL)
    <m>     RealTek RTL-8139 PCI Fast Ethernet Adapter support

Keyboard support might be nice:

 Input device support  --->
  [*]   Keyboards

'Cos we'd like to be able to actually do something (enabled and hidden by default if CONFIG_EMBEDDED is not set):

 Character devices  --->
  [*] Virtual terminal
  [*]   Support for console on virtual terminal
  [*] Unix98 PTY support

We don't want X stuff:

  < > /dev/agpgart (AGP Support)
  < > Direct Rendering Manager 

Use lspci -v | grep HCI to see what ?HCI drivers you want. lspci is part of sys-apps/pciutils

 USB support  --->
  <*> Support for USB
  <*>   EHCI HCD (USB 2.0) support (EXPERIMENTAL)
  <*>   UHCI Alternate Driver (JE) support
  <*>   OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support
  <*>   USB Mass Storage support

For rw access to a partiton on the USB stick that is accessable from Windows too select VFAT.

File systems  --->
 <M> DOS FAT fs support
 <M>   VFAT (Windows-95) fs support
 [*] /proc file system support
 Native Language Support  --->
  <*> NLS ISO 8859-1  (Latin 1; Western European Languages) (NEW)
Console drivers  --->
 [*] VGA text console
 [*] Video mode selection support

As a final touch, you may also need something else than the default us keymap for your future system. If you need it, you can build the proper keymap for your keyboard layout inside the kernel issuing the following command from within the /usr/src/linux directory:

loadkeys -m <path_to_keymap> > drivers/char/defkeymap.c

An example for french layout:

loadkeys -m /usr/share/keymaps/i386/azerty/ > drivers/char/defkeymap.c

Compiling the kernel

Now just:

make -j2 && make modules_install
cp arch/i386/boot/bzImage /tmp/vmlinuz-tinygentoo

If you go back to menuconfig and change things, clean out the old modules so there wont be any extra ones taking up space:

rm -r /lib/modules/*
make modules_install

or if you don't want do the next step (coping modules) you can launch this command:

make INSTALL_MOD_PATH=/tinygentoo modules_install

Copying the modules

We want all the modules inside the initrd, so they'll need to be copied there.

mkdir -p /tinygentoo/lib/modules
cp -vr /lib/modules/* /tinygentoo/lib/modules/

Packaging /tinygentoo

We want everything under /tinygentoo to be turned into a single initramfs image. Don't forget to copy the kernel modules to /tinygentoo before this step!

Cleaning up

Copy the files to some other place so you can easily restart if you mess up, then remove all the files you don't need or want.

cp -r /tinygentoo /tmp/
rm -r /tmp/tinygentoo/var/*/* /tmp/tinygentoo/tmp/*

If you want to see how much space its using:

du -hs /tmp/tinygentoo

Creating the initramfs image

To create the initramfs image we will use cpio to create an archive of the files that the kernel can understand, and gzip it to make it smaller.

cd /tmp/tinygentoo && find . | cpio -H newc -o | gzip -9 > /tmp/initramfs-tinygentoo.igz
Note: This creates an initramfs type image which requires a file (or symlink) /init (such as the script we've shown above, or a symlink to /sbin/init or /bin/busybox). If your filesystem doesn't have a /init, the kernel will fall back to the initrd (not initramfs) method of mounting the root file system, which is incompatible with the cpio method of compression. In other words: without a /init, the kernel will panic with this method of creating the file system.

Preparing the USB flash disk

Basically we just want one partiton for the TinyGentoo boot files, and one partiton for saving files that you want to keep even after a reboot, and that will also be accessable from Windows.

Backing up the old data

Just in case you don't like it or just want to try it or.... something else, back up what you have got on your dongle (USB flash disk) right now. Make sure that you use the correct device, it might not be /dev/sda if you have other drives showing up as SCSI. Those could be a SATA hdd, a camera or an MP3 player. fdisk -l will show you what partitions are seen by linux.

Preferably do all the partitioning stuff outside the uClibc chroot, but you could do it from in there too if you've fallen in love with it :P

We'll just raw copy the whole disk. Note: sda is the whole disk, sda1 is only the first partition, it does not include the MBR/partiton table. Gzip it too to save space. 4K blocks to read to make it slightly faster, but its still slow..

cd /root
dd if=/dev/sda of=dongle_backup.img bs=4K
gzip dongle_backup.img

Creating the partitions

Clear the partition table and use fdisk (or something else if you don't like fdisk) to create the partitions.

dd if=/dev/zero of=/dev/sda bs=1 count=512
fdisk /dev/sda

Change the size of the boot partition so that it will fit your kernel + initrd.img + 1-2MB, though you could make it larger if you would like to use it for other stuff too.

Command (m for help): n
Command action
  e   extended
  p   primary partition (1-4)
Partition number (1-4): 1
First cylinder (1-1024, default 1): <enter>
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-1024, default 1024): +6M

To make it bootable:

Command (m for help): a
Partition number (1-4): 1

Then the vfat partition. Your cylinder numbers propably will not match mine, don't worry bout that.

Command (m for help): n
Command action
  e   extended
  p   primary partition (1-4)
Partition number (1-4): 2
First cylinder (95-1024, default 95): <enter>
Last cylinder or +size or +sizeM or +sizeK (95-1024, default 1024): <enter>
Using default value 1024

Change the type to FAT32 so that Windows will see it correctly

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): b
Changed system type of partition 2 to b (W95 FAT32)

Then to check everything is OK

Command (m for help): p

If yes, write and exit

Command (m for help): w

Formatting the partitions

There isn't really any good reason to use something other than ext2 for the boot partition. You may need to emerge dosfstools for vfat formatting support. The -F 32 makes it FAT32 to support longer filenames and stuff. Change label to what name you would like the partition to have.

mke2fs /dev/sda1
mkfs.vfat -v -F 32 -n label /dev/sda2

Installing GRUB

If you do not yet have grub, mount /boot && emerge grub.

First you will need to copy the stages. e2fs_stage1_5 is optional, and you may delete it after grub has embedded it. Make sure you have /boot mounted to be able to copy the files from there.

mkdir /mnt/dongle
mount /dev/sda1 /mnt/dongle
mkdir /mnt/dongle/grub
cp /boot/grub/stage? /boot/grub/e2fs_stage1_5 /mnt/dongle/grub/
umount /mnt/dongle
grub> device (hd0) /dev/sda
grub> root (hd0,0)
grub> setup (hd0)
grub> quit
mount /dev/sda1 /mnt/dongle
rm /mnt/dongle/grub/e2fs_stage1_5


In my case, I had to do use the following commands.

mkdir /mnt/dongle
mount /dev/sda1 /mnt/dongle
mkdir /mnt/dongle/grub
cp /boot/grub/stage? /boot/grub/e2fs_stage1_5 /mnt/dongle/grub/
touch /mnt/dongle/grub/usb_flag
umount /mnt/dongle
grub> find /grub/usb_flag
grub> root (hd1,0)
grub> setup (hd1)
grub> setup (hd1,0)
grub> quit
mount /dev/sda1 /mnt/dongle
rm /mnt/dongle/grub/usb_flag

The difference being that I had to setup BOTH the MBR and the boot partition's MBR. Until I did this, my BIOS would not boot from the USB stick.

Writing menu.lst (for GRUB)

GRUB looks for menu.lst, not grub.conf, but you may make a symlink to grub.conf from menu.lst and then edit grub.conf.

Add init=/sbin/init to the kernel line if you do not have a linuxrc file.

File: /mnt/dongle/grub/menu.lst
timeout 3

title TinyGentoo
kernel /vmlinuz-tinygentoo vga=791
initrd /initramfs-tinygentoo.igz

Set vga=ask to get a prompt to be able to select the resolution for your console. With the ramdisk_size= option you can set how large you would like your / to be, in KB. Don't set it too high if because you will also need RAM for applications to run, but you've got to set it large enough for the uncompressed initrd.img and dynamic files that will be created.

Note: If you get a blank screen after selecting the right kernel from the grub selector, try keep out vga=791 from the kernel line.

Copying the important files

Something you need to do to get it working..

cp /tmp/vmlinuz-tinygentoo /tmp/initramfs-tinygentoo.igz /mnt/dongle/
umount /mnt/dongle

BIOS Setup, Reboot and Enjoy!

Reboot, hit Del, F2 or whatever it is that you need to do to enter the BIOS configuration. Find the section where you can change the boot order, and select USB-HDD, USB-ZIP or something similar to have the highest priority. Save and exit, and reboot with the USB stick attached.

Where to from here?

If all goes well, you'll be in your shiny new TinyGentoo, that you will still need to learn to use though.. You will propably want to write a script to get the net going and maybe something to save your settings.


See Also

Retrieved from ""

Last modified: Mon, 13 Oct 2008 05:15:00 +0000 Hits: 74,142