I've always played around with different Linux distributions, including those which are "DIY" like Arch Linux, or source-based like Gentoo Linux, but there has always been a project in the back of my mind that I never had the time to start: Linux from Scratch.
Since I had an extended Christmas/New Year's holiday, I thought this would be the perfect time to sit down and embark on the adventure of building my own Linux distribution from source code.
Please note that this blog post is just my experience with LFS and not a step-by-step guide to achieve a bootable system (but I will provide some tips).
Also, this blog post was an after thought since I wanted to concentrate on the build itself, so there will be a limited number of screenshots.
To quote the project itself: Linux From Scratch (LFS) is a project that provides you with step-by-step instructions for building your own customized Linux system entirely from source.
Basically, you are given a book which contains almost everything you need to build your own Linux distribution.
and I say almost because there are some aspects which are overlooked; more on that later.
There are multiple versions of this book, based on the targeted init system. The recommended ones are: sysv
and systemd
. You also have two branches: stable which is the recommended format, and the development branch which contains daily rendered snapshots. The former should be avoided for first time LFS'ers since changes can happen at any time that break the build, but since you've already embarked on this adventure, you should be prepared for things to go wrong.
LFS itself is pretty straight forward, but you have to take some things in consideration:
12.2-systemd
(the one I chose), expat
required version is 2.6.2
, but the link provided by the book won't work as the developers of the library deemed this version vulnerable. As such, I went with 2.6.4
after checking everything was compatible.dd
: # dd if=/dev/zero of=./lfs.raw bs=1G count=<size> status=progress
, partitioned it with cfdisk
and created a loop device to mount it with losetup
.tmux
), you can add the $LFS
variable to your .shrc
so you don't have to create the variable for every terminal session.$LFS
variable, otherwise, you risk doing things on your host machine.root
(unless the book says to use the lfs
or tester
users) and always set the correct permissions.ninja
) it could take more or less time.gcc
version on the host and the load and prioritization of the compilation process.gmp
, mpc
, mpfr
or binutils
, gcc
, for compilation, linking, assembling, etc.) to the system to make sure that they are correctly compiled.chroot
environment, then in the chroot
environment you are preparing them for the lfs build. In the cross-compilation section of the book, you'll see the 3 stages explained. If you skip these compilations, the configure
scripts will most likely not work and some features of the packages will be unavailable or straight-up not working.chroot
environment after backing up.systemd
configuration sections are after building the system and should be done when you are booted in the LFS system./dev/loopX
in the fstab
. This is just a temporary loopback device on your host./dev/sdaX
where X is the partition number. Your disk naming may vary based on disk type.libzstd.so.1.5.6
because I wasn't careful enough while stripping debugging symbols (at this point, I was 7 hours in) and make
wouldn't run.ext2
file system (even though you don't), just use --force
chroot
into your LFS drive from that VM and use grub-mkconfig > /boot/grub/grub.cfg
. This will generate a GRUB config that should just work.In the end, if everything went well, you can just boot into your LFS build.
This is a screenshot of my first boot into my LFS build. Ignore the specs of the VM, I was just rushing to create the VM to boot it.
In total, the time to get to a working LFS distribution was 8 hours on my personal workstation, which has the following specs:
It was truly a remarkable experience, and I think in these 8 hours, I've compiled more utils than I did in my entire life.
Would I do this again? Probably, but if I want to create a customized GNU/Linux distribution for a certain use-case with specific configs for the kernel, I would just go with Gentoo since: it already has package management with portage
, and you can still customize the compilation for each package, or just install a binary. portage
is very powerful and, in many cases, it helps you when creating an actually daily-drive-able with built-in support for multilib and packages built by the developers targeting Gentoo.
LFS is time-consuming and results in a bare-bones system, but at the same time an educational experiment and it really shows how we take for granted all of the low-level utilities that make up a functional Linux distribution (and how perl
truly is an important piece in every utility, no wonder it is called the swiss army knife for awk
, sed
, bash
, etc.)
Join me next time, as I build BSD Unix for a PDP 11. /s