Part of the Fathom-OS Project Log.
Chapter 4 sets up the environment that Chapters 5 and 6 depend on entirely. This includes creating the directory layout inside the LFS partition, adding a dedicated unprivileged build user, and configuring a clean isolated shell environment for that user. Nothing from the host system bleeds into the build after this point.
References:
- LFS 13.0-systemd - 4.2 Creating a Limited Directory Layout
- LFS 13.0-systemd - 4.3 Adding the LFS User
- LFS 13.0-systemd - 4.4 Setting Up the Environment
Section 4.2: Creating the Directory Layout
The first step is creating a minimal directory structure inside $LFS. The temporary tools built in Chapters 5 and 6 install here, and they get overwritten by the real versions in Chapter 8. The layout needs to exist first so those installs have somewhere to go.
These commands run as dayotte with sudo:
sudo mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}
for i in bin lib sbin; do
sudo ln -sv usr/$i $LFS/$i
done
case $(uname -m) in
x86_64) sudo mkdir -pv $LFS/lib64 ;;
esac
sudo mkdir -pv $LFS/tools
Output:
mkdir: created directory '/lfs/etc'
mkdir: created directory '/lfs/var'
mkdir: created directory '/lfs/usr'
mkdir: created directory '/lfs/usr/bin'
mkdir: created directory '/lfs/usr/lib'
mkdir: created directory '/lfs/usr/sbin'
'/lfs/bin' -> 'usr/bin'
'/lfs/lib' -> 'usr/lib'
'/lfs/sbin' -> 'usr/sbin'
mkdir: created directory '/lfs/lib64'
mkdir: created directory '/lfs/tools'
The bin, lib, and sbin entries under $LFS are symlinks pointing to their counterparts under $LFS/usr. The lib64 directory is created because this is an x86_64 build. The book specifically warns never to create a /usr/lib64 directory. If it appears for any reason it will break the system.
The tools directory is where the cross-compiler and temporary tools will live during Chapters 5 and 6.
Section 4.3: Adding the LFS User
The book requires all packages in Chapters 5 and 6 to be built as an unprivileged user. Running as root during compilation means a single mistake could damage the host system. The dedicated lfs user contains that risk.
sudo groupadd lfs
sudo useradd -s /bin/bash -g lfs -m -k /dev/null lfs
sudo passwd lfs
The lfs group and user already existed from a previous build attempt. The password was reset and everything proceeded normally.
Give the lfs user ownership of the directories it needs to write to:
sudo chown -v lfs $LFS/{usr{,/*},var,etc,tools}
case $(uname -m) in
x86_64) sudo chown -v lfs $LFS/lib64 ;;
esac
Output:
changed ownership of '/lfs/usr' from root to lfs
changed ownership of '/lfs/usr/bin' from root to lfs
changed ownership of '/lfs/usr/lib' from root to lfs
changed ownership of '/lfs/usr/sbin' from root to lfs
changed ownership of '/lfs/var' from root to lfs
changed ownership of '/lfs/etc' from root to lfs
changed ownership of '/lfs/tools' from root to lfs
changed ownership of '/lfs/lib64' from root to lfs
Section 4.4: Setting Up the Environment
This section runs partly as dayotte and partly as lfs. The order matters.
Neutralize /etc/bash.bashrc (run as dayotte)
Some distributions add an /etc/bash.bashrc file that can silently modify the lfs user’s environment and interfere with the build. The book requires moving it out of the way before switching to the lfs user. This is easy to miss as it is buried in an Important callout in the middle of Section 4.4.
sudo bash -c '[ ! -e /etc/bash.bashrc ] || mv -v /etc/bash.bashrc /etc/bash.bashrc.NOUSE'
Output:
renamed '/etc/bash.bashrc' -> '/etc/bash.bashrc.NOUSE'
The file existed and was moved. It can be restored after the build is complete if needed.
Switch to the lfs User
su - lfs
The - flag starts a login shell, which is required for the .bash_profile to be read correctly.
Create .bash_profile
cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF
This replaces the running shell with a completely clean environment, keeping only HOME, TERM, and PS1. Nothing from the host environment carries over.
Create .bashrc
cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF
Note: LFS=/lfs is used here instead of the book’s example of /mnt/lfs to match the actual mount point on this build host.
set +h disables bash’s hash function so the shell always finds the newly built tools in $LFS/tools/bin rather than caching the path to older host versions.
LFS_TGT sets the cross-compilation target triplet to x86_64-lfs-linux-gnu.
CONFIG_SITE prevents configure scripts from pulling in host-specific configuration during the cross-compilation chapters.
Add MAKEFLAGS
cat >> ~/.bashrc << "EOF"
export MAKEFLAGS=-j$(nproc)
EOF
This tells make to use all available logical cores. The build host has 10 vCPUs so $(nproc) returns 10. Never pass -j without a number, the book specifically warns this will cause make to spawn infinite jobs and destabilize the system.
Source the Profile
source ~/.bash_profile
Verify the Environment
echo $LFS
echo $LFS_TGT
echo $MAKEFLAGS
umask
Output:
/lfs
x86_64-lfs-linux-gnu
-j10
0022
All four confirmed correct.
What Is Next
Chapter 4 is complete. The build environment is isolated, the lfs user is in place, and the directory structure is ready. The next step is Chapter 5, which begins the cross-compilation toolchain.
More updates to follow as each build phase completes.
Previous: Chapter 3: Packages and Patches | Next: Chapter 5: Compiling a Cross-Toolchain
All session notes and build logs are committed to the private repository at github.com/QuietWireDev/fathom-os.


