Welcome to Linux From Scratch! >_<

LFS >.<

What is Linux From Scratch (LFS)?
LFS is a project that provides step-by-step instructions for building your own custom Linux system entirely from source code. You'll compile everything yourself, from the kernel to the shell!
⚠️ WARNING: This process takes 6-20 hours depending on your hardware and can be quite challenging. Make sure you have patience and a good understanding of Linux basics before starting!

What you'll learn:

  • How Linux systems are constructed from the ground up
  • The relationship between kernel, libraries, and userspace
  • Cross-compilation and toolchain building
  • Package management without package managers
  • System initialization and boot processes

Table of Contents 📋

Chapter 1: Requirements & Preparation

What You'll Need

Step 1.1: Hardware Requirements

Minimum System Requirements:

  • CPU: Any x86_64 processor (Intel/AMD 64-bit)
  • RAM: 4GB minimum, 8GB+ recommended
  • Storage: 20GB free space minimum, 50GB+ recommended
  • Time: 6-20 hours depending on hardware
Step 1.2: Host System Requirements

You need a working Linux system to build LFS. The following distributions work well as host systems:

  • Ubuntu 20.04+ / Debian 11+
  • Fedora 35+ / CentOS Stream 9+
  • Arch Linux (current)
  • openSUSE Leap 15.4+
⚠️ Important: Do NOT attempt LFS on Windows Subsystem for Linux (WSL) or in a container. You need a real Linux system with full hardware access!
Step 1.3: Required Host System Packages

Install these packages on your host system before starting:

For Ubuntu/Debian:

sudo apt update sudo apt install -y build-essential bison flex texinfo gawk m4 \ libncurses5-dev libssl-dev bc kmod cpio python3 python3-pip \ rsync wget curl git vim nano

For Fedora/CentOS:

sudo dnf groupinstall -y "Development Tools" sudo dnf install -y bison flex texinfo gawk m4 ncurses-devel \ openssl-devel bc kmod cpio python3 python3-pip rsync wget \ curl git vim nano

For Arch Linux:

sudo pacman -S base-devel bison flex texinfo gawk m4 \ ncurses openssl bc kmod cpio python python-pip rsync wget \ curl git vim nano
Step 1.4: Version Check Script

Run this script to verify your host system has the required tool versions:

#!/bin/bash # version-check.sh - LFS Host System Requirements Checker export LC_ALL=C bash --version | head -n1 | cut -d" " -f2-4 MYSH=$(readlink -f /bin/sh) echo "/bin/sh -> $MYSH" echo $MYSH | grep -q bash || echo "ERROR: /bin/sh does not point to bash" unset MYSH echo -n "Binutils: "; ld --version | head -n1 | cut -d" " -f3- bison --version | head -n1 if [ -h /usr/bin/yacc ]; then echo "/usr/bin/yacc -> `readlink -f /usr/bin/yacc`"; elif [ -x /usr/bin/yacc ]; then echo yacc is `/usr/bin/yacc --version | head -n1` else echo "yacc not found" fi echo -n "Coreutils: "; chown --version | head -n1 | cut -d")" -f2 diff --version | head -n1 find --version | head -n1 gawk --version | head -n1 if [ -h /usr/bin/awk ]; then echo "/usr/bin/awk -> `readlink -f /usr/bin/awk`"; elif [ -x /usr/bin/awk ]; then echo awk is `/usr/bin/awk --version | head -n1` else echo "awk not found" fi gcc --version | head -n1 g++ --version | head -n1 grep --version | head -n1 gzip --version | head -n1 cat > version-check.c << "EOF" #include int main() { printf("Compilation successful\n"); return 0; } EOF gcc -o version-check version-check.c if [ -x version-check ]; then echo "gcc compilation OK"; else echo "gcc compilation failed"; fi rm -f version-check.c version-check m4 --version | head -n1 make --version | head -n1 patch --version | head -n1 echo Perl `perl -V:version` python3 --version sed --version | head -n1 tar --version | head -n1 makeinfo --version | head -n1 # texinfo version xz --version | head -n1 echo 'int main(){}' > dummy.c && g++ -o dummy dummy.c if [ -x dummy ] then echo "g++ compilation OK"; else echo "g++ compilation failed"; fi rm -f dummy.c dummy

Save this as version-check.sh, make it executable, and run it:

chmod +x version-check.sh ./version-check.sh
Expected Output: All tools should show version numbers. If any tool is missing or too old, install/update it before proceeding.
Chapter 2: Preparing the Host System

Setting Up Your Build Environment

Step 2.1: Create the LFS User

For security and isolation, we'll create a dedicated user for building LFS:

sudo groupadd lfs sudo useradd -s /bin/bash -g lfs -m -k /dev/null lfs sudo passwd lfs

Grant the lfs user sudo privileges:

sudo usermod -aG sudo lfs
Step 2.2: Set Up Environment Variables

Switch to the lfs user and set up the build environment:

su - lfs

Create the .bashrc file for the lfs user:

cat > ~/.bashrc << "EOF" set +h umask 022 LFS=/mnt/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
Environment Variables Explained:
LFS: Mount point for the LFS partition
LFS_TGT: Target triplet for cross-compilation
PATH: Ensures we use the right tools
set +h: Disables bash hash function

Source the new environment:

source ~/.bashrc echo $LFS
Step 2.3: Create Directory Structure

Create the basic directory structure for LFS:

sudo mkdir -pv $LFS sudo chown -v lfs $LFS mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin} for i in bin lib sbin; do ln -sv usr/$i $LFS/$i done case $(uname -m) in x86_64) mkdir -pv $LFS/lib64 ;; esac mkdir -pv $LFS/tools
⚠️ Critical: The $LFS variable must be set correctly! Double-check with echo $LFS - it should show /mnt/lfs
Chapter 3: Downloading Source Packages

Getting the Source Code

Step 3.1: Create Sources Directory
mkdir -pv $LFS/sources chmod -v a+wt $LFS/sources
Step 3.2: Download Package List

Create a wget list file with all required packages:

cat > $LFS/sources/wget-list << "EOF" https://download.savannah.gnu.org/releases/acl/acl-2.3.1.tar.xz https://download.savannah.gnu.org/releases/attr/attr-2.5.1.tar.gz https://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.xz https://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.xz https://ftp.gnu.org/gnu/bash/bash-5.2.15.tar.gz https://github.com/gavinhoward/bc/releases/download/6.0.1/bc-6.0.1.tar.xz https://ftp.gnu.org/gnu/binutils/binutils-2.39.tar.xz https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.xz https://www.sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz https://github.com/libcheck/check/releases/download/0.15.2/check-0.15.2.tar.gz https://ftp.gnu.org/gnu/coreutils/coreutils-9.1.tar.xz https://ftp.gnu.org/gnu/dejagnu/dejagnu-1.6.3.tar.gz https://ftp.gnu.org/gnu/diffutils/diffutils-3.8.tar.xz https://downloads.sourceforge.net/project/e2fsprogs/e2fsprogs/v1.46.5/e2fsprogs-1.46.5.tar.gz https://sourceware.org/ftp/elfutils/0.187/elfutils-0.187.tar.bz2 https://prdownloads.sourceforge.net/expat/expat-2.4.8.tar.xz https://prdownloads.sourceforge.net/expect/expect5.45.4.tar.gz https://astron.com/pub/file/file-5.42.tar.gz https://ftp.gnu.org/gnu/findutils/findutils-4.9.0.tar.xz https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz https://ftp.gnu.org/gnu/gawk/gawk-5.1.1.tar.xz https://ftp.gnu.org/gnu/gcc/gcc-12.2.0/gcc-12.2.0.tar.xz https://ftp.gnu.org/gnu/gdbm/gdbm-1.23.tar.gz https://ftp.gnu.org/gnu/gettext/gettext-0.21.tar.xz https://ftp.gnu.org/gnu/glibc/glibc-2.36.tar.xz https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xz https://ftp.gnu.org/gnu/gperf/gperf-3.1.tar.gz https://ftp.gnu.org/gnu/grep/grep-3.7.tar.xz https://ftp.gnu.org/gnu/groff/groff-1.22.4.tar.gz https://ftp.gnu.org/gnu/grub/grub-2.06.tar.xz https://ftp.gnu.org/gnu/gzip/gzip-1.12.tar.xz https://github.com/Mic92/iana-etc/releases/download/20220812/iana-etc-20220812.tar.gz https://ftp.gnu.org/gnu/inetutils/inetutils-2.3.tar.xz https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz https://www.kernel.org/pub/linux/utils/net/iproute2/iproute2-5.19.0.tar.xz https://files.pythonhosted.org/packages/source/J/Jinja2/Jinja2-3.1.2.tar.gz https://www.kernel.org/pub/linux/utils/kbd/kbd-2.5.1.tar.xz https://www.kernel.org/pub/linux/utils/kernel/kmod/kmod-30.tar.xz https://www.greenwoodsoftware.com/less/less-590.tar.gz https://www.kernel.org/pub/linux/libs/security/linux-pam/library/Linux-PAM-1.5.2.tar.xz https://github.com/libffi/libffi/releases/download/v3.4.2/libffi-3.4.2.tar.gz https://download.savannah.gnu.org/releases/libpipeline/libpipeline-1.5.6.tar.gz https://ftp.gnu.org/gnu/libtool/libtool-2.4.7.tar.xz https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.19.2.tar.xz https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz https://ftp.gnu.org/gnu/make/make-4.3.tar.gz https://download.savannah.gnu.org/releases/man-db/man-db-2.10.2.tar.xz https://www.kernel.org/pub/linux/docs/man-pages/man-pages-5.13.tar.xz https://github.com/mesonbuild/meson/releases/download/0.63.1/meson-0.63.1.tar.gz https://ftp.gnu.org/gnu/mpc/mpc-1.2.1.tar.gz https://ftp.gnu.org/gnu/mpfr/mpfr-4.1.0.tar.xz https://invisible-mirror.net/archives/ncurses/ncurses-6.3.tar.gz https://github.com/ninja-build/ninja/archive/v1.11.0/ninja-1.11.0.tar.gz https://www.openssl.org/source/openssl-3.0.5.tar.gz https://ftp.gnu.org/gnu/patch/patch-2.7.6.tar.xz https://www.cpan.org/src/5.0/perl-5.36.0.tar.xz https://distfiles.gentoo.org/distfiles/pkgconf-1.8.0.tar.xz https://sourceforge.net/projects/procps-ng/files/Production/procps-ng-4.0.0.tar.xz https://sourceforge.net/projects/psmisc/files/psmisc/psmisc-23.5.tar.xz https://www.python.org/ftp/python/3.10.6/Python-3.10.6.tar.xz https://ftp.gnu.org/gnu/readline/readline-8.1.2.tar.gz https://ftp.gnu.org/gnu/sed/sed-4.8.tar.xz https://github.com/shadow-maint/shadow/releases/download/4.12.2/shadow-4.12.2.tar.xz https://www.infodrom.org/projects/sysklogd/download/sysklogd-1.5.1.tar.gz https://github.com/systemd/systemd/archive/v251/systemd-251.tar.gz https://ftp.gnu.org/gnu/tar/tar-1.34.tar.xz https://sourceforge.net/projects/tcl/files/Tcl/8.6.12/tcl8.6.12-src.tar.gz https://ftp.gnu.org/gnu/texinfo/texinfo-6.8.tar.xz https://www.iana.org/time-zones/repository/releases/tzdata2022c.tar.gz https://www.kernel.org/pub/linux/utils/util-linux/v2.38/util-linux-2.38.1.tar.xz https://cpan.metacpan.org/authors/id/T/TO/TODDR/XML-Parser-2.46.tar.gz https://tukaani.org/xz/xz-5.2.6.tar.xz https://zlib.net/zlib-1.2.12.tar.gz https://github.com/facebook/zstd/releases/download/v1.5.2/zstd-1.5.2.tar.gz EOF
Step 3.3: Download All Packages
cd $LFS/sources wget --input-file=wget-list --continue --directory-prefix=$LFS/sources
💡 Download Tip: This will take a while! The total download is about 500MB. Consider using a download manager or running this overnight.
Step 3.4: Verify Downloads (Optional but Recommended)

Create and run a simple verification script:

cd $LFS/sources ls -la | wc -l echo "Downloaded $(ls -1 | wc -l) files" du -sh .

You should see approximately 50+ source packages totaling around 500MB.

Chapter 4: Preparing the Build Partition

Setting Up Storage

⚠️ DANGER ZONE: The following commands can destroy data! Make sure you're working on the correct partition and have backups!
Step 4.1: Create a New Partition

You need at least 20GB of free space. You can either:

  • Option A: Use an existing empty partition
  • Option B: Create a new partition with fdisk/parted
  • Option C: Use a loop device with a file

Option C (Safest - Using a file):

# Create a 30GB file sudo dd if=/dev/zero of=/home/lfs-build.img bs=1G count=30 # Create a loop device sudo losetup /dev/loop0 /home/lfs-build.img # Create filesystem sudo mkfs.ext4 /dev/loop0 # Set the LFS partition variable export LFS_PARTITION=/dev/loop0

Option A/B (Using real partition):

# List available partitions lsblk # Format the partition (REPLACE /dev/sdXY with your partition!) sudo mkfs.ext4 /dev/sdXY # Set the LFS partition variable export LFS_PARTITION=/dev/sdXY
Step 4.2: Mount the LFS Partition
sudo mkdir -pv /mnt/lfs sudo mount -v -t ext4 $LFS_PARTITION /mnt/lfs sudo chown -v lfs /mnt/lfs
Step 4.3: Make Mount Persistent

Add to /etc/fstab so the partition mounts automatically:

echo "$LFS_PARTITION /mnt/lfs ext4 defaults 1 1" | sudo tee -a /etc/fstab
Verification: Run df -h /mnt/lfs to confirm the partition is mounted and has enough space.
Chapter 5: Building the Cross-Compilation Toolchain

The Heart of LFS

This is where the real magic happens! We'll build a cross-compilation toolchain that can compile programs for our target LFS system.

What's a Cross-Compilation Toolchain?
It's a set of tools (compiler, linker, assembler) that run on your host system but produce binaries for a different target system (our LFS system).
Step 5.1: Build Binutils (Pass 1)

Switch to the lfs user and start building:

su - lfs cd $LFS/sources tar -xf binutils-2.39.tar.xz cd binutils-2.39 mkdir -v build cd build ../configure --prefix=$LFS/tools \ --with-sysroot=$LFS \ --target=$LFS_TGT \ --disable-nls \ --enable-gprofng=no \ --disable-werror make make install
Step 5.2: Build GCC (Pass 1)
cd $LFS/sources tar -xf gcc-12.2.0.tar.xz cd gcc-12.2.0 tar -xf ../mpfr-4.1.0.tar.xz mv -v mpfr-4.1.0 mpfr tar -xf ../gmp-6.2.1.tar.xz mv -v gmp-6.2.1 gmp tar -xf ../mpc-1.2.1.tar.gz mv -v mpc-1.2.1 mpc case $(uname -m) in x86_64) sed -e '/m64=/s/lib64/lib/' \ -i.orig gcc/config/i386/t-linux64 ;; esac mkdir -v build cd build ../configure \ --target=$LFS_TGT \ --prefix=$LFS/tools \ --with-glibc-version=2.36 \ --with-sysroot=$LFS \ --with-newlib \ --without-headers \ --enable-default-pie \ --enable-default-ssp \ --disable-nls \ --disable-shared \ --disable-multilib \ --disable-threads \ --disable-libatomic \ --disable-libgomp \ --disable-libquadmath \ --disable-libssp \ --disable-libvtv \ --disable-libstdcxx \ --enable-languages=c,c++ make make install cd .. cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \ `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/install-tools/include/limits.h
⚠️ Time Warning: GCC compilation can take 1-4 hours depending on your hardware! This is normal. Go make some pancakes! 🥞
Step 5.3: Build Linux API Headers
cd $LFS/sources tar -xf linux-5.19.2.tar.xz cd linux-5.19.2 make mrproper make headers find usr/include -type f ! -name '*.h' -delete cp -rv usr/include $LFS/usr
Step 5.4: Build Glibc
cd $LFS/sources tar -xf glibc-2.36.tar.xz cd glibc-2.36 case $(uname -m) in i?86) ln -sfv ld-linux.so.2 $LFS/lib/ld-lsb.so.3 ;; x86_64) ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64 ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64/ld-lsb-x86-64.so.3 ;; esac patch -Np1 -i ../glibc-2.36-fhs-1.patch mkdir -v build cd build echo "rootsbindir=/usr/sbin" > configparms ../configure \ --prefix=/usr \ --host=$LFS_TGT \ --build=$(../scripts/config.guess) \ --enable-kernel=3.2 \ --with-headers=$LFS/usr/include \ libc_cv_slibdir=/usr/lib make make DESTDIR=$LFS install sed '/RTLDLIST=/s@/usr@@g' -i $LFS/usr/bin/ldd echo 'int main(){}' | $LFS_TGT-gcc -xc - readelf -l a.out | grep ld-linux rm -v a.out
Success Check: The last command should show something like:
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
Chapter 6: Building the Temporary System

Essential Tools

Now we'll build essential tools needed for the final system. This creates a minimal but functional environment.

Step 6.1: Build Libstdc++ (from GCC)
cd $LFS/sources cd gcc-12.2.0 mkdir -v build-libstdc++ cd build-libstdc++ ../libstdc++-v3/configure \ --host=$LFS_TGT \ --build=$(../config.guess) \ --prefix=/usr \ --disable-multilib \ --disable-nls \ --disable-libstdcxx-pch \ --with-gxx-include-dir=/tools/$LFS_TGT/include/c++/12.2.0 make make DESTDIR=$LFS install rm -v $LFS/usr/lib/lib{stdc++,stdc++fs,supc++}.la
Step 6.2: Build M4
cd $LFS/sources tar -xf m4-1.4.19.tar.xz cd m4-1.4.19 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make make DESTDIR=$LFS install
Step 6.3: Build Ncurses
cd $LFS/sources tar -xf ncurses-6.3.tar.gz cd ncurses-6.3 sed -i s/mawk// configure mkdir build pushd build ../configure make -C include make -C progs tic popd ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(./config.guess) \ --mandir=/usr/share/man \ --with-manpage-format=normal \ --with-shared \ --without-normal \ --with-cxx-shared \ --without-debug \ --without-ada \ --disable-stripping \ --enable-widec make make DESTDIR=$LFS TIC_PATH=$(pwd)/build/progs/tic install echo "INPUT(-lncursesw)" > $LFS/usr/lib/libncurses.so
Step 6.4: Build Bash
cd $LFS/sources tar -xf bash-5.2.15.tar.gz cd bash-5.2.15 ./configure --prefix=/usr \ --build=$(sh support/config.guess) \ --host=$LFS_TGT \ --without-bash-malloc make make DESTDIR=$LFS install ln -sv bash $LFS/bin/sh
Step 6.5: Build Coreutils
cd $LFS/sources tar -xf coreutils-9.1.tar.xz cd coreutils-9.1 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) \ --enable-install-program=hostname \ --enable-no-install-program=kill,uptime make make DESTDIR=$LFS install mv -v $LFS/usr/bin/chroot $LFS/usr/sbin mkdir -pv $LFS/usr/share/man/man8 mv -v $LFS/usr/share/man/man1/chroot.1 $LFS/usr/share/man/man8/chroot.8 sed -i 's/"1"/"8"/' $LFS/usr/share/man/man8/chroot.8
Progress Check: You now have basic tools like bash, ls, cp, mv, etc. in your LFS system! We're getting closer to a bootable system.
Step 6.6: Build Additional Essential Tools

Continue building these tools in order (abbreviated for space):

  • Diffutils
  • File
  • Findutils
  • Gawk
  • Grep
  • Gzip
  • Make
  • Patch
  • Sed
  • Tar
  • Xz
# Example for one more tool - Findutils cd $LFS/sources tar -xf findutils-4.9.0.tar.xz cd findutils-4.9.0 ./configure --prefix=/usr \ --localstatedir=/var/lib/locate \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make make DESTDIR=$LFS install
⚠️ Time Investment: Building all temporary tools takes 2-6 hours. Each package follows a similar pattern: extract, configure, make, install. Take breaks!
Chapter 7: Entering Chroot Environment

The Point of No Return

Now we enter the chroot environment where we'll build the final system. This isolates us completely from the host system.

Step 7.1: Change Ownership
sudo chown -R root:root $LFS/{usr,lib,var,etc,bin,sbin,tools} case $(uname -m) in x86_64) sudo chown -R root:root $LFS/lib64 ;; esac
Step 7.2: Prepare Virtual Kernel File Systems
sudo mkdir -pv $LFS/{dev,proc,sys,run} sudo mount -v --bind /dev $LFS/dev sudo mount -v --bind /dev/pts $LFS/dev/pts sudo mount -vt proc proc $LFS/proc sudo mount -vt sysfs sysfs $LFS/sys sudo mount -vt tmpfs tmpfs $LFS/run if [ -h $LFS/dev/shm ]; then sudo mkdir -pv $LFS/$(readlink $LFS/dev/shm) else sudo mount -t tmpfs -o nosuid,nodev tmpfs $LFS/dev/shm fi
Step 7.3: Enter Chroot Environment
sudo chroot "$LFS" /usr/bin/env -i \ HOME=/root \ TERM="$TERM" \ PS1='(lfs chroot) \u:\w\$ ' \ PATH=/usr/bin:/usr/sbin \ /bin/bash --login
🎉 Congratulations! You're now inside your LFS system! The prompt should show (lfs chroot). Everything you do now happens in your custom Linux system.
Step 7.4: Create Essential Directories
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/{misc,terminfo,zoneinfo} mkdir -pv /usr/{,local/}share/man/man{1..8} mkdir -pv /var/{cache,local,log,mail,opt,spool} mkdir -pv /var/lib/{color,misc,locate} ln -sfv /run /var/run ln -sfv /run/lock /var/lock install -dv -m 0750 /root install -dv -m 1777 /tmp /var/tmp
Step 7.5: Create Essential Files
ln -sv /proc/self/mounts /etc/mtab cat > /etc/hosts << EOF 127.0.0.1 localhost $(hostname) ::1 localhost EOF cat > /etc/passwd << "EOF" 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 messagebus:x:18:18:D-Bus Message Daemon User:/run/dbus:/usr/bin/false uuidd:x:80:80:UUID Generation Daemon User:/dev/null:/usr/bin/false nobody:x:65534:65534:Unprivileged User:/dev/null:/usr/bin/false EOF cat > /etc/group << "EOF" root:x:0: bin:x:1:daemon sys:x:2: kmem:x:3: tape:x:4: tty:x:5: daemon:x:6: floppy:x:7: disk:x:8: lp:x:9: dialout:x:10: audio:x:11: video:x:12: utmp:x:13: usb:x:14: cdrom:x:15: adm:x:16: messagebus:x:18: input:x:24: mail:x:34: kvm:x:61: uuidd:x:80: wheel:x:97: users:x:999: nogroup:x:65534: EOF echo "tester:x:101:101::/home/tester:/bin/bash" >> /etc/passwd echo "tester:x:101:" >> /etc/group install -o tester -d /home/tester exec /usr/bin/bash --login
⚠️ Important: From this point forward, you're working entirely within the chroot environment. If you exit, you'll need to re-mount the virtual filesystems and re-enter chroot.
Chapter 8: Building the Final System

The Real Deal

Now we rebuild everything properly for the final system. This creates the permanent, production-ready versions of all tools.

Step 8.1: Build Gettext
cd /sources tar -xf gettext-0.21.tar.xz cd gettext-0.21 ./configure --disable-shared make cp -v gettext-tools/src/{msgfmt,msgmerge,xgettext} /usr/bin
Step 8.2: Build Bison
cd /sources tar -xf bison-3.8.2.tar.xz cd bison-3.8.2 ./configure --prefix=/usr --docdir=/usr/share/doc/bison-3.8.2 make make install
Step 8.3: Build Perl
cd /sources tar -xf perl-5.36.0.tar.xz cd perl-5.36.0 export BUILD_ZLIB=False export BUILD_BZIP2=0 sh Configure -des \ -Dprefix=/usr \ -Dvendorprefix=/usr \ -Dprivlib=/usr/lib/perl5/5.36/core_perl \ -Darchlib=/usr/lib/perl5/5.36/core_perl \ -Dsitelib=/usr/lib/perl5/5.36/site_perl \ -Dsitearch=/usr/lib/perl5/5.36/site_perl \ -Dvendorlib=/usr/lib/perl5/5.36/vendor_perl \ -Dvendorarch=/usr/lib/perl5/5.36/vendor_perl make make install unset BUILD_ZLIB BUILD_BZIP2
Step 8.4: Build Python
cd /sources tar -xf Python-3.10.6.tar.xz cd Python-3.10.6 ./configure --prefix=/usr \ --enable-shared \ --with-system-expat \ --with-system-ffi \ --enable-optimizations make make install
Step 8.5: Build Texinfo
cd /sources tar -xf texinfo-6.8.tar.xz cd texinfo-6.8 ./configure --prefix=/usr make make install
Step 8.6: Build Util-linux
cd /sources tar -xf util-linux-2.38.1.tar.xz cd util-linux-2.38.1 mkdir -pv /var/lib/hwclock ./configure ADJTIME_PATH=/var/lib/hwclock/adjtime \ --libdir=/usr/lib \ --docdir=/usr/share/doc/util-linux-2.38.1 \ --disable-chfn-chsh \ --disable-login \ --disable-nologin \ --disable-su \ --disable-setpriv \ --disable-runuser \ --disable-pylibmount \ --disable-static \ --without-python \ --without-systemd \ --without-systemdsystemunitdir make make install
Final System Progress: You're now building the production versions of all tools. This process involves rebuilding GCC, Glibc, and all other packages with proper optimization and configuration.
⚠️ Marathon Alert: Building the final system takes 4-12 hours! This includes rebuilding GCC (again), Glibc (again), and 60+ other packages. Plan accordingly!
Step 8.7: Clean Up and Strip Debugging Symbols
rm -rf /tmp/* find /usr/lib /usr/libexec -name \*.la -delete find /usr -depth -name $(uname -m)-lfs-linux-gnu\* | xargs rm -rf userdel -r tester
Chapter 9: Configuring and Building the Kernel

The Heart of the System

Time to build the Linux kernel! This is the core of your operating system.

Step 9.1: Extract and Prepare Kernel Source
cd /sources tar -xf linux-5.19.2.tar.xz cd linux-5.19.2 make mrproper
Step 9.2: Configure the Kernel
# Option 1: Use a default configuration make defconfig # Option 2: Interactive configuration (recommended) make menuconfig
Kernel Configuration Tips:
• Enable your filesystem (ext4, etc.)
• Enable your network card driver
• Enable your graphics driver
• Enable USB support
• Enable sound if needed
Step 9.3: Compile the Kernel
make # Install kernel modules make modules_install # Copy kernel to /boot cp -iv arch/x86/boot/bzImage /boot/vmlinuz-5.19.2-lfs-12.0 cp -iv System.map /boot/System.map-5.19.2 cp -iv .config /boot/config-5.19.2
Step 9.4: Install Kernel Documentation
install -d /usr/share/doc/linux-5.19.2 cp -r Documentation/* /usr/share/doc/linux-5.19.2
⚠️ Kernel Compilation Time: This can take 30 minutes to 3 hours depending on your configuration and hardware. The kernel has thousands of files to compile!
Chapter 10: Installing the Bootloader

Making It Bootable

Install GRUB bootloader so your system can actually boot!

Step 10.1: Build and Install GRUB
cd /sources tar -xf grub-2.06.tar.xz cd grub-2.06 ./configure --prefix=/usr \ --sysconfdir=/etc \ --disable-efiemu \ --disable-werror make make install mv -v /etc/bash_completion.d/grub /usr/share/bash-completion/completions
Step 10.2: Install GRUB to Boot Device
⚠️ CRITICAL: Replace /dev/sdX with your actual boot device! This command can make your system unbootable if wrong!
# Install GRUB to MBR (replace /dev/sdX with your disk!) grub-install /dev/sdX # Generate GRUB configuration grub-mkconfig -o /boot/grub/grub.cfg
Step 10.3: Create GRUB Configuration
cat > /boot/grub/grub.cfg << "EOF" # Begin /boot/grub/grub.cfg set default=0 set timeout=5 insmod ext2 set root=(hd0,2) menuentry "GNU/Linux, Linux 5.19.2-lfs-12.0" { linux /boot/vmlinuz-5.19.2-lfs-12.0 root=/dev/sda2 ro } EOF
Configuration Notes:
• Replace (hd0,2) with your boot partition
• Replace /dev/sda2 with your root partition
• Adjust kernel version if different
Chapter 11: Final System Configuration

The Finishing Touches

Step 11.1: Create /etc/fstab
cat > /etc/fstab << "EOF" # Begin /etc/fstab # file system mount-point type options dump fsck # order /dev/sda2 / ext4 defaults 1 1 /dev/sda1 /boot ext4 defaults 1 2 proc /proc proc nosuid,noexec,nodev 0 0 sysfs /sys sysfs nosuid,noexec,nodev 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 tmpfs /run tmpfs defaults 0 0 devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 # End /etc/fstab EOF
Step 11.2: Configure Network
# Set hostname echo "lfs-system" > /etc/hostname # Configure network interface cat > /etc/systemd/network/10-eth-dhcp.network << "EOF" [Match] Name=eth0 [Network] DHCP=ipv4 [DHCP] UseDomains=true EOF
Step 11.3: Configure Locale
cat > /etc/locale.conf << "EOF" LANG=en_US.UTF-8 EOF # Generate locales localedef -i en_US -f UTF-8 en_US.UTF-8
Step 11.4: Configure Console
cat > /etc/inputrc << "EOF" # Begin /etc/inputrc set horizontal-scroll-mode Off set meta-flag On set input-meta On set convert-meta Off set output-meta On set bell-style none "\eOd": backward-word "\eOc": forward-word "\e[1~": beginning-of-line "\e[4~": end-of-line "\e[5~": beginning-of-history "\e[6~": end-of-history "\e[3~": delete-char "\e[2~": quoted-insert # End /etc/inputrc EOF
Step 11.5: Set Root Password
passwd root
Security Note: Choose a strong password! This will be the root password for your LFS system.
Chapter 12: First Boot and Testing

The Moment of Truth!

Step 12.1: Exit Chroot and Unmount
# Exit chroot environment logout # Unmount virtual filesystems sudo umount -v $LFS/dev/pts sudo umount -v $LFS/dev sudo umount -v $LFS/run sudo umount -v $LFS/proc sudo umount -v $LFS/sys # Unmount LFS partition sudo umount -v $LFS
Step 12.2: Reboot and Test
⚠️ Point of No Return: Make sure you have a backup plan! Keep a rescue USB handy in case something goes wrong.
# Reboot the system sudo reboot
Step 12.3: First Boot Checklist

When your system boots, verify these things work:

  • ✅ System boots to login prompt
  • ✅ Root login works
  • ✅ Basic commands work (ls, ps, df, etc.)
  • ✅ Network connectivity
  • ✅ File system is writable
# Test basic functionality uname -a cat /proc/version df -h free -h lscpu ip addr show
Step 12.4: Troubleshooting Common Issues

System won't boot:

  • Check GRUB configuration
  • Verify kernel was compiled correctly
  • Check /etc/fstab entries

Kernel panic:

  • Missing filesystem driver in kernel
  • Wrong root device in GRUB config
  • Corrupted kernel image

No network:

  • Missing network driver in kernel
  • Incorrect network configuration
  • systemd-networkd not enabled
🎉 Congratulations! You Built Linux From Scratch!

What You've Accomplished

🏆 Achievement Unlocked: Linux From Scratch Master!
You've just built a complete Linux system from source code. That's seriously impressive!

What you've learned:

  • 🔧 How Linux systems are constructed from the ground up
  • ⚙️ Cross-compilation and toolchain building
  • 🐧 Kernel configuration and compilation
  • 🚀 Bootloader installation and configuration
  • 📦 Package management without package managers
  • 🔐 System security and user management
  • 🌐 Network configuration
  • 💾 File system management
Next Steps

Now that you have a basic LFS system, you can:

  • Install a desktop environment (GNOME, KDE, XFCE)
  • Add more software packages
  • Create your own package management system
  • Optimize for specific hardware
  • Build Beyond Linux From Scratch (BLFS)
  • Share your experience with the community!
🎯 Pro Tip: Document everything you did! LFS is a learning experience, and you'll want to remember the process for next time or to help others.

Resources for continued learning:

🥞 You deserve pancakes after this marathon!
Building LFS is one of the most challenging and rewarding experiences in Linux. You've joined an elite group of people who truly understand how operating systems work. Well done! :3