Vanguard
A minimal, security-focused initramfs generator for Linux systems with full disk encryption. Written in Go, Vanguard creates lightweight boot images optimized for LUKS + LVM + TPM2 setups.
Features
- Full Disk Encryption - LUKS2 with TPM2 automatic unlock via systemd-cryptenroll
- TPM2 Integration - Automatic token detection, PIN support, PCRLock policy binding
- LVM Support - Full LVM2 volume group and logical volume activation
- GPT Autodiscovery - Automatic root partition detection using Discoverable Partitions Specification
- Hibernate/Resume - Support for resuming from encrypted swap (inside LUKS+LVM)
- Filesystem Check - Optional fsck before mounting root
- Vconsole Support - Keyboard layout and console font configuration for password prompts
- Minimal Footprint - Only includes binaries and modules needed for your configuration
- Fast Boot - zstd compression, parallel device scanning
- Self-contained - CLI embeds pre-built init binaries
Screens
Quick Start
# Build from source
git clone https://github.com/zaolin/vanguard
cd vanguard
make
# Generate initramfs
sudo ./vanguard generate -o /boot/initramfs-linux.img
# With debug output enabled
sudo ./vanguard generate -o /boot/initramfs-linux.img --debug
Documentation
Commands
generate
Generate an initramfs image:
vanguard generate -o /boot/initramfs-linux.img [options]
| Option |
Description |
-o, --output |
Output path (required) |
-f, --firmware |
Comma-separated firmware files |
-m, --modules |
Comma-separated kernel modules |
-c, --compression |
zstd, gzip, or none (default: zstd) |
-d, --debug |
Enable verbose boot output |
-s, --strict |
Strict mode: token-only unlock, no passphrase fallback |
--config |
Path to TOML config file |
update-tpm-policy
Update TPM2 PCRLock policy for secure boot:
vanguard update-tpm-policy -u /boot/EFI/Linux/kernel.efi [options]
| Option |
Description |
-u, --uki-path |
Path to UKI file (required) |
-p, --policy-output |
Output path for policy JSON |
-l, --luks-device |
LUKS device for token verification (enables GPT binding) |
--no-gpt |
Disable GPT partition table binding (PCR 5) |
--no-verify |
Skip policy verification |
-v, --verbose |
Show verbose output from pcrlock tools |
-c, --cleanup |
Remove old unused pcrlock NV indices from TPM |
verify-pcrlock-setup
Verify TPM2 pcrlock setup (PCRs, NV Index, LUKS token):
vanguard verify-pcrlock-setup -p /boot/pcrlock.json [options]
| Option |
Description |
-p, --policy-path |
Path to pcrlock.json policy file (required) |
-l, --luks-device |
LUKS device to verify (optional) |
This checks:
- NV Index synchronization (TPM matches policy file)
- Current PCR values against policy expectations
- LUKS token validation (when
-l specified)
Configuration File
Create /etc/vanguard.toml:
output = "/boot/initramfs-linux.img"
compression = "zstd"
debug = false
firmware = [
"amd/amd_sev.fw",
"amdgpu/vangogh_sos.bin",
]
modules = [
"nvme",
"xhci_pci",
]
Typical Setup
1. Partition Layout
/dev/sda
├── /dev/sda1 ESP (FAT32, ~512MB) - EFI System Partition
└── /dev/sda2 LUKS encrypted - Contains LVM
└── LVM PV
└── VG: vg0
├── LV: root (ext4/xfs)
└── LV: swap
2. Enroll TPM2
# Basic enrollment
systemd-cryptenroll --tpm2-device=auto /dev/sda2
# With PIN
systemd-cryptenroll --tpm2-device=auto --tpm2-with-pin=yes /dev/sda2
# With PCRLock policy
vanguard update-tpm-policy -u /boot/EFI/Linux/kernel.efi
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrlock=/boot/pcrlock.json /dev/sda2
3. Generate Initramfs
vanguard generate -o /boot/initramfs-linux.img
4. Kernel Command Line
root=/dev/vg0/root resume=/dev/vg0/swap
See docs/kernel-parameters.md for all supported parameters.
Boot Sequence Overview
┌──────────────────────────────────────────────────────────────────┐
│ 1. Console Setup Set up early console I/O │
│ 2. Mount Filesystems /proc, /sys, /dev, /run │
│ 3. Vconsole Config Load keyboard layout/font │
│ 4. Mount /boot Mount boot partition for policy │
│ 5. Init Boot Log Start logging to /boot │
│ 6. Start udevd Device discovery daemon │
│ 7. Load Modules Kernel modules from image │
│ 8. Trigger udev Events Firmware loading │
│ 9. Load TPM Modules tpm_crb, tpm_tis, tpm_tis_core │
│ 10. Setup PCRLock Copy pcrlock.json for TPM2 │
│ 11. Unlock LUKS TPM2 → PIN → Passphrase │
│ 11a. Trigger udev Process dm-crypt devices │
│ 12. Activate LVM Scan and activate volumes │
│ 12a. Trigger udev Process LVM devices │
│ 13. Try Resume Hibernate resume from swap │
│ 14. Find Root Device cmdline → fstab → GPT autodiscovery │
│ 15. fsck Check root filesystem │
│ 16. Mount Root Mount to /sysroot │
│ 16a. LVM Symlinks Create symlinks in /sysroot/dev │
│ 17. Cleanup udev Settle, cleanup DB, stop daemon │
│ 18. Close Boot Log Close log, unmount /boot │
│ 19. Switch Root Hand off to real init │
└──────────────────────────────────────────────────────────────────┘
See docs/boot-flow.md for detailed documentation.
Requirements
Build Requirements:
Runtime Dependencies (included in initramfs):
- lvm2
- systemd-udevd
- tpm2-tools (optional, for PCR debugging)
Testing
# Run QEMU test with software TPM
./scripts/qemu-test.sh all-tpm
# Individual steps
./scripts/qemu-test.sh build # Build initramfs
./scripts/qemu-test.sh disk # Create test disk
./scripts/qemu-test.sh enroll-tpm # Enroll TPM2 token
./scripts/qemu-test.sh tpm # Boot with TPM
Security Features
- TPM2 sealed keys with PCR policy binding (PCR 4 for UKI, PCR 7 for Secure Boot)
- PCRLock for predictable boot measurement validation
- PIN protection for TPM2 tokens
- Strict mode (
-s): disables passphrase fallback when TPM2 token is present, halting if TPM2 unlock fails
- Passphrase fallback when TPM2 fails (3 attempts before halt, unless strict mode)
- Kernel message suppression during password entry
- Static Go binary init (no dynamic linking vulnerabilities in init)
- Minimal attack surface (only essential binaries included)
- Boot logging to
/boot/.vanguard.log for audit trail
License
MIT License - see LICENSE for details.
Contributing
Contributions welcome! Please open an issue or pull request on GitHub.