Today I had a paid day off, so I took the chance to hook up that raspberry pi 1B+, which I had laying around for some months.

The idea is to use it as a fileserver for the internal network (read: only at home, not exposed to the Internet).

So I don’t need a graphical UI, but instead a headless system. Sounds for a minimal distribution. Let’s go for Gentoo :-)

If you want to follow along, you should have:

  • No fear of GNU/Linux
  • Something to take notes
  • Internet connection
  • A LAN cable
  • A sd card (I am using a 2 GiB microSD here)
  • A card reader to hook the sd card to a laptop
  • Raspberry Pi
  • External keyboard for the Raspberry Pi
  • Some hours at hand (it took me about five hours with all the read-up)
  • A laptop with GNU/Linux to download the needed tar balls
  • A laptop with GNU/Linux for mounting the SD card
  • Knowledge of a CLI editor (nano is sufficient. I’m using vim, too)
  • GParted installed on the laptop (you could go for parted as well…)

Everything ready? Let’s go!

Preparing the sd card

I am mainly relying on the Quick Install Guide of Gentoo here.

So first plug the sd card into the card reader and wire that one up to your GNU/Linux box. Backup everything you might need later, because we are going to wipe the card now :-)

Make sure, the card is unmounted. You can verify it like so:

$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sdc      8:32   1   1,9G  0 disk
├─sdc1   8:33   1    33M  0 part
└─sdc2   8:34   1   1,8G  0 part

There MUST NOT be a mountpoint given! In case it is, umount /path/to/mountpoint it. (You can force umount it if you are not worried about data corruption. After all, you have a backup, right?)

Ready? Fine!

Creating partitions

Let’s start gparted with root permissions (it will prompt you to do so if you are opening it without).

Make sure you are targeting the right device! In my case, that would be sdc. You can change the device via GParted > Devices.

According to the Quick Install Guide, Raspberry boots off of a FAT32 partition. So we are first deleting all partitions (again, make sure you are on the right device!) and then create new ones. I added a FAT32 one with the minmal size (33MB) at the beginning. A second partition with ext4 takes up all the rest.

A swap partition is a nice-to-have. Since I don’t have much space, I skipped to create one.

Both are primary ones. I’ve assigned labels to them, so they show up nicely when mounted to my laptop :-)

After application of the changes, you can add a flat to the first partition to indicate it’s bootable. Therefore rightlick the entry and select edit flags.

The UI will shortly reload. Close GParted. You are done here.

Double check with lsblk again.

Later on I ran into an issue with running out of inodes to set up portage. On Telegram’s Gentoo chat room, @khaosgrille suggested to change the bytes-per-inode ratio. If you don’t know, what an inode is, read up about inodes on Wikipedia.

Because it is not clever to blindly apply commands found on the Internet I myself read up about the options. Since I was using ext4 for the second partition, that let me to man mkfs.ext4, looking for the usage-type option. The docs told me to look into /etc/mke2fs.conf for details.

Turns out, I need the usage type small. Since I had not put anything on the partition, I entered sudo mkfs.ext4 -T small /dev/sdc2 and confirmed the warning (partition busy). This raised my inode count from 117K to 477K (according to ls -ih /dev/sdc2). Enough for moving on.

Downloading Gentoo

For the following sections, you should cd /tmp on your laptop, so the downloaded tar balls are removed during your next boot.

Visit Gentoo’s autobuilds for ARM chips and copy the URL for the correct ARM version (in the case of a Raspberry PI first generation that would be ARMv6 with hard FP). You are looking for the file ending with .tar.bz2.

Switch back to the terminal at /tmp and download the file: wget <Link-to-tar-ball>. This can take some time. Go grab a cup of tea.

After the download, I suggest to download portage as well.

Now creating the mount points and mount the SD card:

sudo mkdir /mnt/gentoo
sudo mount /dev/sdc2 /mnt/gentoo
sudo mkdir /mnt/gentoo/boot
sudo mount /dev/sdc1 /mnt/gentoo/boot

Pay attention to mount the first partition to the sub-directory boot!

Ready to launch the tar bomb?

tar bomb (by Randall Munroe, CC BY-SA 2.5)

Jokes aside, run the following commands:

sudo tar xfpj /tmp/stage3-armv6j_hardfp-*.tar.bz2 -C /mnt/gentoo/
sudo tar xjf /tmp/portage-latest.tar.bz2 -C /mnt/gentoo/usr

Again, this will take some time. Time for a walk?

Completed? Cool! Now we are only lacking a kernel. There are good and bad news here.

The bad news? The kernels are proprietary. The good ones? The Raspberry Pi Foundation is hosting compiled ones on GitHub. Run the following commands to add the kernel to the sd card:

cd /tmp/
git clone --depth 1 https://github.com/raspberrypi/firmware/
cd /tmp/firmware/boot
sudo cp -r * /mnt/gentoo/boot/
sudo cp -r ../modules /mnt/gentoo/lib/

Pre-boot configuration

Almost finished! Just some configuration steps needed until we can boot into Gentoo. Let’s go!

fstab

In order to have the partition mounted on boot, you need to edit the fstab file. You can use either nano or vim to do so:

sudo vim /mnt/gentoo/etc/fstab
# Append the following lines to the file and write them with <Esc>:wq

/dev/mmcblk0p1      /boot       auto        noauto,noatime  1 2
/dev/mmcblk0p2      /           ext4        defaults,noatime     0 1

I’ve modified the Quick Install Guide here by using the correct number for my root partition (mounted at /) and adding the defaults option. Otherwise I found the partition mounted read-only. Keep in mind, that it will likely allow more things than what would be healthy. See man 5 fstab if you interested in details. First, I’ve tried to use UUID instead of the device identifier, but on boot I’ve read, that Linux could not find it. Same with /dev/sdc2. So stick to the way they are written here.

If you want to understand more about why they are looking so cryptic, read up about Predictable Network Interface Names and udev.

boot options

Anyway, let’s continue with the boot options.

Fire up your editor again:

sudo vim /mnt/gentoo/boot/cmdline.txt
# The file is likely new. Add the following content:
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

Pay attention to point to the correct partition for root! You can read more about cmdline.txt if you want.

Timezone

I ran into a small problem here. So let me explain. First, list all available time zones and copy the correct as localtime:

sudo ls /mnt/gentoo/usr/share/zoneinfo
sudo cp /mnt/gentoo/usr/share/zoneinfo/Europe/Berlin /mnt/gentoo/etc/localtime

Now, the instructions that to pipe the timezone (“Europe/Berlin”) into /mnt/gentoo/etc/timezone. This didn’t work for me (permission error). So I just created the file and added this line as its content.

Clear root password

Last step before we can unmount! Blank the root password so you can set it right after boot:

sudo sed -i 's/^root:.*/root::::::::/' /mnt/gentoo/etc/shadow

Unmount and boot

You’re done! Now unmount the sd card and put it into your Raspberry Pi:

sudo umount /mnt/gentoo/boot
sudo umount /mnt/gentoo/boot

(Yes, it’s umount, not unmount!)

Remove the sdcard from the card reader, put it into the Raspberry Pi, add your keyboard, (HDMI) monitor, LAN cable and power supply. The device will boot as soon as it gets power.

Post-boot configuration

You should be prompted to a screen for login. The username is root. I wasn’t asked for a password. If you are, just hit Enter.

Keep in mind, that you are using an US keyboard here!

Change root password

The first thing after boot is to change the root password. Therefore enter passwd.

I was told that the “authentication token look busy” and learnt, that this is caused by a root partition mounted as read-only. I advise you to go back and get the fstab and cmdline.txt files right.

Enabling network on boot

In case you are plugging your LAN cable just now, reboot the raspberry. (Enter your chosen password now ;-) ).

Then follow these steps:

cd /etc/init.d/
ln -sv net.lo net.eth0
rc-service net.eth0 start
rc-update add net.eth0 boot

Muting debug statements

You likely saw messages like

INIT: Id “s0” respawning too fast

so mute those messages.

nano /etc/rc.conf
# Uncomment rc_sys
rc_sys=""
nano /etc/inittab
# Comment s0
# SERIAL CONSOLES
#s0:12345:respawn:/sbin/agetty 9600 ttyS0 vt100
#s1:12345:respawn:/sbin/agetty 9600 ttyS1 vt100

Fix the clock

No, we don’t have 1970 any more. So let’s fix that one:

rc-update --update
rc-update add swclock boot
rc-update del hwclock boot
date  # In case it is not correct, enter it in format MMDDhhmmYYYY
date 050204212013

What happened? The raspberry pi has no hardware clock, but a software one. So we switched it.

Then we entered the correct date in the format of month-day-hour-minutes-year.

What you could do next is adding software for NTP, but on the device, it takes hours.

You likely want to look into cross-compiling software on a more powerful device.

Select a profile

Before you run emerge, make sure you have selected the right profile:

eselect profile list

The output can take a while. Personally I’ve chosen default/linux/arm/17.0/armv6j (dev).

Install packages

Now that’s settled, let’s use emerge!

emerge --ask ntp
rc-update add ntp-client default

Start SSHD

To finish up, start the SSH daemon, so you can log into without a screen.

rc-update add sshd default
/etc/init.d/sshd start

At this point you can shutdown the raspberry pi, detach everything and power it on again. Now, you should be able to SSH into it.

I’ve added my public SSH key as authorized to it to be double sure.

You can look up the IP address via your router.

Finishing up

Some last steps I’d recommend before putting the raspberry pi on the shelf.

Creating a non-root user

The general advice is to not log in as root. Hence you’ll need a second user.

useradd -m -G users,wheel -s /bin/bash john
passwd john

Log out from root by executing exit and re-login as john. If you need to become root it is as easy as su -.

Setting hostname

In order to have a speaking name, it makes sense to define the hostname. Therefore edit these two files:

nano /etc/hostname
# Give it a speaking name. Like raspi
raspi
nano /etc/hosts
# Pay attention to separate the entries with <kbd>tab</kbd>s!
127.0.0.1   localhost
127.0.0.1   raspi.local localhost raspi

Restart the hostname daemon, so the changes take effect:

/etc/init.d/hostname restart

Now you can log in from your laptop as john via SSH:

ssh john@raspi

Shutdown and reboot

In order to safely shutdown your machine, don’t pull the plug, but instead issue these commands as root:

reboot
# or, preferably
shutdown -hP now

Install packages without permanent SSH connection

If you are like me, you don’t want to run risk of commands breaking because the connection drop. Therefore, install tmux.

emerge --ask app-misc/tmux

Now you can start a tmux session as root, execute emerge and detach it.

tmux new-session -s portage
# Install something
emerge --ask app-misc/colordiff
# Hit Ctrl-b d to detach the session
tmux ls
tmux attach -t portage

Oh, speaking of colordiff. You’ll quickly run into situations, where you will need to update config files.

If you use a modern tool like dispatch-conf instead of etc-update, bring some colour in by editing its conf file.

nano /etc/dispatch-conf.conf
# Update the following line
diff="colordiff -Nu '%s' '%s'"

Now if emerge tells you, that there are config files in need of update, run dispatch-conf and edit it to your liking.

Conclusion

That was a fun exercise!

I learnt a bunch of new things like the inode-per-byte ratio and alternatives to solve conf conflicts.

If I run into some other interesting problems, be sure I’ll write a blog post!