{"id":29057564,"url":"https://github.com/pccr10001/pve-trusted-boot","last_synced_at":"2025-10-07T07:51:26.925Z","repository":{"id":298818902,"uuid":"1001233197","full_name":"pccr10001/pve-trusted-boot","owner":"pccr10001","description":"Enable trusted boot with LUKS and TPM to protect root partition and VM storage.","archived":false,"fork":false,"pushed_at":"2025-06-14T06:11:15.000Z","size":31,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-27T06:06:02.159Z","etag":null,"topics":["clevis","luks","pve","secureboot","tpm","trusted-boot"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pccr10001.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-13T03:35:28.000Z","updated_at":"2025-06-22T04:20:45.000Z","dependencies_parsed_at":"2025-06-13T04:33:26.252Z","dependency_job_id":"2725bf4c-927b-4f20-b218-27406ee27563","html_url":"https://github.com/pccr10001/pve-trusted-boot","commit_stats":null,"previous_names":["pccr10001/pve-trusted-boot"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pccr10001/pve-trusted-boot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pccr10001%2Fpve-trusted-boot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pccr10001%2Fpve-trusted-boot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pccr10001%2Fpve-trusted-boot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pccr10001%2Fpve-trusted-boot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pccr10001","download_url":"https://codeload.github.com/pccr10001/pve-trusted-boot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pccr10001%2Fpve-trusted-boot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278740821,"owners_count":26037480,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clevis","luks","pve","secureboot","tpm","trusted-boot"],"created_at":"2025-06-27T06:06:00.826Z","updated_at":"2025-10-07T07:51:26.889Z","avatar_url":"https://github.com/pccr10001.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"PVE Trusted Boot with TPM and LUKS\n===\n\n## Goal\n* Install Proxmov VE\n* Enforce Secure boot\n* Keep kernel and initramfs update automatically\n* Seal with TPM to protect kernel, initramfs and kernel cmdline.\n\n## My Environment\n* Intel N100\n* 8G DDR4\n* 128G NVMe SSD\n* BIOS Supports TPM 2.0 and Secure Boot\n\n## Boot with Debian Live CD\n* Get Debian Bookworm Live DVD from \n    * [https://mirror.twds.com.tw/debian-cd/12.11.0-live/amd64/iso-hybrid/debian-live-12.11.0-amd64-standard.iso](https://mirror.twds.com.tw/debian-cd/12.11.0-live/amd64/iso-hybrid/debian-live-12.11.0-amd64-standard.iso)\n* Create bootable USB drive using rufus or others tools.\n* Boot Debian USB drive with `EFI` mode.\n\n## Partition\n* My SSD is 128G NVMe, locate at `/dev/nvme0n1`\n* Partition Table\n    * 500M `EFI` `/boot/efi`\n    * 500M `Boot` `/boot`\n    * 4G Swap\n    * 114G LVM for `root` and VMs\n* Using `fdisk` to part the disk.\n\n```bash=\nroot@debian:~# fdisk /dev/nvme0n1\n\nWelcome to fdisk (util-linux 2.38.1).\nChanges will remain in memory only, until you decide to write them.\nBe careful before using the write command.\n\n\nCommand (m for help): n\nPartition number (1-128, default 1):\nFirst sector (2048-250069646, default 2048):\nLast sector, +/-sectors or +/-size{K,M,G,T,P} (2048-250069646, default 250068991): +500M\n\nCreated a new partition 1 of type 'Linux filesystem' and of size 500 MiB.\n\nCommand (m for help): n\nPartition number (2-128, default 2):\nFirst sector (1026048-250069646, default 1026048):\nLast sector, +/-sectors or +/-size{K,M,G,T,P} (1026048-250069646, default 250068991): +500M\n\nCreated a new partition 2 of type 'Linux filesystem' and of size 500 MiB.\n\nCommand (m for help): n\nPartition number (3-128, default 3):\nFirst sector (2050048-250069646, default 2050048):\nLast sector, +/-sectors or +/-size{K,M,G,T,P} (2050048-250069646, default 250068991): +4G\n\nCreated a new partition 3 of type 'Linux filesystem' and of size 4 GiB.\n\nCommand (m for help): n\nPartition number (4-128, default 4):\nFirst sector (10438656-250069646, default 10438656):\nLast sector, +/-sectors or +/-size{K,M,G,T,P} (10438656-250069646, default 250068991):\n\nCreated a new partition 4 of type 'Linux filesystem' and of size 114.3 GiB.\n```\n\n* Then set labels and type for each partitions\n\n```bash=\nCommand (m for help): t\nPartition number (1-4, default 4): 1\nPartition type or alias (type L to list all): 1\n\nChanged type of partition 'Linux filesystem' to 'EFI System'.\n\nCommand (m for help): t\nPartition number (1-4, default 4): 2\nPartition type or alias (type L to list all): 4\n\nChanged type of partition 'Linux filesystem' to 'BIOS boot'.\n\nCommand (m for help): t\nPartition number (1-4, default 4): 3\nPartition type or alias (type L to list all): swap\n\nChanged type of partition 'Linux filesystem' to 'Linux swap'.\n\nCommand (m for help): t\nPartition number (1-4, default 4): 4\nPartition type or alias (type L to list all): lvm\n\nChanged type of partition 'Linux filesystem' to 'Linux LVM'.\n\nCommand (m for help):\n```\n\n* Save changes to disk.\n\n```bash=\nCommand (m for help): w\nThe partition table has been altered.\nCalling ioctl() to re-read partition table.\nSyncing disks.\n\nroot@debian:~#\n```\n\n### Format partitions\n* Install FAT32 tools\n    * `apt install dosfstools`\n```bash=\nroot@debian:~# apt install dosfstools\nReading package lists... Done\nBuilding dependency tree... Done\nReading state information... Done\nThe following NEW packages will be installed:\n  dosfstools\n0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.\nNeed to get 142 kB of archives.\nAfter this operation, 323 kB of additional disk space will be used.\nGet:1 http://deb.debian.org/debian bookworm/main amd64 dosfstools amd64 4.2-1 [142 kB]\nFetched 142 kB in 0s (723 kB/s)\nSelecting previously unselected package dosfstools.\n(Reading database ... 83280 files and directories currently installed.)\nPreparing to unpack .../dosfstools_4.2-1_amd64.deb ...\nUnpacking dosfstools (4.2-1) ...\nSetting up dosfstools (4.2-1) ...\nProcessing triggers for man-db (2.11.2-2) ...\n```\n\n* Format partitions\n```bash=\nroot@debian:~# mkfs.fat -F32 /dev/nvme0n1p1\nmkfs.fat 4.2 (2021-01-31)\n\nroot@debian:~# mkfs.ext4 /dev/nvme0n1p2\nmke2fs 1.47.0 (5-Feb-2023)\nDiscarding device blocks: done\nCreating filesystem with 512000 1k blocks and 128016 inodes\nFilesystem UUID: f9abf8f0-5925-4a6d-8e5e-7d0e1aee40a8\nSuperblock backups stored on blocks:\n        8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409\n\nAllocating group tables: done\nWriting inode tables: done\nCreating journal (8192 blocks): done\nWriting superblocks and filesystem accounting information: done\n\nroot@debian:~# mkswap /dev/nvme0n1p3\nSetting up swapspace version 1, size = 4 GiB (4294963200 bytes)\nno label, UUID=69b75414-231a-471c-a6fe-8b948d51ffcd\n\nroot@debian:~#\n```\n\n## Setup LUKS\n* Install related tools\n    * `apt install clevis clevis-tpm2 clevis-luks cryptsetup tpm2-tools`\n\n* Create LUKS on `/dev/nvme0n1p4`\n    * Please define a password to unlock the partition.\n    * `cryptsetup luksFormat /dev/nvme0n1p4`\n```bash=\nroot@debian:~# cryptsetup luksFormat /dev/nvme0n1p4\n\nWARNING!\n========\nThis will overwrite data on /dev/nvme0n1p4 irrevocably.\n\nAre you sure? (Type 'yes' in capital letters): YES\nEnter passphrase for /dev/nvme0n1p4:\nVerify passphrase:\nroot@debian:~#\n```\n\n* Open encrypted partition and mount it on `cryptroot`\n    * `cryptsetup open /dev/nvme0n1p4 cryptroot`\n```bash=\nroot@debian:~# cryptsetup open /dev/nvme0n1p4 cryptroot\nEnter passphrase for /dev/nvme0n1p4:\nroot@debian:~#\n```\n\n## Setup LVM\n* Install LVM tools\n    * `apt -y install lvm2`\n* Create PV\n    * `pvcreate /dev/mapper/cryptroot`\n```bash=\nroot@debian:~# pvcreate /dev/mapper/cryptroot\n  Physical volume \"/dev/mapper/cryptroot\" successfully created.\n```\n* Create VG\n    * `vgcreate pve /dev/mapper/cryptroot`\n```bash=\nroot@debian:~# vgcreate pve /dev/mapper/cryptroot\n  Volume group \"pve\" successfully created\n```\n* Create LV\n    * I chosed 40G as `root` for PVE\n```bash=\nroot@debian:~# lvcreate -L 40G -n root pve\n  Logical volume \"root\" created.\nroot@debian:~# lvcreate -l 100%FREE --thinpool data pve\n  Thin pool volume with chunk size 64.00 KiB can address at most \u003c15.88 TiB of data.\n  Logical volume \"data\" created.\n```\n* Format PVE `root`\n```bash=\nroot@debian:~# mkfs.ext4 /dev/pve/root\nmke2fs 1.47.0 (5-Feb-2023)\nCreating filesystem with 10485760 4k blocks and 2621440 inodes\nFilesystem UUID: 6d9ec1fc-8743-4748-ba20-766541debbbb\nSuperblock backups stored on blocks:\n        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,\n        4096000, 7962624\n\nAllocating group tables: done\nWriting inode tables: done\nCreating journal (65536 blocks): done\nWriting superblocks and filesystem accounting information: done\nroot@debian:~#\n```\n\n## Install Debian\n* Mount root for PVE\n    * `mount /dev/pve/root /mnt`\n* Install `debootstrap`\n    * `apt install -y debootstrap`\n* Install Debian with debootstrap\n    * You can also change mirror for APT.\n    * `debootstrap --arch amd64 stable /mnt http://free.nchc.org.tw/debian`\n* Mount system directory for `chroot`\n```bash=\nmount --make-rslave --rbind /proc /mnt/proc\nmount --make-rslave --rbind /sys /mnt/sys\nmount --make-rslave --rbind /dev /mnt/dev\nmount --make-rslave --rbind /run /mnt/run\n```\n* Chroot to Debian\n    * `chroot /mnt`\n* Mount `/boot`\n    * `mount /dev/nvme0n1p2 /boot`\n    * `mkdir /boot/efi`\n    * `mount /dev/nvme0n1p1 /boot/efi`\n* Update APT sources\n```bash=\nroot@debian:~# cat \u003e /etc/apt/sources.list \u003c\u003c EOF\ndeb http://free.nchc.org.tw/debian/ bookworm main contrib non-free non-free-firmware\ndeb-src http://free.nchc.org.tw/debian/ bookworm main contrib non-free non-free-firmware\n\ndeb http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware\ndeb-src http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware\n\ndeb http://free.nchc.org.tw/debian/ bookworm-updates main contrib non-free non-free-firmware\ndeb-src http://free.nchc.org.tw/debian/ bookworm-updates main contrib non-free non-free-firmware\nEOF\n\nroot@debian:~# apt update\n```\n* Update `/etc/fstab`\n```\n/dev/nvme0n1p2          /boot          ext4    defaults    0      2\n/dev/nvme0n1p1          /boot/efi      vfat    defaults    0      1\n/dev/mapper/pve-root    /              ext4    defaults    0      1\n```\n* Add `/etc/crypttab`\n    * `echo \"cryptroot UUID=$(blkid -o value -s UUID /dev/nvme0n1p4) none luks,discard\" \u003e /etc/crypttab`\n* Configute timezone\n    * `dpkg-reconfigure tzdata`\n* Configure Locales\n    * `apt install -y locales`\n    * `dpkg-reconfigure locales\n* Set password for `root`\n    * `passwd root`\n* Install Kernel\n    * Remove Realtek firmware if you don't need it.\n    * `apt install -y linux-image-amd64 firmware-linux firmware-realtek`\n* Setup Hostname\n    * `echo \"pvebox2\" \u003e /etc/hostname`\n* Setup `/etc/hosts`\n    * PVE needs to resolve IP with full FQDN hostname, replace following entries and save to `/etc/hosts`\n```\n127.0.0.1 localhost\n{LAN_IP_ADDRESS} {HOSTNAME} {HOSTNAME}.{FQDN}\n\n::1     localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n```\n\n```\n# Example\n\n127.0.0.1 localhost\n192.168.2.1 pvebox2 pvebox2.example.tld\n\n::1     localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n```\n* Install Grub2\n    * `apt install -y grub-efi-amd64-signed grub2`\n    * `grub-install --target=x86_64-efi --uefi-secure-boot --efi-directory=/boot/efi /dev/nvme0n1`\n    * `update-grub`\n* Configure network\n    * Set DNS server in `/etc/ressolv.conf`\n    * Configure network setting in `/etc/network/interfaces`\n```\nallow-hotplug enp1s0\niface enp1s0 inet static\n    address 192.168.2.2\n    netmask 255.255.255.0\n    gateway 192.168.2.1\n```\n## Configure LUKS\n* Install related tools\n    * `apt install clevis-tpm2 clevis-luks clevis cryptsetup clevis-initramfs cryptsetup-initramfs lvm2`\n* Bind LUKS to TPM without checking PCR\n    * `clevis luks bind -d /dev/nvme0n1p4 tpm2 '{}'`\n* Reboot\n    * You will see following output in boot logs, LUKS unlock with TPM2 and boot successfully\n\n## Install Proxmox\n* Following instruction from Proxmox Wiki \n    * [https://pve.proxmox.com/wiki/Install_Proxmox_VE_on_Debian_12_Bookworm](https://pve.proxmox.com/wiki/Install_Proxmox_VE_on_Debian_12_Bookworm)\n* Enable Proxmox APT source\n    * `echo \"deb [arch=amd64] http://download.proxmox.com/debian/pve bookworm pve-no-subscription\" \u003e /etc/apt/sources.list.d/pve-install-repo.list`\n    * `apt install -y wget`\n    * `wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg`\n    * `apt update \u0026\u0026 apt full-upgrade -y`\n* Install Proxmox kernel\n    * `apt install proxmox-default-kernel -y`\n    * `reboot`\n* Install Proxmox\n    * `apt install proxmox-ve postfix open-iscsi chrony -y`\n* Remove Debian kernel image\n    * `apt remove linux-image-amd64 'linux-image-6.1*'`\n    * `update-grub`\n    * `reboot`\n* Add `local-lvm` storage\n    * ` pvesm add lvmthin local-lvm --thinpool data --vgname pve`\n* Enable Secure boot in BIOS\n* Now your system will boot with \n\n## Enable Trusted Boot for PVE\n* Check TPM hash algorithm\n    * `tpm2_pcrread`\n    * Please check banks in TPM, make sure ID 7,8,9 have values.\n    * Check hash algorithm that contains ID 7,8,9, eg. `SHA256`\n* Unbind LUKS with TPM\n```\nroot@pvebox2:~# clevis luks unbind -d /dev/nvme0n1p4 -s 1\nThe unbind operation will wipe a slot. This operation is unrecoverable.\nDo you wish to erase LUKS slot 1 on /dev/nvme0n1p4? [ynYN] y\nEnter any remaining passphrase:\n```\n* Bind LUKS with TPM PCR ID 7,8,9\n    * `clevis luks bind -d /dev/nvme0n1p4 tpm2 '{\"pcr_ids\":\"7,8,9\"}'`\n    * You need to input password during boot if you update kernel and initramfs.\n\n## Enable auto-sealing during updating kernel and initramfs\n* Root access will BREAK this mechanism, don't setup up this if you want to share root access to others.\n* To make LUKS unlock automatically, we need to unbind and re-bind LUKS with PCR ID 7,8,9\n* Create a unlock key in `/root`\n    * `dd if=/dev/urandom of=/root/.luks_unlock_key bs=1 count=32`\n    * `chmod 400 /root/.luks_unlock_key`\n* Add key to LUKS\n    * `cryptsetup luksAddKey /dev/nvme0n1p4 /root/.luks_unlock_key`\n* Create `/etc/systemd/system/tpm-full-reseal.service` to bind LUKS with TPM during boot\n* Create re-bind script `/usr/local/sbin/tpm-full-reseal-post-boot.sh`\n* Enable reseal service\n    * `chmod 700 /usr/local/sbin/tpm-full-reseal-post-boot.sh`\n    * `systemctl enable tpm-full-reseal.service`\n* Create initramfs hook `/etc/initramfs/post-update.d/99-tpm-auto-reseal`\n* Enable initramfs hook\n    * `chmod 700 /etc/initramfs/post-update.d/99-tpm-auto-reseal`\n## Testing\n* Check LUKS is binded with TPM PCR ID 7,8,9\n```\nroot@pvebox2:~# clevis luks list -d /dev/nvme0n1p4\n2: tpm2 '{\"hash\":\"sha256\",\"key\":\"ecc\",\"pcr_bank\":\"sha256\",\"pcr_ids\":\"7,8,9\"}'\n```\n* Update initramfs to check unseal is working\n```\nroot@pvebox2:~# update-initramfs -k all -u\nupdate-initramfs: Generating /boot/initrd.img-6.8.12-11-pve\nTPM Hook: initramfs for kernel 6.8.12-11-pve has been updated at /boot/initrd.img-6.8.12-11-pve.\nStarting TPM auto-reseal process.\nUnbinding existing TPM token from slot 2...\nBinding temporary token using PCR 7...\nCreating trigger file for post-reboot finalization...\nTPM Hook: Successfully prepared system for reboot. A reboot is required to finalize TPM configuration.\nRunning hook script 'zz-proxmox-boot'..\nRe-executing '/etc/kernel/postinst.d/zz-proxmox-boot' in new private mount namespace..\nNo /etc/kernel/proxmox-boot-uuids found, skipping ESP sync.\nSystem booted in EFI-mode but 'grub-efi-amd64' meta-package not installed!\nInstall 'grub-efi-amd64' to get updates.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpccr10001%2Fpve-trusted-boot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpccr10001%2Fpve-trusted-boot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpccr10001%2Fpve-trusted-boot/lists"}