
Figure 1: Screenshot of my LFS VM's GNOME session as of 12 July 2026.
I first installed LFS 12.4 systemd edition to a virtual machine on 9 February 2026. Since then, I have upgraded the system to the development systemd branch, and kept the system up to date. It has been a challenging, yet informative journey.
From my NixOS host machine, I have written — with the help of artificial intelligence (AI) — several shell functions that are imported into my LFS VM and provide basic package management functionality. These functions are part of both my host's and VM's shell profile. These functions can be found in my NixOS configuration user shell profile.
Table 1: Shell functions used for package management within the LFS VM. | Function name | Defined in | Syntax | Description |
| Guest | Host |
autobuild | lfs_autobuild | lfs-autobuild.sh | autobuild PACKAGE(S) [OPTION(S)] | Default: build and install the specified package(s), if and only if the latest version of the package is not already installed. LFS/Beyond LFS (BLFS) instructions are used to build most packages. Although, some packages are built using custom build scripts defined in ~/lfs_packaging. --dry-run: show what actions would be executed to build and install the package. --strip: run stripping commands after build. --no-upstream: disable upstream version searching. --include-config: include configuration commands in the LFS/BLFS book entry. --rm-libs: remove old library versions after build (disabled by default). --lfs: search only in the LFS book. --blfs: search only in the BLFS book. --lfs-book : specify LFS book (e.g., development, systemd, stable, or full URL). --blfs-book : specify BLFS book (e.g., systemd, development, stable, or full URL). --skip-tests: skip test commands (make check/test, etc.). --ignore-test-failures: ignore test failures by appending '|| true' to test commands. -f/--force: force rebuild and installation even when latest version is already installed. -h/--help: show help message. |
autoremove | lfs_autoremove | 21-lfs.sh | autoremove PACKAGE(S) [OPTION(S)] | Default: remove the specified package(s), if and only if no other packages have libraries that depend on the package(s). --dry-run: show what actions would be executed to remove the package. -f/--force: force removal, without regard for library dependencies. |
| N/A | cleanup_old_libraries_gpt | 21-lfs.sh | cleanup_old_libraries_gpt | Remove old unused libraries. As for used old used libraries, rebuild packages that depend on the library and then remove it. |
| N/A | cleanup_old_doc_dirs_gpt | 21-lfs.sh | cleanup_old_doc_dirs_gpt | Remove old unused documentation directories. |
update | lfs_update | 21-lfs.sh | update [OPTION(s)] | Update packages. --dry-run: Show what would be updated without downloading/building. --no-upstream: Check only LFS/BLFS book versions (disable upstream tracking). -h/--help: Show help message. |
updates | lfs_updates | lfs-updates.sh | updates | Print table that list available updates (marked with [UPDATE]), as well as packages with missing inventories (marked with [FILES MISSING]) and packages with versioning failures (marked with [FAILED]). |
Package inventories are stored within /var/lib/book-packages for LFS/BLFS packages and /var/lib/custom-packages for custom packages.
These are defined in ~/lfs_apps. They include desktop configuration files that generate plots of boot times and cycle through wallpapers.
~/lfs_packaging provides custom build scripts to install many packages. Some of these packages are also provided by LFS and BFLS — such as Linux PAM, Vim, rustc and packages within the xorg-apps and xorg-libs metapackages. I provide these custom packages sometimes to overcome build errors that the book-extraction function cause and other times to more robustly ensure I have the latest version of these packages at all times. Other packages are provided in this repository because LFS and BLFS do not provide them; other books in the LFS such as SLFS do provide some of these packages, but some are unique to this repository (e.g. GNU Octave and R are).
I have also customized Fastfetch/HyFetch output so that it accurately prints the number of packages I have installed. The configuration file used is located in ~/lfs-scripts/config.jsonc. In the screenshot above, 807 ( 573, 130, 1, 74, 29) means that 807 packages are installed in total. Of them 573 are LFS or BLFS book packages installed via autobuild and its extracting build commands and source URLs from the books' webpages. A further 130 were installed via custom build scripts in ~/lfs_packaging. 1 Julia package was installed; this package is Julia itself which was installed via juliaup (the compilation process of Julia is incredibly complex and even requires its own custom build of LLVM). 74 Python packages were installed via pip. 29 R packages were installed.
My shell profile is defined in ~/lfs-scripts. Some scripts called for by GNOME and KDE Plasma Executor/Command Output commands are in this repository, too.
GNOME was the first desktop I installed. Its packages are kept at the latest upstream version, not merely the latest version in the BLFS book. Dash to Dock is enabled and installed, as is WeatherPanel and Show Desktop Button. Executor is another extension I use; I've actually created my own fork with more features.
Installed via the executor ~/lfs_packaging package. It can be installed via more standard ways, too.
The base executor extension provides up to three widgets in the GNOME panel on the left, centre and right of the panel. In these widgets is displayed the output of specified commands. The interval at which the command is re-run can also be specified. The executor fork I maintain provides the following additional features:
Tooltips, which can include command output at their end as well as the static text within the widget that precedes the command output; and
Command execution upon clicking the widget in the panel. Left, middle and right click options are specifiable.
Includes:
count-wallpapers.sh — displays the number of the currently shown wallpaper / the total number of wallpapers in ~/wallpapers. In my set up, it is used to generate output by the centre widget.
list-wallpaper.sh — displays the list of wallpapers in ~/wallpapers with the currently shown wallpaper highlighted and centred. gnome-terminal -- zsh -ic "~/lfs-scripts/list-wallpapers.sh" is run when left-clicking the centre widget in my setup.
open-wallpaper.sh — opens the displayed wallpaper in Eye of GNOME. This script is run when I right-click the centre widget in my setup.
updates_no.sh — checks for updates using the updates command in the shell profile. It displays $in_progress $mod_time $no_updates $no_missing_total $no_failed where $in_progress is replaced with nothing if the updates command is not running, and ${percent}% otherwise, where $percent is an approximation of how far through the running of updates we are. $mod_time is replaced with the time the updates command last stopped running. $no_updates is replaced with the number of available package updates. $no_missing_total is replaced with the number of packages with missing inventories. $no_failed is replaced with the number of package versioning failures.
update-table.sh — generates a more compact table of packages with updates, missing inventories and versioning failures. It is run to generate the tooltip for the right widget.
Left-clicking the right widget opens a terminal in which update is run. Middle-clicking the right widget re-runs updates to update the displayed values. Right-clicking the right widget runs tail -f ~/updates.log (~/updates.log contains the output of the last updates run).
KDE Plasma was the second desktop I installed. Panel Spacer Extended extension is installed, as is the Command Output Plasma widget.