Skip to content

Conversation

@JeGoi
Copy link
Contributor

@JeGoi JeGoi commented Nov 10, 2025

Description

Add a new USB Bootable ISO builder for PacketFence that creates a fully functional Debian 12 live system with PacketFence pre-installed. This ISO can be:

  • Run directly from USB/DVD without installation (Live mode)
  • Run with persistence to save changes on USB between reboots
  • Installed to hard drive using a graphical or text-based installer
  • Used in recovery mode for troubleshooting

Unlike the existing net-install ISO, this USB bootable ISO includes all PacketFence dependencies offline, making it ideal for demos, testing, and quick deployments without internet access.

Additionally, adds a new system requirements checker (pfcmd checkrequirements) that validates if the system meets recommended hardware specifications (8GB RAM, 8 CPU cores, 50GB disk).

Impacts

New functionality - No impact on existing code

Reviewers should focus on:

  • CI/CD integration (.gitlab-ci.yml) - New jobs for USB ISO building with BUILD_PF_IMG_USB_ISO trigger
  • Build scripts (ci/usb-bootable-iso/) - Debian live-build configuration and Docker wrapper
  • pfcmd integration (lib/pf/cmd/pf/checkrequirements.pm) - New command implementation
  • Documentation (ci/usb-bootable-iso/README.md) - Usage and build instructions

Testing:

  • Trigger CI build with BUILD_PF_IMG_USB_ISO=yes variable
  • Build locally: cd ci/usb-bootable-iso && make local
  • Test requirements checker: /usr/local/pf/bin/pfcmd checkrequirements

Code / PR Dependencies

None - This is a standalone addition

NEW Package(s) required

Build-time only (inside Docker container):

  • live-build - Debian live system builder
  • debootstrap - Bootstrap Debian base system
  • xorriso - ISO image creation tool
  • squashfs-tools - SquashFS filesystem tools
  • syslinux-utils - Boot loader utilities
  • isolinux - ISO boot loader

No new runtime dependencies for PacketFence itself.

Issue

This addresses the need for a bootable demo/testing ISO that doesn't require internet access during installation.

Delete branch after merge

YES

Checklist

  • Document the feature - Comprehensive README in ci/usb-bootable-iso/README.md
  • [n/a] Add OpenAPI specification - Not applicable (build tooling)
  • [n/a] Add unit tests - Build scripts, not applicable
  • [n/a] Add acceptance tests (TestLink) - Infrastructure tooling

NEWS file entries

New Features

  • USB Bootable ISO Builder: New build system for creating bootable Debian 12 ISO with PacketFence pre-installed

    • Run PacketFence directly from USB/DVD without installation (Live mode)
    • USB persistence support to save changes between reboots
    • Graphical and text-based installer options
    • Recovery mode for troubleshooting
    • All dependencies included offline (no internet required)
    • Hybrid ISO compatible with USB drives and DVD media
  • System Requirements Checker: New pfcmd checkrequirements command

    • Validates system hardware: 8GB RAM, 8 CPU cores, 50GB disk
    • Available via: /usr/local/pf/bin/pfcmd checkrequirements
    • Standalone script: /usr/local/pf/bin/pf-check-requirements
    • Integrated into USB ISO welcome message

Enhancements

  • CI/CD Integration: USB bootable ISO build jobs in GitLab CI

    • New trigger variable: BUILD_PF_IMG_USB_ISO=yes
    • Independent from net-install ISO builds
    • Automatic builds on devel/maintenance branches when triggered
    • Manual builds available on release tags
    • Upload to SourceForge: PacketFence USB Bootable ISO project
  • Docker-based builds: Clean Debian 12 environment for reproducible ISO builds

Bug Fixes

None - New feature only

UPGRADE file entries

Not required - This is new functionality that doesn't affect existing installations.


Additional Notes

Build Process

# Local build
cd ci/usb-bootable-iso
make local

# CI build - add variable in GitLab
BUILD_PF_IMG_USB_ISO=yes

# Or via commit message
git commit -m "Update config

build_pf_img_usb_iso=yes"

USB Bootable ISO Builder (ci/usb-bootable-iso/):
- Create Debian 12 live system with PacketFence pre-installed
- Support multiple boot modes: Live, Live with persistence, Install, Recovery
- Include all PacketFence dependencies offline (no internet required)
- Build using Docker for clean Debian 12 environment
- Generate hybrid ISO compatible with USB and DVD
- Show admin GUI URL on first login with setup wizard prompt
- Comprehensive documentation and build instructions

System Requirements Checker:
- Add new pfcmd command: 'pfcmd checkrequirements'
- Add standalone script: bin/pf-check-requirements
- Check RAM (8GB), CPU (8 cores), and disk (50GB) requirements
- Display warnings if requirements are not met
- Integrated into USB bootable ISO welcome message

GitLab CI Integration:
- New trigger variable: BUILD_PF_IMG_USB_ISO=yes
- Independent from net-install ISO (BUILD_PF_IMG_ISO)
- Automatic builds on devel/maintenance branches when triggered
- Manual builds on release tags
- Upload to SF_USB_ISO_REPO_URL
- Same Docker-based build process as net-install ISO

Features:
- Run PacketFence directly from USB without installation
- USB persistence support to save changes between reboots
- Quick installer option to copy to hard drive
- All dependencies pre-installed for offline use
- GRUB boot menu with multiple options
- Automated PacketFence installation via hooks
- MariaDB and Redis pre-configured
- System requirements validation accessible via pfcmd
@JeGoi JeGoi force-pushed the feature/usb-bootable-iso branch from 5a30c08 to 65f5bf7 Compare November 10, 2025 20:16
JeGoi added 23 commits November 10, 2025 16:37
- Add pf-check-requirements binary to bin section
- Add lib/pf/cmd directory with wildcard for new checkrequirements.pm module
- Remove duplicate haproxy-admin-docker-wrapper entry

Fixes 'File listed twice' and 'Installed (but unpackaged) file(s) found' errors during RPM build.
Remove syslinux from bootloaders list to avoid 'Multiple BIOS instances' error.
Use grub-efi and grub-pc only for hybrid UEFI/BIOS support.
- Add policy-rc.d to prevent services from starting during apt install
- Use RUNLEVEL=1 to signal installation environment
- Skip Docker operations in chroot (images will download on first boot)
- Remove MariaDB password reset (not needed in chroot, done on first boot)

This fixes the 'Cannot connect to Docker daemon' error during ISO build.
- Create /media/cdrom/postinst-debian-installer.sh marker file
- This triggers the DEBIAN_ISO_INSTALLER path in postinst script
- Create dummy run-docker-in-debian-installer.sh script
- Properly create /usr/local/pf/containers directory first
- This prevents 'Cannot connect to Docker daemon' error

The postinst script will detect this as installer mode and skip
Docker/systemd operations that require a running system.
The run-docker-in-debian-installer.sh script is installed with the package
and tries to mount cgroups/load modules which fails in live-build chroot.

- Let apt install complete (will fail at postinst)
- Replace the Docker script with a dummy version
- Re-run dpkg --configure to complete the installation

This prevents cgroup mount and modprobe errors in chroot environment.
Create dummy Docker script before package installation and use dpkg-divert
to ensure it won't be overwritten by the package files.

- Create /usr/local/pf/containers directory and dummy script first
- Use dpkg-divert to protect the dummy script from being overwritten
- Install PacketFence package (will use our dummy script)
- Remove diversion after installation completes

This prevents cgroup mount and modprobe errors during package installation.
Instead of complex dpkg-divert approach:
- Let apt install run and fail (package files get unpacked)
- Replace the Docker script after files are unpacked
- Run dpkg --configure to complete installation with dummy script

This avoids dpkg-divert complexity and ensures the script exists
before we try to replace it.
NEW approach - different from previous attempts:
- Download package with apt-get download
- Unpack with dpkg --unpack (extracts files WITHOUT running postinst)
- Replace Docker script while package is in unpacked state
- Run apt-get install -f to configure and install dependencies

This ensures files are extracted before we replace the script,
avoiding the 'not found' error during postinst execution.
Pre-download Docker images on the build host and include them in the ISO:
- Download all PacketFence container images using docker pull
- Save images as compressed tar files in /usr/local/pf/var/docker-images
- Create load-predownloaded-images.sh script to load images on first boot
- Hook loads images during system configuration in chroot
- Images are removed after loading to save space

This significantly reduces first-boot time by avoiding image downloads.
If Docker is not available on build host, falls back to download on first boot.
Fix pre-dependency error by installing all dependencies first:
- Use apt-get install -d to download all packages
- Use apt-get install -f to install dependencies
- Then dpkg --unpack the main package
- This ensures pre-dependencies are satisfied before unpacking

Fixes 'pre-dependency problem - not installing packetfence' error.
Revert to simpler approach that works:
- Use normal 'apt-get install' which handles all dependencies
- Let it fail during postinst (files are already unpacked)
- Replace Docker script after files are on disk
- Run dpkg --configure to complete with dummy script

The complex dpkg --unpack approach was causing dependency issues.
This simpler method lets apt handle dependencies while still allowing
us to override the Docker script before final configuration.
Kill any remaining processes (mysqld, redis-server, perl) after stopping
services to ensure /sys can be unmounted cleanly at the end of the build.

Fixes 'target is busy' error during filesystem unmount.
More comprehensive process and mount cleanup:
- Stop all systemd services with --all
- Kill systemd-udevd and systemd-journald processes
- Add sync to flush filesystem buffers
- Increase sleep time to 3 seconds
- Add lazy unmount (-l) for /sys/fs/cgroup and /sys mounts

This ensures all processes release their handles on /sys before
live-build tries to unmount it.
- Create dummy Docker script BEFORE installing PacketFence
  This prevents cgroup mount errors and overlay module issues

- Install dependencies explicitly before PacketFence
  Ensures mariadb, redis, docker are available

- Remove aggressive cleanup hooks that were killing build process
  Simplified cleanup by disabling services instead of force-killing

- Fix Docker image pre-download paths
  Use absolute paths to find config.mk and build_id files

- Remove binary cleanup hook
  Not needed with proper dummy Docker script in place

This should resolve:
1. cgroup mount errors during postinst
2. overlay module not found errors
3. /sys unmount issues (services now disabled properly)
4. Docker images not being saved (path issues fixed)
The previous approach created the dummy script before PacketFence
installation, but the package overwrote it with the real script.

Now using the correct sequence:
1. Download package with apt-get install -d
2. Unpack with dpkg --unpack (extracts files, no postinst)
3. Replace Docker script while files are on disk
4. Configure with dpkg --configure (runs postinst with dummy script)

This ensures our dummy script is in place when postinst runs.
Fixed pre-dependency problem where packetfence-pfcmd-suid was
unpacked but not configured before packetfence installation.

New approach:
1. Download packetfence and all dependencies
2. Unpack ALL downloaded packages
3. Configure all dependencies EXCEPT packetfence
4. Replace Docker script
5. Configure packetfence last

This ensures pre-dependencies are fully configured before
configuring the dependent package.
The dpkg --unpack approach from 9e2bd69 was causing 'Docker script
not found' errors because it tried to unpack packages that were already
installed (mariadb, redis, docker).

Reverting to the proven approach from commit 0dfebe0:
- Use apt-get install for PacketFence (handles all dependencies)
- Let postinst fail gracefully (expected in chroot)
- Replace Docker script after files are on disk
- Reconfigure with dpkg --configure -a

This approach successfully installed PacketFence before and avoids
the complexity of manually managing package unpacking and pre-dependencies.
The dummy run-docker-in-debian-installer.sh was working, but postinst
also calls manage-images.sh which tries to connect to Docker.

Root cause: postinst runs TWO Docker-related scripts:
1. run-docker-in-debian-installer.sh (was being replaced)
2. manage-images.sh (was NOT being replaced) - this caused the error

Fix: Replace BOTH scripts with dummy versions that skip Docker
operations in the chroot environment.
The /sys unmount error keeps recurring despite stopping/disabling services.
This is because some processes still hold references to /sys.

New approach:
1. Add final killall -9 for mysqld, redis, perl before hook exits
2. Create binary hook to patch live-build's chroot_sysfs script
3. Modify live-build to use 'umount -l' (lazy unmount) for /sys
4. Lazy unmount allows system to continue even with busy filesystem

The binary hook runs on the host system and patches live-build's
unmount behavior before it tries to clean up the chroot.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants