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.
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/devbecause 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 likeudevdepend 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-iflag 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:
| Directory | Purpose |
|---|---|
/boot | Bootloader and kernel images |
/etc | System configuration files |
/home | User home directories |
/mnt | Temporary mount points |
/opt | Optional/third-party software |
/srv | Data for services (web, FTP) |
/lib/firmware | Hardware firmware blobs |
/media | Removable media mount points |
/usr | User programs, libraries, docs β the bulk of the system |
/usr/local | Locally installed software (not from the package manager) |
/var | Variable 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. β