A Docker Compose-based pipeline for building Linux From Scratch 12.4 (SysVinit)
EasyLFS is a modern, containerized implementation of the Linux From Scratch build process. It transforms the traditional manual LFS build into a modular, repeatable Docker Compose pipeline designed for both educational purposes and reproducible builds.
Key Features:
- Modular Pipeline: 6 sequential Docker services mapping to LFS chapters
- Reproducible: Same inputs produce identical outputs
- Educational: Learn LFS concepts without host system pollution
- Portable: Works on any Docker-enabled system
- Stateful: Named volumes preserve build artifacts between stages
┌─────────────────┐
│ download-sources│──> lfs-sources (volume)
└────────┬────────┘
│
v
┌─────────────────┐
│ build-toolchain │──> lfs-tools + lfs-rootfs
└────────┬────────┘
│
v
┌─────────────────┐
│build-basesystem │──> lfs-rootfs (chroot)
└────────┬────────┘
│
v
┌─────────────────┐
│configure-system │──> lfs-rootfs
└────────┬────────┘
│
v
┌─────────────────┐
│ build-kernel │──> lfs-rootfs (/boot)
└────────┬────────┘
│
v
┌─────────────────┐
│ package-image │──> lfs-dist (bootable .img)
└─────────────────┘
- Docker: 24.0 or higher
- Docker Compose: 2.20 or higher
- Disk Space: 20GB minimum (30GB recommended)
- RAM: 4GB minimum (8GB recommended for faster builds)
- CPU: Multi-core recommended (affects build time)
The easiest way to build your LFS system is using the unified easylfs command:
# Clone and enter the project
git clone https://github.com/gnovelli/easylfs.git
cd easylfs
# Build the complete LFS system (automatic setup included)
./easylfs build
# That's it! The script will:
# ✓ Auto-initialize Docker volumes
# ✓ Build all service images
# ✓ Run the complete 6-stage pipeline
# ✓ Create a bootable LFS system./easylfs status # Check build progress and volume status
./easylfs logs # View build logs
./easylfs export # Export final disk image to current directory
./easylfs shell # Open shell in LFS rootfs
./easylfs clean # Remove containers (keep volumes)
./easylfs reset # Complete reset (removes everything)
./easylfs help # Show all available commandsmake setup # Initialize environment
make build # Build complete LFS system
make status # Check progress
make export # Export disk imageAfter building your LFS system, you can access it directly from your browser using two web interfaces:
# Start both interfaces
make web
# Or start individually
make web-terminal # Text-based terminal (http://localhost:7681)
make web-screen # Graphical console (http://localhost:6080/vnc.html)
# Stop interfaces
make web-stop- Lightweight and fast text-based shell access
- URL: http://localhost:7681
- Perfect for command-line operations and testing
- Low resource usage
- Full graphical console with VNC streaming
- URL: http://localhost:6080/vnc.html
- See complete boot process and visual output
- Supports graphics applications
# Use custom ports
WEB_TERMINAL_PORT=8080 make web-terminal
WEB_SCREEN_PORT=8888 make web-screen
# Or set both
WEB_TERMINAL_PORT=7777 WEB_SCREEN_PORT=8888 make webSee WEB_INTERFACE.md for complete documentation, troubleshooting, and advanced usage.
For advanced users who want full control over each build stage:
git clone https://github.com/gnovelli/easylfs.git
cd easylfsOption A - Automatic (recommended):
./setup.shOption B - Manual:
docker volume create easylfs_lfs-sources
docker volume create easylfs_lfs-tools
docker volume create easylfs_lfs-rootfs
docker volume create easylfs_lfs-dist
docker volume create easylfs_lfs-logs
# Fix log volume permissions
docker run --rm -v easylfs_lfs-logs:/logs alpine chmod 777 /logs
# Build service images
docker compose buildExecute services sequentially (not in parallel):
# Step 1: Download sources (~5-15 min)
docker compose run --rm download-sources
# Step 2: Build toolchain (~2-4 hours)
docker compose run --rm build-toolchain
# Step 3: Build base system (~3-6 hours)
docker compose run --rm build-basesystem
# Step 4: Configure system (~10-20 min)
docker compose run --rm configure-system
# Step 5: Build kernel (~20-60 min)
docker compose run --rm build-kernel
# Step 6: Package image (~15-30 min)
docker compose run --rm package-image# Extract rootfs tarball from Docker volume
docker run --rm -v easylfs_lfs-dist:/dist -v $(pwd):/out alpine \
cp /dist/lfs-12.4-sysv-rootfs.tar.gz /out/
# Verify tarball
tar -tzf lfs-12.4-sysv-rootfs.tar.gz | head -20Option A: Extract to chroot environment
# Create target directory
sudo mkdir -p /mnt/lfs
# Extract rootfs
sudo tar -xzf lfs-12.4-sysv-rootfs.tar.gz -C /mnt/lfs
# Chroot into the system
sudo chroot /mnt/lfs /bin/bashOption B: Create bootable disk image (requires bare metal or VM)
# Create disk image
dd if=/dev/zero of=lfs-disk.img bs=1M count=2048
# Partition and format
sudo losetup -fP lfs-disk.img
sudo mkfs.ext4 /dev/loop0
# Extract and install GRUB
sudo mount /dev/loop0 /mnt
sudo tar -xzf lfs-12.4-sysv-rootfs.tar.gz -C /mnt
sudo grub-install --boot-directory=/mnt/boot /dev/loop0
sudo grub-mkconfig -o /mnt/boot/grub/grub.cfg# Console mode (recommended for SSH/remote)
qemu-system-x86_64 \
-m 2G \
-smp 2 \
-drive file=lfs-12.4-sysv.img,format=raw \
-boot c \
-nographic \
-serial mon:stdio
# Or with GUI (if running locally)
qemu-system-x86_64 \
-m 2G \
-smp 2 \
-drive file=lfs-12.4-sysv.img,format=raw \
-boot cDownloads all LFS source packages and patches from linuxfromscratch.org mirrors.
docker compose run --rm download-sourcesOutput: Populates lfs-sources volume (~500MB, ~100 packages)
Builds the temporary cross-compilation toolchain (LFS Chapters 5-6).
docker compose run --rm build-toolchainDuration: 2-4 hours
Output: lfs-tools and initial lfs-rootfs volumes
Enters chroot and builds the final LFS system (Chapters 7-8).
docker compose run --rm build-basesystemDuration: 3-6 hours
Requires: SYS_CHROOT capability (configured in docker compose.yml)
Creates system configuration files (Chapter 9).
docker compose run --rm configure-systemCreates: /etc/fstab, /etc/hosts, /etc/inittab, SysV bootscripts, etc.
Compiles the Linux kernel with essential features for LFS.
docker compose run --rm build-kernelDuration: 20-60 minutes
Output: /boot/vmlinuz-* and kernel modules
Creates bootable disk image with GRUB2 bootloader and tarball.
docker compose run --rm package-imageDuration: 15-30 minutes Output:
lfs-12.4-sysv.img.gz(bootable disk image with GRUB2)lfs-12.4-sysv.tar.gz(rootfs tarball)
Note: The image is immediately bootable. GRUB is automatically installed to the MBR and configured to detect available kernels.
# List volumes
docker volume ls | grep easylfs
# Inspect sources
docker run --rm -v easylfs_lfs-sources:/sources alpine ls -lh /sources
# Inspect rootfs
docker run --rm -v easylfs_lfs-rootfs:/lfs alpine ls -lh /lfsAll services write detailed logs to the lfs-logs volume. Logs persist across container restarts and include timestamps, command output, and exit status.
# View a specific service log
docker run --rm -v easylfs_lfs-logs:/logs alpine cat /logs/build-toolchain.log
# View the master log (all services combined)
docker run --rm -v easylfs_lfs-logs:/logs alpine cat /logs/easylfs-master.log
# Copy all logs to current directory
docker run --rm -v easylfs_lfs-logs:/logs -v $(pwd):/out alpine \
cp -r /logs /out/
# Tail logs in real-time (while service is running)
docker run --rm -v easylfs_lfs-logs:/logs alpine tail -f /logs/build-basesystem.logAvailable log files:
download-sources.log- Source download phasebuild-toolchain.log- Toolchain compilation (2-4 hours of output)build-basesystem.log- Base system buildconfigure-system.log- System configurationbuild-kernel.log- Kernel compilationpackage-image.log- Image creationeasylfs-master.log- Combined log from all services
# Backup lfs-rootfs volume
docker run --rm -v easylfs_lfs-rootfs:/lfs -v $(pwd):/backup alpine \
tar -czf /backup/lfs-rootfs-backup.tar.gz -C /lfs .# Remove all containers and volumes (complete reset)
docker compose down -v
# Remove only containers (keep volumes for resume)
docker compose downApproximate durations on modern hardware (Intel i5/Ryzen 5, 8GB RAM):
| Service | Duration |
|---|---|
| download-sources | 5-15 min |
| build-toolchain | 2-4 hours |
| build-basesystem | 3-6 hours |
| configure-system | 10-20 min |
| build-kernel | 20-60 min |
| package-image | 15-30 min |
| Total | 6-11 hours |
Tip: Run toolchain and basesystem builds overnight.
EasyLFS includes a containerized test suite for validation and QA.
Verify volumes contain expected files without running builds:
docker compose run --rm test quickdocker compose run --rm test download-sources
docker compose run --rm test build-kernelRun complete build with validation (6-11 hours):
docker compose run --rm test fulldocker compose run --rm test validateTests provide colored output with pass/fail status:
[TEST] Checking Docker volumes...
[PASS] Volume easylfs_lfs-sources exists
[PASS] Found 98 source files (expected ~100)
[PASS] Checksum file (md5sums) present
Exit codes:
0= All tests passed1= One or more tests failed
Use in automated pipelines:
# .github/workflows/test.yml
- name: Test EasyLFS Pipeline
run: docker compose run --rm test quickCause: Missing SYS_CHROOT capability
Solution: Verify docker compose.yml has:
cap_add:
- SYS_CHROOTCause: Insufficient Docker storage
Solution:
# Check Docker disk usage
docker system df
# Clean up unused images/containers
docker system prune -aCause: build-toolchain service didn't complete successfully
Solution: Re-run docker compose run --rm build-toolchain and check logs
Solutions:
- Increase
MAKEFLAGSparallelism:export MAKEFLAGS=-j$(nproc) - Allocate more resources to Docker Desktop
- Use faster storage (SSD recommended)
Solution: Check the service log to identify the failure point
# View the failed service log
docker run --rm -v easylfs_lfs-logs:/logs alpine cat /logs/<service-name>.log
# Search for errors
docker run --rm -v easylfs_lfs-logs:/logs alpine grep -i error /logs/<service-name>.logUse volume backups to resume from last successful stage:
# After each major stage completes
docker compose run --rm <service>
docker run --rm -v easylfs_lfs-rootfs:/lfs -v $(pwd):/backup alpine \
tar -czf /backup/checkpoint-<service>.tar.gz -C /lfs .Edit docker compose.yml:
environment:
- KERNEL_VERSION=6.8.1# Use 8 cores for compilation
export MAKEFLAGS=-j8
docker compose run --rm build-toolchainconfigure-system:
environment:
- HOSTNAME=my-lfs-box
- TIMEZONE=America/New_York# Debug a service with bash shell
docker compose run --rm --entrypoint /bin/bash build-toolchain
# View service logs
docker compose logs download-sources# Write image to USB drive (CAREFUL: This will erase the drive!)
sudo dd if=lfs-12.4-sysv.img of=/dev/sdX bs=4M status=progress sync
# Replace /dev/sdX with your actual USB device (check with lsblk)easylfs/
├── docker compose.yml # Main orchestration file
├── services/ # Service implementations
│ ├── common/ # Shared utilities
│ │ ├── logging.sh # Centralized logging system
│ │ └── README.md # Logging documentation
│ ├── download-sources/
│ │ ├── Dockerfile
│ │ └── scripts/download.sh
│ ├── build-toolchain/
│ │ ├── Dockerfile
│ │ └── scripts/build_toolchain.sh
│ ├── build-basesystem/
│ ├── configure-system/
│ ├── build-kernel/
│ └── package-image/
├── tests/ # Automated test suite
│ ├── Dockerfile
│ ├── README.md
│ └── scripts/
│ ├── test_runner.sh
│ ├── quick_test.sh
│ ├── test_pipeline.sh
│ ├── test_service.sh
│ └── validate_volumes.sh
├── volumes/ # Bind mount points
│ └── sources/
└── dist/ # Output images
This project was designed as a teaching tool for Linux User Groups (LUGs) to demonstrate:
- Advanced Docker Patterns: Multi-stage builds, named volumes, sequential orchestration
- LFS Concepts: Cross-compilation, chroot, system bootstrap process
- DevOps Practices: Reproducible builds, infrastructure as code
- Linux Internals: Kernel configuration, SysVinit boot process, runlevels
✅ PRODUCTION READY - Complete pipeline fully functional and verified!
Service Status:
- ✅ download-sources: Complete and tested
- ✅ build-toolchain: Complete and verified
- ✅ build-basesystem: COMPLETE - All 59 packages build successfully
- ✅ configure-system: COMPLETE - System configuration applied
- ✅ build-kernel: COMPLETE - Linux 6.12.6 compiled and installed
- ✅ package-image: COMPLETE - Bootable images and tarball created
Current Version: v1.1.2
Final Deliverables:
lfs-12.4-sysv.img(5GB) - Bootable disk image with GRUBlfs-12.4-sysv.img.gz(~1GB) - Compressed bootable imagelfs-12.4-sysv-rootfs.tar.gz(~1GB) - Complete LFS root filesystem- Linux kernel 6.12.6 with SysVinit support
- 59 essential packages from LFS Chapter 8
- Full system configuration (fstab, hostname, network, shell profiles)
v1.1.2 (2025-11-06) - Current Release
- Comprehensive documentation updates
- All services verified and production-ready
- Complete test coverage
v1.1.1 (2025-11-06)
- Fixed kbd package build issue (autom4te dependency)
- Improved timestamp handling to prevent testsuite regeneration
- Enhanced build reliability
v1.1.0 (2025-11-05)
- Enhanced security with SHA-512 password encryption
- Increased web-screen resolution to Full HD (1920x1080)
- Improved testing experience
v1.0.0 (2025-11-05) - First Production Release
- Complete LFS 12.4 (SysVinit) build pipeline
- 59 essential packages in base system
- Reproducible builds with checkpoint system
- Bootable disk images with GRUB
- ✅ Complete Build Pipeline: All 6 services functional and tested
- ✅ Reproducible Builds: Hash-based checkpoint system working perfectly
- ✅ Bootable System: Creates working LFS 12.4 (SysVinit) systems
- ✅ Resume Capability: Can resume from any failure point
- ✅ Web Access: Terminal and graphical console interfaces
- ✅ Production Ready: Fully tested and documented
All critical issues have been completely resolved:
Chroot logging✅ Fixed with explicit output redirectionCheckpointing in chroot✅ Fixed module copy pathSilent exits✅ Added success markers and exit codesKbd package build✅ Fixed autom4te dependency issue
Minor Limitations:
- Initial build takes 6-10 hours (hardware dependent)
- 5 files without upstream MD5 checksums re-download (~5s impact)
- Text console only (X11 not included in minimal system)
EasyLFS includes a publishing system to share production-ready files on GitHub while keeping development files private.
# First time setup
make publish-setup
# Enter your GitHub repository URL when prompted
# Publish production files
make publishOnly essential production files are published:
- Core pipeline (docker-compose.yml, setup.sh, easylfs, build.sh)
- Essential documentation (README.md, QUICKSTART.md)
- All services and tests
- No development notes, status reports, or debug files
# Interactive publishing (recommended)
make publish
# See what would be published (dry run)
make publish-dry-run
# Setup GitHub remote
make publish-setupThe script will:
- Copy only production files to a separate worktree
- Show you the changes (diff)
- Ask for confirmation and commit message
- Push to GitHub with clean history
See PUBLISHING.md for complete documentation.
Contributions welcome! The core pipeline is production-ready. Current priorities:
✅ Completed:
Debug and fix chroot logging issues✅Implement checkpointing module copy to chroot✅Add explicit success/failure status reporting✅Complete all 6 pipeline services✅Comprehensive testing and validation✅Production-ready documentation✅
High Priority (Enhancements):
- Implement local checksum storage for files without upstream MD5
- Add comprehensive error handling and retry logic
- Expand automated test suite with boot testing
- CI/CD pipeline integration
Medium Priority (Extensions): 5. Add BLFS (Beyond Linux From Scratch) package extensions 6. Package manager integration (optional) 7. Build caching with ccache for faster rebuilds 8. Improved logging and progress reporting
Low Priority (Future Features): 9. Multi-architecture support (ARM64, RISC-V) 10. Parallel package builds where possible 11. ISO image generation 12. Network installation support 13. Alternative init system variants
- Linux From Scratch Book - Primary source for build instructions
- LFS Credits - Contributors to the LFS project
- SysVinit Documentation
- Docker Multi-Stage Builds
License to be determined - See CREDITS.md for attribution and third-party licenses
This project is built upon the Linux From Scratch (LFS) project, utilizing the build instructions and commands from LFS 12.4, which are provided under the MIT License.
EasyLFS automates and containerizes these instructions while preserving the educational value of the LFS approach. We strongly recommend reading the original LFS book to understand the concepts behind each step.
Credits:
- Linux From Scratch Project Team - https://www.linuxfromscratch.org/
See CREDITS.md for detailed attribution, licensing information, and third-party components.
Built with: Docker, Bash, and the wisdom of the LFS community ☕