Linux From Scratch
Created: 2024-12-30 Last Modified: 2025-02-22
Linux From Scratch (LFS) teaches you how to build a functional Linux system from the ground up. This December, I decided to to follow the LFS book’s instructions to creaty my own Linux system from scratch.
In this article, I’ll share my experience with the project, what I learned along the way, and my overall thoughts on the value of LFS. Rather than summarizing the book chapter by chapter, I want to highlight my takeaways and insights from the process.
My primary goal for this project was to understand what it takes to get a Linux system running. I wanted to build and see the “bare minimum” required to create a bootable and usable system.
While I am familiar with the installation process for Arch Linux, I wanted to see what actually needs to be done and what steps are involved.
Additionally, with some vacation time during the holidays, I was looking for a fun and challenging nerd project to keep me engaged. LFS turned out to be the perfect fit.
How did it go? Really good!
The LFS book is excellent, it explains everything in great detail! I found the instructions to be clear and straightforward with very little room for misunderstandings. The author tries to be as precise as possible! I encountered only one decision point in the entire process: Where should the run OS? Should I use my physical hardware? This is a big no no! The risk of messing around with my system (partitions and installation) and therefore wrecking my system was too high. Insted, I opted for a virtual machine (VM).
I chose QEMU to run the VM, simply because it was convenient. A quick internet search lead me to a wonderful blog article by CRMullins
. This was a good starting point for me. Like the author, I also decided to use Ubuntu as the host system to build my LFS system.
Early in the process, I realized just how many commands need to be run to complete this installation. Also, I new that I would not finish it in one session. To make things manageable, I started scripting everything and syncing it with rsync
to the VM. This approach was a livesaver. Whenever I wrecked the VM because I made a mistake, I could simply delete the VM, and restore the previous state in less than five minutes by running the scripts. The scripts proved to be a good idea, as a single mistake often could lead to breaking either the host system or the target system.
One part of the process which tested my patience was Chapter 8, where all the software is installed on the target system in a chroot environment. While many of the packages include explanaitions of their purpose and usage, the process itself is long, repetitive and prone to errors. This chapter consumed the most time, but carefully reading through the instructions and understanding the rationale behind each step was crucial.
Installing software in this fashion showed me even more how important package manager are. Package managers are not just convenient tools but complex systems that save an immense amount of time and effort. Performing this large manual task let me appreciate their importance even more.
Although I automated much of the LFS installation myself, I discovered the existence of an official project called Automated Linux From Scratch (ALFS). When I reached Chapter 8, I considered switching to ALFS but decided against it. I wanted the full, unfiltered LFS experience, and I’m glad I stuck with it.
What did I learn? A lot!
There were so many “aha!” moments throughout this process. One of the first was realizing that you need to compile GCC and other tools multiple times in different stages to build a fully independent toolchain. At first, this idea was mind-blowing, but as I progressed and read the explanations, it all made sense.
Did I really just replace some strings in the Makefile to make a package build? Sometimes the instructions call for a sed
command to replace text in the Makefile or even in the source code itself. While this approach worked, it felt a bit like “duct tape”, something that probably shouldn’t be done unless absolutely necessary.
When I skimmed over the list of packages, I noticed not only Python but also Python packages. Why are these needed? It turns out that even in a basic Linux installation, Python is used in the build systems of some packages.
What does it actually take to chroot into another system? Mounting the necessary filesystems from the running system into the target system, and understanding why this is needed, helped me understand what the arch-chroot
command actually does behind the scenes. I had always taken it for granted, never really considering what happens under the hood.
I also saw the network devices like enp3s0 and, while I understood it was a network device from the context, I never really asked why it was named like that, or how it was created. The book explained very well that a sequence of events takes place to create network devices, and that this is managed by udev. Actually, not just network devices, but any device node on the system. I learned that udev is responsible for managing device nodes in Linux.
Since I started using Linux, systemd has always been the init system I was familiar with. I never stopped to consider what systemd actually does or what its responsibilities are. When installing Linux From Scratch, I learned that SysVInit (or simply init) is used instead of systemd. Init is the very first program that runs and essentially starts everything else.
There were a lot more moments like these, but these points were definitely the biggest “wow” and “aha” moments for me.
My Summary
The book was a really good read with a nice practial part. I had a lof of fun even during the long Chapter 8. The joy of seeing the system actually boot and run as expected was wonderful! This is contrary to my expectations and feels even more rewarding.
My goal was to use this as a learning experience, rather than aiming for a production ready system. The risk of breaking the entire system is too high. Especially, if something like a package update isn’t handled correctly. A good example for this is Glibc.