Secure Fedora Server setup with LUKS encryption, TPM, and BTRFS RAID1 for (Hetzner) Dedicated Servers.
.gitignore | ||
build-config.yaml.example | ||
build.py | ||
deploy-config.yaml.example | ||
deploy.py | ||
icon.svg | ||
MASTER_README.md | ||
README.md | ||
requirements.txt |
Nullpoint
Secure Fedora Server setup with LUKS encryption, TPM, and BTRFS RAID1 with focus on Hetzner Infra.
Features
- Fedora Server base
- Full disk encryption with LUKS
- Remote unlock via Tang server
- TPM-based boot verification
- BTRFS RAID1 storage with optimized subvolumes
- Automated deployment to Hetzner
- Kickstart-based automated installation
Security Model
Unlock Methods
The system uses multiple methods to unlock the LUKS volumes:
- Primary Method: TPM2 + Tang server
- TPM2 verifies boot integrity
- Tang server provides remote unlock capability
- Both must succeed for automatic unlock
- Fallback Method: Manual passphrase
- Available via SSH if primary method fails
- Can be used for recovery or maintenance
TPM Integration
- TPM2 chip verifies boot integrity
- PCR measurements ensure system hasn't been tampered with
- Combined with Tang for defense in depth
- Monitors all critical boot components
Storage Security
- BTRFS RAID1 for data redundancy
- Dedicated database subvolume with
nodatacow
andnoatime
- LUKS2 encryption with multiple unlock methods
- Secure boot enabled by default
- Redundant boot partition using BTRFS RAID1
TPM Updates
After firmware updates (UEFI/BIOS), the TPM bindings need to be updated: (otherwise the system will not be able to boot without recovery phrase)
- Use the provided script:
sudo /root/update-tpm-bindings.sh
- The script will:
- Show current PCR values
- Update TPM bindings to match new measurements
- Verify all bindings are correct
- Manual passphrase is available in
/root/luks-passphrase.txt
if needed
Repository Structure
.
├── build.py # Build and upload image from build-config
├── deploy.py # Deployment script for Hetzner from deploy-config
├── MASTER_README.md # Tang server setup documentation
├── README.md # Main project documentation
└── requirements.txt # Python dependencies
Prerequisites
# Install tools
curl -fsSL https://raw.githubusercontent.com/hetznercloud/cli/master/install.sh | bash
go install github.com/hetznercloud/hcloud-upload-image@latest
sudo dnf install -y jq python3-pyyaml libguestfs-tools cloud-image-utils curl
# Configure Hetzner
export HCLOUD_TOKEN="your-token-here"
hcloud ssh-key create --name "fedora-server-hetzner" --public-key "$(cat ~/.ssh/id_ed25519.pub)"
Setup
-
Configure Build Settings
cp build-config.yaml.example build-config.yaml vim build-config.yaml # Edit LUKS, storage, and image settings
-
Build Base Image (one-time setup)
python3 build.py # Creates and uploads Fedora Server image to Hetzner
-
Configure Deployment Settings
cp deploy-config.yaml.example deploy-config.yaml vim deploy-config.yaml # Edit server type, location, and hostname settings
-
Deploy Server
python3 deploy.py # Creates new server from base image
-
Verify
ssh admin@your-server systemctl status clevis-luks-askpass lsblk clevis-luks-list -d /dev/sda2
Installation Process
The installation is fully automated using Fedora's kickstart system:
-
Partitioning:
- Boot partitions (1GB each) on both drives
- Main partitions using remaining space
- All partitions use BTRFS
-
Storage Setup:
- RAID1 for boot partitions
- LUKS2 encryption for data partitions
- BTRFS RAID1 for data with optimized subvolumes
-
Security Setup:
- TPM binding during installation
- Tang server integration
- Secure boot configuration
-
Post-Installation:
- Automatic service configuration
- TPM update script installation
- System optimization
Troubleshooting
Installation Issues
- Check installation logs at
/root/postinstall.log
- Press Alt+F3 during installation to view real-time logs
- Press Alt+F1 to return to main installation screen
Boot Issues
-
If TPM unlock fails:
- Use the manual passphrase from
/root/luks-passphrase.txt
- Run
/root/update-tpm-bindings.sh
if firmware was updated
- Use the manual passphrase from
-
If Tang server is unreachable:
- Check network connectivity
- Verify Tang server is running
- Use manual passphrase as fallback
Storage Issues
- Check RAID status:
cat /proc/mdstat
- Check BTRFS status:
btrfs filesystem show
- Verify LUKS status:
cryptsetup status