The Linux From Scratch site provides a tutorial on building a complete Linux distribution “by hand”. You can find my notes on that experience here. As noted there, the LFS book leaves you with a very minimal system - it boots, has a shell, and wired (but not wireless) networking but not much more.
I spent some more time installing software using the BLFS book (systemd-based variant). Here are my notes..
I got as far as a running X environment with a basic window manager and firefox. An entirely usable system - but already outdated. It’s hard to estimate how long it took as this was done in pieces over time, but I would think somewhere around 20 hours of read/download/compile/configure were required.
After all this work, I have come to the conclusion that LFS/BLFS are not that great as a tutorial on Linux. There is certainly something to be learned, but they are mostly instructions on how to compile specific versions of software without much background on why, what alternatives, how it interacts with other apps, etc. If you have a desire, and the necessary time, to build and run a Linux os purely from source, then this is certainly a useful resource. I’m not sure who would really benefit from that though. I wouldn’t recommend it for the “simply curious”; IMO the time could be better spent learning about Linux in other ways.
To Chroot or not to Chroot
The BLFS instructions are written as if the installation was being done within a BLFS environment. However that makes reading the instructions difficult, given that BLFS has initially no networking, and no graphics. It is possible (see this BLFS hint for example), but not very convenient.
I can imaging that a desktop PC could be used to read the website, with an SSH connection to a separate machine on which LFS/BLFS is being installed (once the BLFS system has networking and SSH obviously).
However I’m installing LFS/BLFS on my primary laptop (ie not using two separate machines). I therefore used the chroot environment described in the LFS book to build 95% of the software for BLFS and that worked well. Interestingly, firefox was the only package I found which had to be compiled by rebooting into LFS; some weird python-related problem occurred in the chroot environment.
Downloading the BLFS Book
The book should definitely be downloaded locally, rather than read online. However be warned: the BLFS “systemd” books are delivered as tarfiles which unpack HTML files into the current directory (rather than creating a subdir to unpack into). Make sure you create a subdir, and move the download there before unpacking!
Entering the Chroot
When resuming work after rebooting do the following (as noted in section 6.4):
# 6.2.2: mounting and populating /dev mount -v --bind /dev $LFS/dev # 6.2.3 Mounting virtual Kernel File Systems mount -vt devpts devpts $LFS/dev/pts -o gid=5,mode=620 mount -vt proc proc $LFS/proc mount -vt sysfs sysfs $LFS/sys mount -vt tmpfs tmpfs $LFS/run # 6.4 Chroot chroot "$LFS" /tools/bin/env -i \ HOME=/root \ TERM="$TERM" \ PS1='\u:\w\$ ' \ PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \ /tools/bin/bash --login +h # If you've completed 6.36 (recompile bash) then do this (or use /bin/bash in the step above): see 6.72 exec /bin/bash --login +h
Installing Specific Packages
Installing python 1 test failed:
[312/400] test_ssl test test_ssl failed -- Traceback (most recent call last): File "/sources2/Python-2.7.9/Lib/test/test_ssl.py", line 2783, in test_dh_params chatty=True, connectionchatty=True) File "/sources2/Python-2.7.9/Lib/test/test_ssl.py", line 1905, in server_params_test s.connect((HOST, server.port)) File "/sources2/Python-2.7.9/Lib/ssl.py", line 824, in connect self._real_connect(addr, False) File "/sources2/Python-2.7.9/Lib/ssl.py", line 815, in _real_connect self.do_handshake() File "/sources2/Python-2.7.9/Lib/ssl.py", line 788, in do_handshake self._sslobj.do_handshake() SSLError: [SSL] dh key too small (_ssl.c:581)
However this doesn’t seem to be a problem: other packages using python worked fine. Not too surprising as the test that fails is something to do with SSL which isn’t relevant for most packages.
Everything installs fine, but when running tests, they hang after this step: PASS: gsettings 23 /gsettings/no-read-binding
This didn’t seem to have any negative effects; other packages depending on glib worked fine.
It wasn’t immediately clear, but when systemd was compiled during the LFS book, some optional dependencies were not present (in particular, glib, gobject-introspection, linux-pam and polkit). It is therefore necessary during LFS to install these dependencies and then rebuild systemd.
The instructions for rebuilding shadow after linux-pam has been installed are confusing. This section provides some configuration-files but there are already files with the same names, and quite different content. It was not at all clear how to “merge” the two sets of files.
The shadow package provides the
/bin/login executable used to manage logins on a text console. When shadow is compiled with PAM available, then the new version of login dynamically links to libpam (fairly obvious). Less obvious is that the new version of login still reads
/etc/login.defs on startup (like the old one); however the pam-enabled version does not support a number of configuration settings that the older login did (because these should be configured via pam plugins). Therefore, if you use the new login binary with the old login.defs file, then a list of warnings are printed on the console as soon as the username is entered at the login prompt:
configuration error - unknown item 'FAILLOG_ENAB' (notify administrator) configuration error - unknown item 'LASTLOG_ENAB' (notify administrator) configuration error - unknown item 'MOTD_FILE' (notify administrator) configuration error - unknown item 'FTMP_FILE' (notify administrator) configuration error - unknown item 'ENV_ROOTPATH' (notify administrator) configuration error - unknown item 'PASS_MIN_LEN' (notify administrator) configuration error - unknown item 'CHFN_AUTH' (notify administrator)
These are only warnings; login will still work fine (assuming you’ve got everything else fixed). Remove the unsupported options from login.defs to avoid the warnings.
One of the primary reasons I started BLFS was to see how xorg gets installed. At first the xorg chapter of BLFS is a little discouraging; it states that xorg is composed of so many small modules that it takes a massive amount of time to install them one-by-one and it is therefore recommended that the process be automated via a script.
Fortunately, the instructions are well-thought-out. The work is “automated” in similar chunks of work, such that the repetitive parts are mostly avoided without hiding what is really being done.
Unfortunately the instructions warn against mixing different versions of modules together, as some xorg “7.7” updates don’t work with other non-updated “7.7” modules. This means that unless you happen to be installing just after the BLFS book has been released, then you will be installing outdated software. Ah well…
It was a pleasant surprise to see that the Xorg source-code comes with excellent documentation on each X “protocol” (eg XRender, XInput). The DRI3 protocol is a very elegant example.
Question: First, the “protocol headers” are installed, ie .h files which define the datastructures corresponding to X request/response messages. But then the “xcb-proto” package is installed, which effectively represents the same information in an XML format. I would have thought that the headers could be generated from the xcb data. Why aren’t they?
These two applications have a mutual dependency, which makes installing tricky. I didn’t find the instructions in BLFS very clear; the correct order is:
- build/install freetype specifying “–without-harfbuzz” in the configure step
- build/install harfbuzz
- build/install freetype as per the BLFS instructions (ie with harfbuzz)
Just a personal opinion: section 24, “xorg drivers” shows what a mess the old X server was. Four different input drivers, 14 different video drivers.
I’m looking forward to the day (hopefully not long now) where there will be one libinput driver for input, and one glamor driver for video. Ideally on top of Wayland, though this should work with X too.
I found that building in a chroot environment didn’t work. I got:
Exception: Could not detect environment shell! configure: error: Python environment does not appear to be sane.
Booting into the lfs system and building there worked better.
I still got:
In file included from /sources2/mozilla-release/content/media/DecoderTraits.cpp:17:0: ../../dist/include/OggReader.h:14:26: fatal error: vorbis/codec.h: No such file or directory #include <vorbis/codec.h> ^ compilation terminated. /sources2/mozilla-release/config/rules.mk:1001: recipe for target 'DecoderTraits.o' failed make: *** [DecoderTraits.o] Error 1 make: Leaving directory '/sources2/mozilla-release/firefox-build-dir/content/media' /sources2/mozilla-release/config/recurse.mk:95: recipe for target 'content/media/compile' failed make: *** [content/media/compile] Error 2 .... make: Leaving directory '/sources2/mozilla-release/firefox-build-dir/content/svg/content/src' make: Leaving directory '/sources2/mozilla-release/firefox-build-dir' /sources2/mozilla-release/config/recurse.mk:39: recipe for target 'compile' failed make: *** [compile] Error 2 make: Leaving directory '/sources2/mozilla-release/firefox-build-dir' /sources2/mozilla-release/config/rules.mk:592: recipe for target 'default' failed make: *** [default] Error 2 make: Leaving directory '/sources2/mozilla-release/firefox-build-dir' /sources2/mozilla-release/client.mk:400: recipe for target 'realbuild' failed make: *** [realbuild] Error 2 make: Leaving directory '/sources2/mozilla-release' client.mk:187: recipe for target 'build' failed make: *** [build] Error 2
The above error is interesting, as I have “–disable-webm” in the mozconfig file. It nevertheless insists on referencing vorbis/codec.h.
Ensuring all requirements for webm (primarily, yasm) and then removing the “–disable-webm” fixed this. In other words, “–disable-webm” doesn’t work for this release of firefox.
It is sad the step of installing ca certificates is so complicated.
Installing the certs is worth doing if you intend to use the LFS install long-term, but it is not absolutely necessary if you are just experimenting/learning - at least I got X + firefox working without them.
Here is some background info on networking that may be helpful to understand some of the LFS/BLFS content. The book chapters on networking assume significant amounts of background knowledge; in particular they mention bridges and virtual lans without mentioning what they are.
The LBFS Ch14 “Advanced Network Setup” page describes how to set up a “network bridge” but doesn’t describe what one is.
A bridge is a “virtual network switch” that acts similarly to a physical switch device.
A physical switch has N end devices connected to it, some of which may be other switches. A switch watches the traffic passing across the network and builds a table of which MAC-addresses (level-2 switch) or IP-addresses (level-3 switch) are connected to which physical port. It then forwards incoming traffic for that address to just the relevant port rather than to all ports (as a hub would do).
Similarly, a Linux server’s sysadmin can define multiple network interfaces, each with its own mac adddress and connect them to a software bridge. Each interface can have its own IP address (allocated statically or by DHCP). Apps can perform normal socket operations on that interface. The virtual bridge will route outgoing traffic from one interface directly to other local interfaces without passing over the physical network card. If one of the interfaces attached to the software bridge happens to be a real interface (ie associated with a real network card) then “broacast packets” sent over the bridge will be passed on via that real interface too, and the virtual bridge will (as usual) build up a list of MAC addresses accessible via that “port” meaning that traffic sent by one of the “virtual” interfaces on the bridge can reach the real network.
A software bridge can also be used in a device with two network cards to “join” the networks, just as a physical switch could do. Create a software bridge, add two physical interfaces to it, and the networks are connected - ie level-2 broadcast packets sent on one network will be forwarded to the other. This works even if different physical network technologies are used, as long as they use the same level-2 protocol.
To phrase it another way: a logical bridge can be seen as a “container” for the interfaces that are attached to it. All the attached interfaces can be logical, in which case you have just built a virtual network within your host which is not connected to the outside world, but otherwise can be used to emulate a set of interacting networked devices. When one (or more) of the attached interfaces are physical NICs (network interface cards) then these cards will emit packets with multiple associated MAC addresses rather than the usual one MAC address.
Interestingly, a physical switch (bridge) device won’t do firewalling - but a virtual bridge in Linux can, via iptables rules.
More sophisticated physical network switches can be configured to regard a subset of ports as being a “virtual LAN”. For example, a network switch with 8 ports may be configured so that ports 1..4 are one virtual network, and ports 5..8 are a different network. The result is as if there were two physical network switches; a broadcast packet originating from port 1 would be forward to ports 2..4 but no others. Internally this is achieved by “tagging” incoming packets with a “vlan id”; this id is only valid within the switch.
This process is conceptually the reverse of “bridging”; if such a network-switch happened to be running Linux (switches generally dont have an operating-system), and somebody set up a bridge connecting the two vlans configured above, then the two would cancel each other out, ie ports 1..8 would be a single network again.
Linux allows the creation of “virtual interfaces” as subinterfaces of a “physical interface”. When the physical interface is named “eth0” then the virtual interfaces will be named “eth0.1”, “eth0.2”, etc. Each virtual interface has its own IP address, but shares the MAC address of the physical interface. This covers some of the same use-cases as bridging but not all.
This is not related to “Virtual LANs” as supported by switches.