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?)
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
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
The UI will shortly reload. Close GParted. You are done here.
Double check with
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
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
ls -ih /dev/sdc2). Enough for moving on.
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
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
Ready to launch the tar bomb?
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/
Almost finished! Just some configuration steps needed until we can boot into Gentoo. Let’s go!
In order to have the partition mounted on boot, you need to edit the fstab
file. You can use either
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
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
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
You can read more about cmdline.txt if you want.
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
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.
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.
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
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
Now that’s settled, let’s use
emerge --ask ntp rc-update add ntp-client default
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.
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
If you need to become root it is as easy as
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:
Now you can log in from your laptop as john via SSH:
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
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.
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!