πŸ“– LFS Series β€” Part 6 of 15 | Previously: Part 5: Temporary Tools

Up until now, you've been a tourist. Building tools on the host, placing them carefully into $LFS, arranging furniture in a house you've never entered. That changes today.

Chapter 7 is the moment you walk through the front door.

You chroot into your new system, and for the first time, commands run inside your Linux. Not on the host. Not cross-compiled. Inside. The system takes its first breath.

LFS Book β€” Chapter 7

Changing Ownership

Everything under $LFS was built by the lfs user. That user doesn't exist inside the new system. There's no /etc/passwd yet, no user database, nothing. If files are owned by a UID that doesn't map to anything, things break in subtle, maddening ways.

So root takes over:

chown -R root:root $LFS/{usr,lib,var,etc,bin,sbin,tools,lib64}

Simple command. Important principle: inside chroot, root is the only identity that exists. Everything must belong to it.

What if I skip this?

Files owned by UID 1000 (the lfs user on the host) will appear owned by a nonexistent user inside chroot. Some build systems check ownership. Some installers refuse to run. You'll chase phantom permission errors for hours. Don't skip it.

Virtual Kernel Filesystems

This is the most conceptual part of the entire LFS build. Pay attention.

Your new system has no kernel. It's a directory tree with some binaries. But Linux programs expect certain filesystems to exist β€” not on disk, but in memory, provided by the running kernel. These are virtual kernel filesystems, and without them, your chroot is deaf, blind, and mute.

mount -v --bind /dev $LFS/dev
mount -vt devpts devpts -o gid=5,mode=0620 $LFS/dev/pts
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run

What each one does:

  • /dev β€” Device files. /dev/null, /dev/zero, /dev/sda, your terminals. We bind-mount the host's /dev because the host kernel manages these. No kernel, no devices β€” so we borrow the host's.
  • /dev/pts β€” Pseudo-terminal devices. Every terminal session you open gets one. Without this, you can't allocate new terminals inside chroot.
  • /proc β€” Process information. /proc/cpuinfo, /proc/meminfo, /proc/self. Dozens of programs read from /proc. It's how userspace talks to the kernel about processes and system state.
  • /sys β€” Hardware and driver info. The kernel's structured view of devices, buses, and firmware. Programs like udev depend on it.
  • /run β€” Runtime variable data. PID files, lock files, sockets. A tmpfs because none of this should survive a reboot.

Think of it this way: your chroot is a body. These mounts are the nervous system connecting it to the brain (the host kernel). Without them, the body can't feel, can't see, can't move.

What if I skip this?

Almost nothing works. bash itself might start, but any program that reads /proc (which is most of them) will fail. Compilation will break. Device access will fail. You'll get cryptic errors that make no sense until you realize the system literally cannot see itself.

The Chroot Command

This is it. The moment:

chroot "$LFS" /usr/bin/env -i \
    HOME=/root TERM="$TERM" \
    PS1='(lfs chroot) \u:\w$ ' \
    PATH=/usr/bin:/usr/sbin \
    MAKEFLAGS='-j8' \
    /bin/bash --login

Let's break it down piece by piece:

  • chroot "$LFS" β€” Changes the root directory. After this, / means $LFS. The host filesystem vanishes. Gone. You can't see it, can't access it. You're inside.
  • /usr/bin/env -i β€” The -i flag wipes the environment completely. Every variable from the host β€” PATH, HOME, LD_LIBRARY_PATH, everything β€” erased. You start clean. Nothing leaks from the host into your new system.
  • HOME=/root β€” Sets the home directory. Basic necessity.
  • TERM="$TERM" β€” Inherits the terminal type so your shell renders correctly. One of the few things worth keeping from the host.
  • PS1='(lfs chroot) \u:\w$ ' β€” Changes your prompt. This is a safety net. When you see (lfs chroot) root:/$, you know exactly where you are. Trust me, you want this. Accidentally running commands on the host when you think you're in chroot (or vice versa) is a classic mistake.
  • PATH=/usr/bin:/usr/sbin β€” Notice what's NOT here: /tools/bin. The cross-toolchain served its purpose. From now on, everything runs from /usr.
  • MAKEFLAGS='-j8' β€” Parallel compilation. Adjust to your core count.
  • /bin/bash --login β€” Start a login shell. You're in.

Your prompt changes. The filesystem root changes. The environment is clean. You are now inside your Linux system.

Creating the Filesystem Layout

An OS needs structure. You wouldn't move into a house that's just one giant empty room. The Filesystem Hierarchy Standard (FHS) defines where everything goes in a Unix system. We build that skeleton now:

mkdir -pv /{boot,home,mnt,opt,srv}
mkdir -pv /etc/{opt,sysconfig}
mkdir -pv /lib/firmware
mkdir -pv /media/{floppy,cdrom}
mkdir -pv /usr/{,local/}{include,src}
mkdir -pv /usr/local/{bin,lib,sbin}
mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man}
mkdir -pv /usr/{,local/}share/man/man{1..8}
mkdir -pv /var/{cache,local,log,mail,opt,spool}

What the top-level directories are for:

DirectoryPurpose
/bootBootloader and kernel images
/etcSystem configuration files
/homeUser home directories
/mntTemporary mount points
/optOptional/third-party software
/srvData for services (web, FTP)
/lib/firmwareHardware firmware blobs
/mediaRemovable media mount points
/usrUser programs, libraries, docs β€” the bulk of the system
/usr/localLocally installed software (not from the package manager)
/varVariable data β€” logs, caches, mail spools

Every directory has a reason. Every path is a convention that thousands of programs rely on. This isn't bureaucracy β€” it's the contract between your OS and every piece of software that will ever run on it.

Essential Files and Symlinks

A Unix system needs certain files to exist before it can function. Not optional. Required.

/etc/passwd β€” the user database:

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/usr/bin/false
daemon:x:6:6:Daemon User:/dev/null:/usr/bin/false
nobody:x:65534:65534:nobody:/dev/null:/usr/bin/false

/etc/group β€” the group database:

root:x:0:
bin:x:1:daemon
sys:x:2:
tty:x:5:
daemon:x:6:
...

These aren't just config files. Programs call getpwnam() and getgrnam() to look up users and groups. Without these files, those calls fail, and builds break.

Critical symlinks:

ln -sv /usr/bin/bash /bin/sh
ln -sv /usr/bin/bash /usr/bin/sh

Nearly every shell script starts with #!/bin/sh. If /bin/sh doesn't exist, nothing runs. We point it at bash for now.

We also create log files (/var/log/btmp, /var/log/lastlog, /var/log/wtmp) so that login tracking works from the start.

Building Inside Chroot β€” Six Packages

Now the system builds software for itself, by itself. No more cross-compilation. No more host tools. The compiler inside chroot compiles code that runs inside chroot. Self-sufficiency begins.

Six packages, each chosen because later builds depend on them:

Gettext

Internationalization framework. Provides msgfmt, msgmerge, xgettext. Many packages include translated strings and need Gettext's tools during make install. We only build the minimum subset needed β€” the full build comes in Chapter 8.

Bison

Parser generator. The GNU replacement for yacc. If a package has a .y grammar file, Bison turns it into C code. Several Chapter 8 packages need it. Without Bison, those builds fail at the configure stage.

Perl

The duct tape of Unix build systems. Autoconf generates configure scripts, but many packages ship Perl-based build helpers, test suites, and code generators. Perl is so deeply woven into the Unix build ecosystem that almost nothing compiles without it.

Python

Needed primarily for the Meson build system, which is written in Python. An increasing number of packages (Systemd, GLib, Mesa) use Meson instead of Autotools. No Python, no Meson, no building those packages.

Texinfo

Documentation tools. Provides makeinfo, which converts .texi source files into Info pages. Many GNU packages run makeinfo during their build process. If it's missing, builds either fail or skip documentation with warnings that pollute your logs.

Util-linux

The Swiss Army knife of system utilities: mount, umount, dmesg, fdisk, lsblk, kill, more, su. These are the basic tools you need to manage a Unix system. We need a few of them for Chapter 8 builds.

Total build time for all six: ~10 minutes. Fast, because these are temporary stripped-down builds. The final, fully-configured versions come in Chapter 8.

The Result

After Chapter 7, take a look around:

(lfs chroot) root:/$ ls /usr/bin | wc -l
354
(lfs chroot) root:/$ ls /usr/lib/*.so* | wc -l
34

354 binaries. 34 shared libraries.

This isn't a complete system. There's no kernel. No bootloader. No init system. No network stack. But it's alive. It has a shell. It has a compiler. It has Perl, Python, and core utilities. It can process text, parse grammars, and build software.

It's an embryo with a heartbeat.

Chapter 8 will take this foundation and build the remaining ~70 packages that make up a complete Linux system. That's the marathon. This was the starting line.

Cleanup

Before moving on, we strip unnecessary content to reclaim space:

rm -rf /usr/share/{info,man,doc}/*
find /usr/{lib,libexec} -name "*.la" -delete
rm -rf /tools

Documentation, libtool archives, and the temporary /tools directory β€” all gone. The /tools removal is symbolic: the cross-toolchain's job is done. Everything from here forward is built natively.

What if I skip cleanup?

Nothing breaks. You waste some disk space. But removing /tools is good practice β€” it prevents accidental use of cross-compiled tools when you should be using native ones.

What Just Happened

Let's zoom out. In Parts 4 and 5, you built tools on the host that targeted the new system. You were standing outside, reaching in. In Part 6, you stepped inside. The perspective flipped entirely.

The chroot boundary is more than a filesystem trick. It's a conceptual boundary. Everything before it was preparation. Everything after it is construction. You're no longer building for your system. You're building in it.

Next up: Chapter 8. The big one. ~70 packages. The full GNU toolchain, core libraries, system utilities β€” everything a Linux system needs to stand on its own.

The foundation is set. Time to build the house.


Compiled by AI. Proofread by caffeine. β˜•


πŸ“– LFS Series Navigation
← Previous: Part 5: Temporary Tools
β†’ Next: Part 7: Coming soon