Debian root file system | ||
---|---|---|
Prev | Created by Bayou. | Index |
Generating root file systems (rootfs) isn't the hardest thing to do in embedded Linux. Debian, for instance, already has a lot of scripts that help one to generate them. You only need to know a few details about mounting and changing your root to get things up and running fast. In this tutorial I will explain how to generate a Debian rootfs, add packages from other repositories, configure the rootfs as normal user and archiving it afterwards.
Rootfs are typically created in four steps: download packages, add custom packages, configure rootfs, archive root file system.
If you plan to generate a rootfs for another architecture, you also need to have a cross compiler. (For instance: gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf). Furthermore, to create rootfss, you need to install the following packagages.
$ apt-get install fakeroot qemu qemu-user-static proot fakeroot multistrap make gcc
$ export PATH="${PATH}:/usr/sbin:/sbin"
Multistrap is a tool that we will use to generate the initial rootfs. It uses a configuration file. To make sure that every package is downloaded and installed correctly, we run multistrap in a fakeroot environment. Fakeroot fakes root privileges for file manupilation.
The configuration file might look as follows. Note that the packages must remain on a single line. Below, I'm creating a Debian Buster filesystem for the armhf architecture. This file is called multistrap.conf
[General]
arch=armhf
directory=rootfs
cleanup=true
noauth=true
unpack=true
aptsources=Buster
debootstrap=Buster
addimportant=true
[Buster]
packages=systemd util-linux bash coreutils psmisc locales dbus procps policykit-1 sed grep apt-utils apt debconf
debianutils dpkg dpkg-sig rcconf base-files base-passwd udev libudev-dev kmod ca-certificates ssh openssl
libcurl4-openssl-dev net-tools mount vim libmodbus5 file
source=http://ftp.nl.debian.org/debian
keyring=debian-archive-keyring
suite=buster
Execute the following command to generate the root file system
$ fakeroot -- /usr/sbin/multistrap -f multistrap.conf
Note: In more recent multistrap might complain about insecure repositories (2.2.10 at the time of writing).
The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 648ACFD622F3D138 NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY DCC9EFBF77E11517
Copy multistrap to cwd and apply the patch below.
--- /usr/sbin/multistrap 2018-11-21 15:00:46.000000000 +0100
+++ multistrap 2021-11-01 09:40:52.288606233 +0100
@@ -340,7 +340,7 @@
my $apt_mark = "APT_CONFIG=" . shellescape($tmp_apt_conf) . " apt-mark $config_str";
printf (_g("Getting package lists: %s update\n"), $apt_get);
-$retval = system ("$apt_get update");
+$retval = system ("$apt_get update --allow-insecure-repositories");
$retval >>= 8;
die (sprintf (_g("apt update failed. Exit value: %d\n"), $retval))
if ($retval != 0);
Of course, now the command to generate the root file system is as follows.
$ fakeroot -- ./multistrap -f multistrap.conf
Usually you have prerequisites for a file system. In my own rootfs I enabled ssh login with password for root and set the timeout to 15 seconds in the systemd networking service. (Don't get me starting on systemd, though). There are also some things you have to add by default. These are:
Filename | Desciption |
---|---|
etc/hostname | Add a hostname. |
etc/fstab | Mount /dev/mmcblk0p1 on /, dev, proc and sys. |
etc/mtab | ln -s ../proc/self/mounts ./etc/mtab |
etc/group | Add root to inet and net_raw groups to make ping work. (inet:x:3003:root, net_raw:x:3004:root). These should be added:
|
etc/timezone | Europe/Amsterdam. Make sure that timezone isn't asked when we automate this in a makefile. |
I prefer to store the prerequisites in a directory named 'skeleton'. Now this directory is created, they must be copied to the rootfs that's being generated.
$ cp -aRf skeleton/* rootfs/.
Within Debian there are some issues between proot and PAM authentication if proot is run by an unprivileged user. This affects the following programs:
This issue prevents configuring systemd and setting passwords or user information. This can be solved easly by overwriting the function in which the error occurs.
$ cat fake_audit_log_acct_message.c
int audit_log_acct_message(int audit_fd, int type, const char *pgname,
const char *op, const char *name, unsigned int id,
const char *host, const char *addr, const char *tty, int result) {
return 0;
}
Make sure you cross compile it. You'll have to prepend `dpkg` and `chpasswd` commands with:
LD_LIBRARY_PATH=/usr/lib/ LD_PRELOAD=libfakeaudit.so.0.0
I stored this in workarounds/pam/.
References:
To ensure that a rootfs is working correctly, several files need to be linked from the host to the rootfs. These files are:
Use proot to configure the rootfs, since it doesn't need root privileges as chroot needs. Before the shell in proot is usable, export the PATH, DEBIAN_DRONTEND and DEBCONFG_NONINTERACTIVE_SEEN environment variables. This makes sure that every command is found and no questions are asked that are already defined.
$ cp `which qemu-arm-static` rootfs/usr/bin/.
$ proot -0 -w / -r rootfs -b /dev -b /proc -b /sys -b /etc/resolv.conf -b workarounds qemu-arm-static /bin/bash
$ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin;
$ export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true;
Configure the rootfs with the following commands.
$ /var/lib/dpkg/info/dash.preinst install;
$ LD_LIBRARY_PATH=/usr/lib/ LD_PRELOAD=libfakeaudit.so.0.0 dpkg --configure -a;
$ echo "root:root" | LD_LIBRARY_PATH=/usr/lib/ LD_PRELOAD=libfakeaudit.so.0.0 chpasswd;
It might be the case that packages remain unconfigured. If this happens, the message below will be printed. Base-files and bash usally complain about missing groups.
Errors were encountered while processing:
base-files
bash
dbus
libpam-systemd:armhf
policykit-1
Through the use of dpkg-reconfigure, these packages can be configured.
$ dpkg-reconfigure base-files bash dbus libpam-systemd:armhf policykit-1
Archiving is the last part. Make sure that root owns every file. If you've added an additional user with a home directory, you should exclude that directory with `--exclude="./home/user"` and add it afterwards.
$ tar -czpf rootfs.tar -C rootfs --owner=0 --group=0 .
Example excluding /home/user.
$ tar -czpf rootfs.tar -C rootfs --owner=0 --group=0 --exclude="./home/user" .
$ tar -rpf rootfs.tar -C rootfs --owner=1000 --group=1000 ./home/user
Prev | Home | Next |
Index | Up | Index |