Modern diskless Linux system using SquashFS + OverlayFS + ZRAM + Dracut.
Features A/B firmware updates with automatic fallback support.
# Build complete USB image
make
# Or just build rootfs
make rootfs
# Build iPXE network boot loaders
make ipxe
# Clean and rebuild
make clean && make- SquashFS: Compressed read-only root filesystem
- OverlayFS: Writable layer on top of squashfs
- ZRAM: Compressed RAM storage for writes (2GB virtual, ~500MB actual)
- Dracut: Modern modular initramfs system
- SquashFS: 0MB (on USB stick)
- Page cache: 200-800MB (adaptive)
- ZRAM overlay: ~500MB
- Total: 0.7-1.3GB
- SquashFS: ~400MB (in RAM)
- Page cache: 200-800MB (adaptive)
- ZRAM overlay: ~500MB
- Total: 1.1-1.7GB
dbrrg/
├── Makefile # Build system
├── build/ # Build scripts
│ ├── lib/common.sh
│ ├── export-rootfs.sh
│ └── make-bootable-image.sh
├── containers/ # Container definitions
│ ├── ubuntu/Dockerfile
│ ├── image-builder/Dockerfile
│ └── ipxe/Dockerfile
├── configs/ # Configuration files
│ └── syslinux.cfg
├── overlay/ # Rootfs customizations
│ ├── usr/lib/dracut/modules.d/90dbrrg/ # Dracut module
│ └── etc/sysctl.d/99-dbrrg-memory.conf # Memory tuning
└── artifacts/ # Build outputs (gitignored)
├── rootfs/
│ ├── vmlinuz
│ ├── initrd.img
│ ├── ramroot.sqsh
│ ├── ipxe.pxe
│ ├── undionly.kpxe
│ └── ipxe.efi
└── images/
├── dbrrg-usb.img
├── dbrrg-usb.img.zst
└── dbrrg-usb.img.zst.sha256
ramroot=tl/ramroot.sqsh
ramroot=http://server/boot/ramroot.sqsh rd.neednet=1 ip=dhcp
rd.debug rd.shell rd.dbrrg.debug rd.break=pre-mount
Edit Makefile variables:
SQUASHFS_COMP=zstd- Compression algorithm (zstd, xz, lz4)SQUASHFS_COMP_LEVEL=3- Compression level (1-19, lower = faster)EFI_PARTITION_SIZE=2000- EFI partition size in MB
# Write compressed image to USB (recommended)
zstd -d < artifacts/images/dbrrg-usb.img.zst | dd of=/dev/sdX bs=1M status=progress conv=fsync
# Or write uncompressed image
dd if=artifacts/images/dbrrg-usb.img of=/dev/sdX bs=1M status=progress conv=fsyncUse the interactive upgrade-image script on a running system:
sudo upgrade-imageFeatures:
- Drive selection: Choose which USB to upgrade
- Boot USB detection: Safe additive upgrade when running from the target USB
- A/B fallback: Previous version kept as fallback (type
previousat boot menu) - Home copy: A fresh install offers to copy this machine's home onto the new drive (SSH host keys and
wg0.confstay behind, so each machine keeps its own identity)
Upgrade modes:
- Additive (boot USB): Writes new firmware to
tl.new/, keepstl/as fallback - In-place (other USB): Rotates
tl/→tl.old/, installs newtl/ - Full image: Complete rewrite with data backup/restore
After login the session opens a grid of tiles. ThinLinc is one click.
Other shipped tiles start oxulnk, a terminal, a home backup, upgrade-image
and the logout. Logging out saves the home directory first; if the save
fails, the menu asks whether to stay or to log out anyway.
Add a tile for one machine as a .desktop file in ~/.config/dbrrg/menu/:
[Desktop Entry]
Type=Application
Name=Screenshot
Exec=grim /home/tluser/screenshot.pngWithout an Icon the tile shows the first letter of Name. The program must
be in the image; a tile whose program is not installed is drawn grey.
Name,Icon,Exec: Label, icon and command of the tile.Terminal=true: Run the command in a terminal window.X-DBRRG-Save-On-Exit=true: Save the home directory when the program exits.
The files are saved with the home directory. A file with the name of a
shipped tile (for example 10-thinlinc.desktop) rewords that tile's Name,
Comment and Icon; its other keys are ignored. dbrrg-menu --check run
from a VT explains why a tile is grey.
# Build iPXE boot loaders
make ipxe
# Copy files to TFTP/HTTP server
cp artifacts/rootfs/ipxe.pxe /var/lib/tftpboot/
cp artifacts/rootfs/ipxe.efi /var/lib/tftpboot/
cp artifacts/rootfs/vmlinuz artifacts/rootfs/initrd.img /var/www/html/boot/
cp artifacts/rootfs/ramroot.sqsh /var/www/html/boot/
# Configure DHCP to serve iPXE, then chainload to kernel with:
ramroot=http://your-server/boot/ramroot.sqshSee MIGRATION.md for detailed migration guide.
# Check podman is working
podman --version
# Clean and rebuild
make clean && make# Use debug mode in syslinux.cfg
rd.debug rd.shell rd.dbrrg.debug
# Check logs after boot
cat /var/log/dracut-boot.log
cat /var/log/dbrrg/*Edit overlay/etc/sysctl.d/99-dbrrg-memory.conf:
- Increase
vm.vfs_cache_pressureto 200 (more aggressive cache eviction) - Decrease ZRAM size in dracut module
# Rebuild initramfs quickly
dracut --force --add dbrrg
# Test in QEMU
qemu-system-x86_64 -m 4G -enable-kvm \
-drive file=artifacts/images/dbrrg-usb.img,format=rawEdit files in overlay/usr/lib/dracut/modules.d/90dbrrg/:
parse-dbrrg.sh- Command line parsingfinalize-upgrade.sh- Activate pending tl.new/ upgradesmount-squashfs.sh- SquashFS mountingsetup-overlay.sh- Overlay setup
Rebuild with make rootfs
The system supports A/B firmware updates with automatic fallback:
EFI-SYSTEM partition:
├── tl/ # Current firmware (or tl.new/ after additive upgrade)
├── tl.old/ # Previous firmware (fallback)
├── config/ # Persistent configuration
└── home.tar.gz # User home backup
current- Boot the active firmware versionprevious- Boot the previous version (fallback)console- Text-only bootdebug- Debug shell
If a new firmware version fails to boot:
- Reboot and press any key at the boot prompt
- Type
previousand press Enter - System boots from the previous known-good version