[{"data":1,"prerenderedAt":1603},["ShallowReactive",2],{"page-by-slug-ubuntu-the-hard-way":3},{"id":4,"title":5,"body":6,"date":1581,"description":12,"extension":1582,"meta":1583,"navigation":308,"path":1585,"seo":1586,"slugs":1587,"stem":1589,"tags":1590,"__hash__":1602,"isRetrievedByPath":308},"journal\u002Fjournal\u002F2026-03-19-ubuntu-the-hard-way.md","Ubuntu The Hard Way",{"type":7,"value":8,"toc":1559},"minimark",[9,13,16,19,22,25,41,44,49,52,56,61,64,153,155,159,163,166,185,189,192,210,212,216,227,231,261,263,267,271,274,395,399,402,488,490,494,497,501,542,544,548,551,555,569,573,576,678,682,685,733,737,740,743,996,1000,1037,1041,1048,1051,1106,1110,1113,1212,1214,1218,1221,1225,1237,1241,1244,1359,1363,1366,1413,1417,1420,1440,1442,1446,1449,1453,1518,1520,1524,1527,1531,1540,1542,1546,1549,1552,1555],[10,11,12],"p",{},"Updated On: 2026-04-27",[10,14,15],{},"Someone once asked how I setup Ubuntu the hard way with LUKS encrypted BTRFS subvolumes and TPM2\nsupport.",[10,17,18],{},"Disclaimer:\nThe Ubuntu installer is my recommended way of setting up Ubuntu until you want to dive into how it\nall works. If you're new to Linux, I recommend following along in a VM, or other low-risk\nenvironment.",[10,20,21],{},"I'm trying to showcase the commands and general approach here. Your milage may very.",[10,23,24],{},"Why Ubuntu without the installer:",[26,27,28,32,35,38],"ul",{},[29,30,31],"li",{},"More control over partitions",[29,33,34],{},"More control over the boot process from the start",[29,36,37],{},"Ability to make semi-standard or non-standard choices like systemd-boot and dracut.",[29,39,40],{},"For all the friends we meet along the way.",[42,43],"hr",{},[45,46,48],"h2",{"id":47},"intro-and-setup","Intro And Setup",[10,50,51],{},"To get started, we'll setup our partition table. I use parted for this. I am going to use btrfs for the main OS, and fat32 for the efi+esp partition. Fat32 might be old, but it's required for UEFI boots. I consider my data more important than the ESP to boot into the system, so the plan is to create our esp partition at the end of the drive so that it can be resized or relocated later if needed.",[45,53,55],{"id":54},"partitioning","Partitioning",[57,58,60],"h3",{"id":59},"using-parted","Using Parted",[10,62,63],{},"I consider user data to be more important than boot-concerns, so if I choose to add other drives, I\nmight choose to boot from there. As such, I place the ESP at the end of the device so that resizing\ndata drives later overtop of it, or shrinking them to grow the space, is trivial. It will always be\neasier to recreate the ESP than a user's data.",[65,66,71],"pre",{"className":67,"code":68,"language":69,"meta":70,"style":70},"language-bash shiki shiki-themes github-light github-dark","parted -a optimal \u002Fdev\u002Fvda\nmktable gpt\nmkpart prevoe-esp -2048M 100%\nset 1 esp on\nmkpart prevoe-luks-0 0% -2048M\nq\n\n","bash","",[72,73,74,94,103,118,133,147],"code",{"__ignoreMap":70},[75,76,79,83,87,91],"span",{"class":77,"line":78},"line",1,[75,80,82],{"class":81},"sScJk","parted",[75,84,86],{"class":85},"sj4cs"," -a",[75,88,90],{"class":89},"sZZnC"," optimal",[75,92,93],{"class":89}," \u002Fdev\u002Fvda\n",[75,95,97,100],{"class":77,"line":96},2,[75,98,99],{"class":81},"mktable",[75,101,102],{"class":89}," gpt\n",[75,104,106,109,112,115],{"class":77,"line":105},3,[75,107,108],{"class":81},"mkpart",[75,110,111],{"class":89}," prevoe-esp",[75,113,114],{"class":85}," -2048M",[75,116,117],{"class":89}," 100%\n",[75,119,121,124,127,130],{"class":77,"line":120},4,[75,122,123],{"class":85},"set",[75,125,126],{"class":85}," 1",[75,128,129],{"class":89}," esp",[75,131,132],{"class":89}," on\n",[75,134,136,138,141,144],{"class":77,"line":135},5,[75,137,108],{"class":81},[75,139,140],{"class":89}," prevoe-luks-0",[75,142,143],{"class":89}," 0%",[75,145,146],{"class":85}," -2048M\n",[75,148,150],{"class":77,"line":149},6,[75,151,152],{"class":81},"q\n",[42,154],{},[45,156,158],{"id":157},"encryption-setup","Encryption Setup",[57,160,162],{"id":161},"luks-formatting","LUKS Formatting",[10,164,165],{},"Next we setup the data partition to use LUKS2. Boring, Simple, Predictable.",[65,167,169],{"className":67,"code":168,"language":69,"meta":70,"style":70},"cryptsetup luksFormat --type=luks2 \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-luks-0\n",[72,170,171],{"__ignoreMap":70},[75,172,173,176,179,182],{"class":77,"line":78},[75,174,175],{"class":81},"cryptsetup",[75,177,178],{"class":89}," luksFormat",[75,180,181],{"class":85}," --type=luks2",[75,183,184],{"class":89}," \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-luks-0\n",[57,186,188],{"id":187},"decrypt-the-disk","Decrypt the Disk",[10,190,191],{},"Decrypt the partition so that we can install into it. I choose to put btrfs into\nthe decrypted partitions label so that I know at a glance what's what when\nrecovering.",[65,193,195],{"className":67,"code":194,"language":69,"meta":70,"style":70},"cryptsetup open \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-luks-0 prevoe-btrfs-0\n\n",[72,196,197],{"__ignoreMap":70},[75,198,199,201,204,207],{"class":77,"line":78},[75,200,175],{"class":81},[75,202,203],{"class":89}," open",[75,205,206],{"class":89}," \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-luks-0",[75,208,209],{"class":89}," prevoe-btrfs-0\n",[42,211],{},[45,213,215],{"id":214},"drive-formatting","Drive Formatting",[10,217,218,219,222,223,226],{},"Formatting the disk with btrfs is easy enough. Notably I'm setting the label here which matches the partition name. This means ",[72,220,221],{},"\u002Fdev\u002Fmapper\u002Fprevoe-btrfs-0"," will now be the same as ",[72,224,225],{},"\u002Fdev\u002Fdisk\u002Fby-label\u002Fprevoe-btrfs-0"," after this step.",[57,228,230],{"id":229},"format-devices","Format Devices",[65,232,234],{"className":67,"code":233,"language":69,"meta":70,"style":70},"mkfs.btrfs --label prevoe-btrfs-0 \u002Fdev\u002Fmapper\u002Fprevoe-btrfs-0\nmkfs.fat -F32 \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-esp\n",[72,235,236,250],{"__ignoreMap":70},[75,237,238,241,244,247],{"class":77,"line":78},[75,239,240],{"class":81},"mkfs.btrfs",[75,242,243],{"class":85}," --label",[75,245,246],{"class":89}," prevoe-btrfs-0",[75,248,249],{"class":89}," \u002Fdev\u002Fmapper\u002Fprevoe-btrfs-0\n",[75,251,252,255,258],{"class":77,"line":96},[75,253,254],{"class":81},"mkfs.fat",[75,256,257],{"class":85}," -F32",[75,259,260],{"class":89}," \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-esp\n",[42,262],{},[45,264,266],{"id":265},"mounts-and-subvolumes","Mounts And Subvolumes",[57,268,270],{"id":269},"btrfs-layout-setup","BTRFS Layout Setup",[10,272,273],{},"BTRFS has subvolumes, and we want to use them for the root of our OS, so we mount the root of the BTRFS partition and create the subvolumes of interest.",[65,275,277],{"className":67,"code":276,"language":69,"meta":70,"style":70},"mkdir \u002Fmnt\u002Fbtrfs-full\nmount \u002Fdev\u002Fdisk\u002Fby-label\u002Fprevoe-btrfs-0 \u002Fmnt\u002Fbtrfs-full\ncd \u002Fmnt\u002Fbtrfs-full\n\n# Now create each directory, and the neach volume\nmkdir -p os\u002Froot\u002Fubuntu-24.04\nbtrfs subvol create os\u002Froot\u002Fubuntu-24.04\u002F@live\n\nmkdir -p home\u002Fcatchall\nbtrfs subvol create home\u002Fcatchall\u002F@live\n\nmkdir -p home\u002Fcprevoe\nbtrfs subvol create home\u002Fcprevoe\u002F@live\n\n",[72,278,279,287,297,304,310,316,326,341,346,356,368,373,383],{"__ignoreMap":70},[75,280,281,284],{"class":77,"line":78},[75,282,283],{"class":81},"mkdir",[75,285,286],{"class":89}," \u002Fmnt\u002Fbtrfs-full\n",[75,288,289,292,295],{"class":77,"line":96},[75,290,291],{"class":81},"mount",[75,293,294],{"class":89}," \u002Fdev\u002Fdisk\u002Fby-label\u002Fprevoe-btrfs-0",[75,296,286],{"class":89},[75,298,299,302],{"class":77,"line":105},[75,300,301],{"class":85},"cd",[75,303,286],{"class":89},[75,305,306],{"class":77,"line":120},[75,307,309],{"emptyLinePlaceholder":308},true,"\n",[75,311,312],{"class":77,"line":135},[75,313,315],{"class":314},"sJ8bj","# Now create each directory, and the neach volume\n",[75,317,318,320,323],{"class":77,"line":149},[75,319,283],{"class":81},[75,321,322],{"class":85}," -p",[75,324,325],{"class":89}," os\u002Froot\u002Fubuntu-24.04\n",[75,327,329,332,335,338],{"class":77,"line":328},7,[75,330,331],{"class":81},"btrfs",[75,333,334],{"class":89}," subvol",[75,336,337],{"class":89}," create",[75,339,340],{"class":89}," os\u002Froot\u002Fubuntu-24.04\u002F@live\n",[75,342,344],{"class":77,"line":343},8,[75,345,309],{"emptyLinePlaceholder":308},[75,347,349,351,353],{"class":77,"line":348},9,[75,350,283],{"class":81},[75,352,322],{"class":85},[75,354,355],{"class":89}," home\u002Fcatchall\n",[75,357,359,361,363,365],{"class":77,"line":358},10,[75,360,331],{"class":81},[75,362,334],{"class":89},[75,364,337],{"class":89},[75,366,367],{"class":89}," home\u002Fcatchall\u002F@live\n",[75,369,371],{"class":77,"line":370},11,[75,372,309],{"emptyLinePlaceholder":308},[75,374,376,378,380],{"class":77,"line":375},12,[75,377,283],{"class":81},[75,379,322],{"class":85},[75,381,382],{"class":89}," home\u002Fcprevoe\n",[75,384,386,388,390,392],{"class":77,"line":385},13,[75,387,331],{"class":81},[75,389,334],{"class":89},[75,391,337],{"class":89},[75,393,394],{"class":89}," home\u002Fcprevoe\u002F@live\n",[57,396,398],{"id":397},"os-layout-setup-leveraging-subvolumes","OS Layout Setup Leveraging Subvolumes",[10,400,401],{},"We mount the subvolumes we've created and the esp so that we have the partition layout of our new OS\navailable.",[65,403,405],{"className":67,"code":404,"language":69,"meta":70,"style":70},"mkdir -p \u002Fmnt\u002Frealroot\u002F\nmount \u002Fdev\u002Fdisk\u002Fby-label\u002Fprevoe-btrfs-0 -o subvol=\u002Fos\u002Froot\u002Fubuntu-24.04\u002F@live \u002Fmnt\u002Frealroot\nmkdir -p \u002Fmnt\u002Frealroot\u002Fboot\u002Fefi \u002Fmnt\u002Frealroot\u002Fhome\nmount \u002Fdev\u002Fdisk\u002Fby-label\u002Fprevoe-btrfs-0 -o subvol=\u002Fhome\u002Fcatchall\u002F@live \u002Fmnt\u002Frealroot\u002Fhome\nmkdir -p \u002Fmnt\u002Frealroot\u002Fhome\u002Fcprevoe\nmount \u002Fdev\u002Fdisk\u002Fby-label\u002Fprevoe-btrfs-0 -o subvol=\u002Fhome\u002Fcprevoe\u002F@live \u002Fmnt\u002Frealroot\u002Fhome\u002Fcprevoe\nmount \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-esp \u002Fmnt\u002Frealroot\u002Fboot\u002Fefi\n",[72,406,407,416,431,443,456,465,478],{"__ignoreMap":70},[75,408,409,411,413],{"class":77,"line":78},[75,410,283],{"class":81},[75,412,322],{"class":85},[75,414,415],{"class":89}," \u002Fmnt\u002Frealroot\u002F\n",[75,417,418,420,422,425,428],{"class":77,"line":96},[75,419,291],{"class":81},[75,421,294],{"class":89},[75,423,424],{"class":85}," -o",[75,426,427],{"class":89}," subvol=\u002Fos\u002Froot\u002Fubuntu-24.04\u002F@live",[75,429,430],{"class":89}," \u002Fmnt\u002Frealroot\n",[75,432,433,435,437,440],{"class":77,"line":105},[75,434,283],{"class":81},[75,436,322],{"class":85},[75,438,439],{"class":89}," \u002Fmnt\u002Frealroot\u002Fboot\u002Fefi",[75,441,442],{"class":89}," \u002Fmnt\u002Frealroot\u002Fhome\n",[75,444,445,447,449,451,454],{"class":77,"line":120},[75,446,291],{"class":81},[75,448,294],{"class":89},[75,450,424],{"class":85},[75,452,453],{"class":89}," subvol=\u002Fhome\u002Fcatchall\u002F@live",[75,455,442],{"class":89},[75,457,458,460,462],{"class":77,"line":135},[75,459,283],{"class":81},[75,461,322],{"class":85},[75,463,464],{"class":89}," \u002Fmnt\u002Frealroot\u002Fhome\u002Fcprevoe\n",[75,466,467,469,471,473,476],{"class":77,"line":149},[75,468,291],{"class":81},[75,470,294],{"class":89},[75,472,424],{"class":85},[75,474,475],{"class":89}," subvol=\u002Fhome\u002Fcprevoe\u002F@live",[75,477,464],{"class":89},[75,479,480,482,485],{"class":77,"line":328},[75,481,291],{"class":81},[75,483,484],{"class":89}," \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-esp",[75,486,487],{"class":89}," \u002Fmnt\u002Frealroot\u002Fboot\u002Fefi\n",[42,489],{},[45,491,493],{"id":492},"os-foundation-bootstrap","OS Foundation Bootstrap",[10,495,496],{},"This is the heaviest step where we actually install everything which needs to be installed for a minimum system. For speed and network reasons, I'm using a local passthrough mirror. You can replace it with your ubuntu mirror of choice.",[57,498,500],{"id":499},"install-os-base-with-debootstrap","Install OS Base with Debootstrap",[65,502,504],{"className":67,"code":503,"language":69,"meta":70,"style":70},"apt install debootstrap\ndebootstrap --arch=amd64 --variant=minbase noble \u002Fmnt\u002Frealroot \\\n  http:\u002F\u002Fapt-cache-ng.k8s.andro.zdani.prevoe.com\u002Farchive.ubuntu.com\u002Fubuntu\u002F\n",[72,505,506,517,537],{"__ignoreMap":70},[75,507,508,511,514],{"class":77,"line":78},[75,509,510],{"class":81},"apt",[75,512,513],{"class":89}," install",[75,515,516],{"class":89}," debootstrap\n",[75,518,519,522,525,528,531,534],{"class":77,"line":96},[75,520,521],{"class":81},"debootstrap",[75,523,524],{"class":85}," --arch=amd64",[75,526,527],{"class":85}," --variant=minbase",[75,529,530],{"class":89}," noble",[75,532,533],{"class":89}," \u002Fmnt\u002Frealroot",[75,535,536],{"class":85}," \\\n",[75,538,539],{"class":77,"line":105},[75,540,541],{"class":89},"  http:\u002F\u002Fapt-cache-ng.k8s.andro.zdani.prevoe.com\u002Farchive.ubuntu.com\u002Fubuntu\u002F\n",[42,543],{},[45,545,547],{"id":546},"os-manual-configuration","OS Manual Configuration",[10,549,550],{},"The arch-install-scripts gives us access to genfstab and arch-chroot which are super useful.",[57,552,554],{"id":553},"install-arch-install-scripts","Install arch-install-scripts",[65,556,558],{"className":67,"code":557,"language":69,"meta":70,"style":70},"apt install arch-install-scripts\n",[72,559,560],{"__ignoreMap":70},[75,561,562,564,566],{"class":77,"line":78},[75,563,510],{"class":81},[75,565,513],{"class":89},[75,567,568],{"class":89}," arch-install-scripts\n",[57,570,572],{"id":571},"create-the-fstab-and-cryptab","Create The fstab And cryptab",[10,574,575],{},"Next we generate our fstab, and then we generate our crypttab",[65,577,579],{"className":67,"code":578,"language":69,"meta":70,"style":70},"mkdir -p \u002Fmnt\u002Frealroot\u002Fetc\ngenfstab -U \u002Fmnt\u002Frealroot > \u002Fmnt\u002Frealroot\u002Fetc\u002Ffstab\n\n# We remove subvol references so we can swap out the subvolumes as desired\nsed -i 's\u002Fsubvolid=[0-9]*,\u002F\u002Fg' \u002Fmnt\u002Frealroot\u002Fetc\u002Ffstab\n\nROOT_UUID=\"$(blkid -s UUID -o value \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-luks-0)\"\necho \"prevoe-btrfs-0 UUID=${ROOT_UUID} none luks,tpm2-device=auto\" > \u002Fmnt\u002Frealroot\u002Fetc\u002Fcrypttab\n\n",[72,580,581,590,607,611,616,629,633,660],{"__ignoreMap":70},[75,582,583,585,587],{"class":77,"line":78},[75,584,283],{"class":81},[75,586,322],{"class":85},[75,588,589],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\n",[75,591,592,595,598,600,604],{"class":77,"line":96},[75,593,594],{"class":81},"genfstab",[75,596,597],{"class":85}," -U",[75,599,533],{"class":89},[75,601,603],{"class":602},"szBVR"," >",[75,605,606],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Ffstab\n",[75,608,609],{"class":77,"line":105},[75,610,309],{"emptyLinePlaceholder":308},[75,612,613],{"class":77,"line":120},[75,614,615],{"class":314},"# We remove subvol references so we can swap out the subvolumes as desired\n",[75,617,618,621,624,627],{"class":77,"line":135},[75,619,620],{"class":81},"sed",[75,622,623],{"class":85}," -i",[75,625,626],{"class":89}," 's\u002Fsubvolid=[0-9]*,\u002F\u002Fg'",[75,628,606],{"class":89},[75,630,631],{"class":77,"line":149},[75,632,309],{"emptyLinePlaceholder":308},[75,634,635,639,642,645,648,651,654,657],{"class":77,"line":328},[75,636,638],{"class":637},"sVt8B","ROOT_UUID",[75,640,641],{"class":602},"=",[75,643,644],{"class":89},"\"$(",[75,646,647],{"class":81},"blkid",[75,649,650],{"class":85}," -s",[75,652,653],{"class":89}," UUID ",[75,655,656],{"class":85},"-o",[75,658,659],{"class":89}," value \u002Fdev\u002Fdisk\u002Fby-partlabel\u002Fprevoe-luks-0)\"\n",[75,661,662,665,668,670,673,675],{"class":77,"line":343},[75,663,664],{"class":85},"echo",[75,666,667],{"class":89}," \"prevoe-btrfs-0 UUID=${",[75,669,638],{"class":637},[75,671,672],{"class":89},"} none luks,tpm2-device=auto\"",[75,674,603],{"class":602},[75,676,677],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fcrypttab\n",[57,679,681],{"id":680},"setup-basic-networking","Setup Basic Networking",[10,683,684],{},"Also to avoid errors, we set the hostname, and setup the expected hosts file.",[65,686,688],{"className":67,"code":687,"language":69,"meta":70,"style":70},"echo prevoe-ubuntu > \u002Fmnt\u002Frealroot\u002Fetc\u002Fhostname\ncat > \u002Fmnt\u002Frealroot\u002Fetc\u002Fhosts \u003C\u003C EOF\n127.0.0.1 localhost\n127.0.1.1 prevoe-ubuntu\nEOF\n\n",[72,689,690,702,718,723,728],{"__ignoreMap":70},[75,691,692,694,697,699],{"class":77,"line":78},[75,693,664],{"class":85},[75,695,696],{"class":89}," prevoe-ubuntu",[75,698,603],{"class":602},[75,700,701],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fhostname\n",[75,703,704,707,709,712,715],{"class":77,"line":96},[75,705,706],{"class":81},"cat",[75,708,603],{"class":602},[75,710,711],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fhosts",[75,713,714],{"class":602}," \u003C\u003C",[75,716,717],{"class":89}," EOF\n",[75,719,720],{"class":77,"line":105},[75,721,722],{"class":89},"127.0.0.1 localhost\n",[75,724,725],{"class":77,"line":120},[75,726,727],{"class":89},"127.0.1.1 prevoe-ubuntu\n",[75,729,730],{"class":77,"line":135},[75,731,732],{"class":89},"EOF\n",[57,734,736],{"id":735},"kernel-cmdline-generation-hook","Kernel CMDLINE Generation Hook",[10,738,739],{},"Instead of grub, we're going to use systemd-boot, and dracut. With a bit of tinkering, one\ncan setup the tpm to provide luks the key to automatically decrypt the drive.",[10,741,742],{},"Ubuntu seems to be heading in the direction of dracut producing the initrd, and systemd-ukify\ncreating the universal kernal image (UKI). We can hook into this cleaner and in a more automated way\nthan if we did it all in dracut, so here we go.",[65,744,746],{"className":67,"code":745,"language":69,"meta":70,"style":70},"mkdir -p \u002Fmnt\u002Frealroot\u002Fetc\u002Fkernel\u002Fpreinst.d\nFILE=\u002Fmnt\u002Frealroot\u002Fetc\u002Fkernel\u002Fpreinst.d\u002F99-generate-kernel-cmdline\ncat > ${FILE} \u003C\u003C ENDOFSCRIPT\n#!\u002Fbin\u002Fbash\n\n# We will define our own cmdline so crypttab is used during boot\nCMDLINE_FILE=\u002Fetc\u002Fkernel\u002Fcmdline\n\nroot_device=\\$(awk '\\$2 == \"\u002F\" { print \\$1 }' \u002Fetc\u002Ffstab)\nroot_device_options=\\$(awk '\\$2 == \"\u002F\" { print \\$4 }' \u002Fetc\u002Ffstab)\n\n# If root device not in fstab, fallback to findmnt\nif [ -z \"\\${root_device}\" ]; then\n    # Square brackets are possible in BTRFS\n    root_device=\\$(findmnt -no SOURCE \u002F | cut -f1 -d'[')\n    root_device_options=\\$(findmnt -no OPTIONS \u002F)\nfi\n\n[ -z \"\\${root_device}\" -o -z \"\\${root_device_options}\" ] && exit 0\n\ncat > \"\\${CMDLINE_FILE}\" \u003C\u003C EOF\nquiet splash\nroot=\\${root_device}\nrootflags=\\${root_device_options}\nrd.luks.crypttab=1\nEOF\nENDOFSCRIPT\n\nchmod +x ${FILE}\n",[72,747,748,757,767,782,787,791,796,801,805,826,844,848,853,863,869,880,891,897,902,918,923,934,940,951,962,968,973,979,984],{"__ignoreMap":70},[75,749,750,752,754],{"class":77,"line":78},[75,751,283],{"class":81},[75,753,322],{"class":85},[75,755,756],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fkernel\u002Fpreinst.d\n",[75,758,759,762,764],{"class":77,"line":96},[75,760,761],{"class":637},"FILE",[75,763,641],{"class":602},[75,765,766],{"class":89},"\u002Fmnt\u002Frealroot\u002Fetc\u002Fkernel\u002Fpreinst.d\u002F99-generate-kernel-cmdline\n",[75,768,769,771,773,776,779],{"class":77,"line":105},[75,770,706],{"class":81},[75,772,603],{"class":602},[75,774,775],{"class":637}," ${FILE} ",[75,777,778],{"class":602},"\u003C\u003C",[75,780,781],{"class":89}," ENDOFSCRIPT\n",[75,783,784],{"class":77,"line":120},[75,785,786],{"class":89},"#!\u002Fbin\u002Fbash\n",[75,788,789],{"class":77,"line":135},[75,790,309],{"emptyLinePlaceholder":308},[75,792,793],{"class":77,"line":149},[75,794,795],{"class":89},"# We will define our own cmdline so crypttab is used during boot\n",[75,797,798],{"class":77,"line":328},[75,799,800],{"class":89},"CMDLINE_FILE=\u002Fetc\u002Fkernel\u002Fcmdline\n",[75,802,803],{"class":77,"line":343},[75,804,309],{"emptyLinePlaceholder":308},[75,806,807,810,813,816,818,821,823],{"class":77,"line":348},[75,808,809],{"class":89},"root_device=",[75,811,812],{"class":85},"\\$",[75,814,815],{"class":89},"(awk '",[75,817,812],{"class":85},[75,819,820],{"class":89},"2 == \"\u002F\" { print ",[75,822,812],{"class":85},[75,824,825],{"class":89},"1 }' \u002Fetc\u002Ffstab)\n",[75,827,828,831,833,835,837,839,841],{"class":77,"line":358},[75,829,830],{"class":89},"root_device_options=",[75,832,812],{"class":85},[75,834,815],{"class":89},[75,836,812],{"class":85},[75,838,820],{"class":89},[75,840,812],{"class":85},[75,842,843],{"class":89},"4 }' \u002Fetc\u002Ffstab)\n",[75,845,846],{"class":77,"line":370},[75,847,309],{"emptyLinePlaceholder":308},[75,849,850],{"class":77,"line":375},[75,851,852],{"class":89},"# If root device not in fstab, fallback to findmnt\n",[75,854,855,858,860],{"class":77,"line":385},[75,856,857],{"class":89},"if [ -z \"",[75,859,812],{"class":85},[75,861,862],{"class":89},"{root_device}\" ]; then\n",[75,864,866],{"class":77,"line":865},14,[75,867,868],{"class":89},"    # Square brackets are possible in BTRFS\n",[75,870,872,875,877],{"class":77,"line":871},15,[75,873,874],{"class":89},"    root_device=",[75,876,812],{"class":85},[75,878,879],{"class":89},"(findmnt -no SOURCE \u002F | cut -f1 -d'[')\n",[75,881,883,886,888],{"class":77,"line":882},16,[75,884,885],{"class":89},"    root_device_options=",[75,887,812],{"class":85},[75,889,890],{"class":89},"(findmnt -no OPTIONS \u002F)\n",[75,892,894],{"class":77,"line":893},17,[75,895,896],{"class":89},"fi\n",[75,898,900],{"class":77,"line":899},18,[75,901,309],{"emptyLinePlaceholder":308},[75,903,905,908,910,913,915],{"class":77,"line":904},19,[75,906,907],{"class":89},"[ -z \"",[75,909,812],{"class":85},[75,911,912],{"class":89},"{root_device}\" -o -z \"",[75,914,812],{"class":85},[75,916,917],{"class":89},"{root_device_options}\" ] && exit 0\n",[75,919,921],{"class":77,"line":920},20,[75,922,309],{"emptyLinePlaceholder":308},[75,924,926,929,931],{"class":77,"line":925},21,[75,927,928],{"class":89},"cat > \"",[75,930,812],{"class":85},[75,932,933],{"class":89},"{CMDLINE_FILE}\" \u003C\u003C EOF\n",[75,935,937],{"class":77,"line":936},22,[75,938,939],{"class":89},"quiet splash\n",[75,941,943,946,948],{"class":77,"line":942},23,[75,944,945],{"class":89},"root=",[75,947,812],{"class":85},[75,949,950],{"class":89},"{root_device}\n",[75,952,954,957,959],{"class":77,"line":953},24,[75,955,956],{"class":89},"rootflags=",[75,958,812],{"class":85},[75,960,961],{"class":89},"{root_device_options}\n",[75,963,965],{"class":77,"line":964},25,[75,966,967],{"class":89},"rd.luks.crypttab=1\n",[75,969,971],{"class":77,"line":970},26,[75,972,732],{"class":89},[75,974,976],{"class":77,"line":975},27,[75,977,978],{"class":89},"ENDOFSCRIPT\n",[75,980,982],{"class":77,"line":981},28,[75,983,309],{"emptyLinePlaceholder":308},[75,985,987,990,993],{"class":77,"line":986},29,[75,988,989],{"class":81},"chmod",[75,991,992],{"class":89}," +x",[75,994,995],{"class":637}," ${FILE}\n",[57,997,999],{"id":998},"kernel-uki-configuration","Kernel UKI Configuration",[65,1001,1003],{"className":67,"code":1002,"language":69,"meta":70,"style":70},"cat > \u002Fmnt\u002Frealroot\u002Fetc\u002Fkernel\u002Finstall.conf \u003C\u003C EOF\nlayout=uki\ninitrd_generator=dracut\nuki_generator=ukify\nEOF\n\n",[72,1004,1005,1018,1023,1028,1033],{"__ignoreMap":70},[75,1006,1007,1009,1011,1014,1016],{"class":77,"line":78},[75,1008,706],{"class":81},[75,1010,603],{"class":602},[75,1012,1013],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fkernel\u002Finstall.conf",[75,1015,714],{"class":602},[75,1017,717],{"class":89},[75,1019,1020],{"class":77,"line":96},[75,1021,1022],{"class":89},"layout=uki\n",[75,1024,1025],{"class":77,"line":105},[75,1026,1027],{"class":89},"initrd_generator=dracut\n",[75,1029,1030],{"class":77,"line":120},[75,1031,1032],{"class":89},"uki_generator=ukify\n",[75,1034,1035],{"class":77,"line":135},[75,1036,732],{"class":89},[57,1038,1040],{"id":1039},"tell-dracut-to-include-crypttab","Tell Dracut to Include crypttab",[10,1042,1043,1044,1047],{},"By default, the kernel now assumes that you either use ",[72,1045,1046],{},"gpt-auto-root"," or tell it where to find root\nwith kernel command line arguments. This is great except our root is behind luks. Rather than tell\nthe kernel via cmdline how to access it, I much prefer to embed that configuration instead.",[10,1049,1050],{},"So, we tell dracut to include the crypttab here. We also include tpm2-tss so it can decrypt using\nthe TPM.",[65,1052,1054],{"className":67,"code":1053,"language":69,"meta":70,"style":70},"mkdir -p \u002Fmnt\u002Frealroot\u002Fetc\u002Fdracut.conf.d\ncat > \u002Fmnt\u002Frealroot\u002Fetc\u002Fdracut.conf.d\u002F99-include-crypttab.conf \u003C\u003C EOF\n# Required for automatic unlocking with tpm2\nadd_dracutmodules+=\" tpm2-tss \"\n\n# Required for decrypting with rd.luks.crypttab=1\ninstall_items+=\" \u002Fetc\u002Fcrypttab \"\nEOF\n\n",[72,1055,1056,1065,1078,1083,1088,1092,1097,1102],{"__ignoreMap":70},[75,1057,1058,1060,1062],{"class":77,"line":78},[75,1059,283],{"class":81},[75,1061,322],{"class":85},[75,1063,1064],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fdracut.conf.d\n",[75,1066,1067,1069,1071,1074,1076],{"class":77,"line":96},[75,1068,706],{"class":81},[75,1070,603],{"class":602},[75,1072,1073],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fdracut.conf.d\u002F99-include-crypttab.conf",[75,1075,714],{"class":602},[75,1077,717],{"class":89},[75,1079,1080],{"class":77,"line":105},[75,1081,1082],{"class":89},"# Required for automatic unlocking with tpm2\n",[75,1084,1085],{"class":77,"line":120},[75,1086,1087],{"class":89},"add_dracutmodules+=\" tpm2-tss \"\n",[75,1089,1090],{"class":77,"line":135},[75,1091,309],{"emptyLinePlaceholder":308},[75,1093,1094],{"class":77,"line":149},[75,1095,1096],{"class":89},"# Required for decrypting with rd.luks.crypttab=1\n",[75,1098,1099],{"class":77,"line":328},[75,1100,1101],{"class":89},"install_items+=\" \u002Fetc\u002Fcrypttab \"\n",[75,1103,1104],{"class":77,"line":343},[75,1105,732],{"class":89},[57,1107,1109],{"id":1108},"configure-apt-sourcs","Configure Apt Sourcs",[10,1111,1112],{},"An old-fashioned sources.list was created for us in the old format by debootstrap, so we want to get rid of that as well and modernize.",[65,1114,1116],{"className":67,"code":1115,"language":69,"meta":70,"style":70},"echo \"\" > \u002Fmnt\u002Frealroot\u002Fetc\u002Fapt\u002Fsources.list\n\ncat > \u002Fmnt\u002Frealroot\u002Fetc\u002Fapt\u002Fsources.list.d\u002Fubuntu.sources \u003C\u003C EOF\nTypes: deb\nURIs: http:\u002F\u002Fapt-cache-ng.k8s.andro.zdani.prevoe.com\u002Farchive.ubuntu.com\u002Fubuntu\u002F\nSuites: noble noble-updates noble-backports\nComponents: main universe restricted multiverse\nSigned-By: \u002Fusr\u002Fshare\u002Fkeyrings\u002Fubuntu-archive-keyring.gpg\n\n## Ubuntu security updates. Aside from URIs and Suites,\n## this should mirror your choices in the previous section.\nTypes: deb\nURIs: http:\u002F\u002Fapt-cache-ng.k8s.andro.zdani.prevoe.com\u002Fsecurity.ubuntu.com\u002Fubuntu\u002F\nSuites: noble-security\nComponents: main universe restricted multiverse\nSigned-By: \u002Fusr\u002Fshare\u002Fkeyrings\u002Fubuntu-archive-keyring.gpg\nEOF\n",[72,1117,1118,1130,1134,1147,1152,1157,1162,1167,1172,1176,1181,1186,1190,1195,1200,1204,1208],{"__ignoreMap":70},[75,1119,1120,1122,1125,1127],{"class":77,"line":78},[75,1121,664],{"class":85},[75,1123,1124],{"class":89}," \"\"",[75,1126,603],{"class":602},[75,1128,1129],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fapt\u002Fsources.list\n",[75,1131,1132],{"class":77,"line":96},[75,1133,309],{"emptyLinePlaceholder":308},[75,1135,1136,1138,1140,1143,1145],{"class":77,"line":105},[75,1137,706],{"class":81},[75,1139,603],{"class":602},[75,1141,1142],{"class":89}," \u002Fmnt\u002Frealroot\u002Fetc\u002Fapt\u002Fsources.list.d\u002Fubuntu.sources",[75,1144,714],{"class":602},[75,1146,717],{"class":89},[75,1148,1149],{"class":77,"line":120},[75,1150,1151],{"class":89},"Types: deb\n",[75,1153,1154],{"class":77,"line":135},[75,1155,1156],{"class":89},"URIs: http:\u002F\u002Fapt-cache-ng.k8s.andro.zdani.prevoe.com\u002Farchive.ubuntu.com\u002Fubuntu\u002F\n",[75,1158,1159],{"class":77,"line":149},[75,1160,1161],{"class":89},"Suites: noble noble-updates noble-backports\n",[75,1163,1164],{"class":77,"line":328},[75,1165,1166],{"class":89},"Components: main universe restricted multiverse\n",[75,1168,1169],{"class":77,"line":343},[75,1170,1171],{"class":89},"Signed-By: \u002Fusr\u002Fshare\u002Fkeyrings\u002Fubuntu-archive-keyring.gpg\n",[75,1173,1174],{"class":77,"line":348},[75,1175,309],{"emptyLinePlaceholder":308},[75,1177,1178],{"class":77,"line":358},[75,1179,1180],{"class":89},"## Ubuntu security updates. Aside from URIs and Suites,\n",[75,1182,1183],{"class":77,"line":370},[75,1184,1185],{"class":89},"## this should mirror your choices in the previous section.\n",[75,1187,1188],{"class":77,"line":375},[75,1189,1151],{"class":89},[75,1191,1192],{"class":77,"line":385},[75,1193,1194],{"class":89},"URIs: http:\u002F\u002Fapt-cache-ng.k8s.andro.zdani.prevoe.com\u002Fsecurity.ubuntu.com\u002Fubuntu\u002F\n",[75,1196,1197],{"class":77,"line":865},[75,1198,1199],{"class":89},"Suites: noble-security\n",[75,1201,1202],{"class":77,"line":871},[75,1203,1166],{"class":89},[75,1205,1206],{"class":77,"line":882},[75,1207,1171],{"class":89},[75,1209,1210],{"class":77,"line":893},[75,1211,732],{"class":89},[42,1213],{},[45,1215,1217],{"id":1216},"os-installation","OS Installation",[10,1219,1220],{},"We now have a basic skeleton of the OS, but it will not boot nor do anything useful yet. We chroot into this directory which allows us to interact with it as though it were the booted OS. We use arch-chroot from arch-install-scripts because it mounts all of the extras like \u002Fdev \u002Fproc and others for us.",[57,1222,1224],{"id":1223},"pivot-into-the-new-os","Pivot Into the new OS",[65,1226,1228],{"className":67,"code":1227,"language":69,"meta":70,"style":70},"arch-chroot \u002Fmnt\u002Frealroot\n",[72,1229,1230],{"__ignoreMap":70},[75,1231,1232,1235],{"class":77,"line":78},[75,1233,1234],{"class":81},"arch-chroot",[75,1236,430],{"class":89},[57,1238,1240],{"id":1239},"update-and-install-non-kernel-packages","Update and Install Non-Kernel Packages",[10,1242,1243],{},"And finally we have the installation. This is the heaviest part involving downloading a gig or two of packages and installing them all. The DEBIAN_FRONTEND prefix tells it to not pause to ask us for our opinions.",[65,1245,1247],{"className":67,"code":1246,"language":69,"meta":70,"style":70},"export DEBIAN_FRONTEND=noninteractive \napt update \\\n  && apt upgrade -yq \\\n  && apt install -yq \\\n     ubuntu-desktop-minimal \\\n     ubuntu-desktop \\\n     sudo \\\n     dracut \\\n     systemd-boot \\\n     systemd-ukify \\\n     btrfs-progs \\\n     tpm2-tools \\\n     gawk\n\n",[72,1248,1249,1262,1271,1286,1298,1305,1312,1319,1326,1333,1340,1347,1354],{"__ignoreMap":70},[75,1250,1251,1254,1257,1259],{"class":77,"line":78},[75,1252,1253],{"class":602},"export",[75,1255,1256],{"class":637}," DEBIAN_FRONTEND",[75,1258,641],{"class":602},[75,1260,1261],{"class":637},"noninteractive \n",[75,1263,1264,1266,1269],{"class":77,"line":96},[75,1265,510],{"class":81},[75,1267,1268],{"class":89}," update",[75,1270,536],{"class":85},[75,1272,1273,1276,1278,1281,1284],{"class":77,"line":105},[75,1274,1275],{"class":637},"  && ",[75,1277,510],{"class":81},[75,1279,1280],{"class":89}," upgrade",[75,1282,1283],{"class":85}," -yq",[75,1285,536],{"class":85},[75,1287,1288,1290,1292,1294,1296],{"class":77,"line":120},[75,1289,1275],{"class":637},[75,1291,510],{"class":81},[75,1293,513],{"class":89},[75,1295,1283],{"class":85},[75,1297,536],{"class":85},[75,1299,1300,1303],{"class":77,"line":135},[75,1301,1302],{"class":89},"     ubuntu-desktop-minimal",[75,1304,536],{"class":85},[75,1306,1307,1310],{"class":77,"line":149},[75,1308,1309],{"class":89},"     ubuntu-desktop",[75,1311,536],{"class":85},[75,1313,1314,1317],{"class":77,"line":328},[75,1315,1316],{"class":89},"     sudo",[75,1318,536],{"class":85},[75,1320,1321,1324],{"class":77,"line":343},[75,1322,1323],{"class":89},"     dracut",[75,1325,536],{"class":85},[75,1327,1328,1331],{"class":77,"line":348},[75,1329,1330],{"class":89},"     systemd-boot",[75,1332,536],{"class":85},[75,1334,1335,1338],{"class":77,"line":358},[75,1336,1337],{"class":89},"     systemd-ukify",[75,1339,536],{"class":85},[75,1341,1342,1345],{"class":77,"line":370},[75,1343,1344],{"class":89},"     btrfs-progs",[75,1346,536],{"class":85},[75,1348,1349,1352],{"class":77,"line":375},[75,1350,1351],{"class":89},"     tpm2-tools",[75,1353,536],{"class":85},[75,1355,1356],{"class":77,"line":385},[75,1357,1358],{"class":89},"     gawk\n",[57,1360,1362],{"id":1361},"install-kernel-packages","Install Kernel Packages",[10,1364,1365],{},"Unfortunately the ubuntu linux images in 24.04 have grub as a \"recommends\" which causes it to be installed.\nTo avoid this, we separate our desktop install from our kernel install and install the latter with\nno-recommends.",[65,1367,1369],{"className":67,"code":1368,"language":69,"meta":70,"style":70},"# Leaving this in for people who pause\nexport DEBIAN_FRONTEND=noninteractive \n\n# We have to use no-install-recommends to avoid grub\napt install --no-install-recommends -yq \\\n  linux-generic-hwe-24.04\n",[72,1370,1371,1376,1386,1390,1395,1408],{"__ignoreMap":70},[75,1372,1373],{"class":77,"line":78},[75,1374,1375],{"class":314},"# Leaving this in for people who pause\n",[75,1377,1378,1380,1382,1384],{"class":77,"line":96},[75,1379,1253],{"class":602},[75,1381,1256],{"class":637},[75,1383,641],{"class":602},[75,1385,1261],{"class":637},[75,1387,1388],{"class":77,"line":105},[75,1389,309],{"emptyLinePlaceholder":308},[75,1391,1392],{"class":77,"line":120},[75,1393,1394],{"class":314},"# We have to use no-install-recommends to avoid grub\n",[75,1396,1397,1399,1401,1404,1406],{"class":77,"line":135},[75,1398,510],{"class":81},[75,1400,513],{"class":89},[75,1402,1403],{"class":85}," --no-install-recommends",[75,1405,1283],{"class":85},[75,1407,536],{"class":85},[75,1409,1410],{"class":77,"line":149},[75,1411,1412],{"class":89},"  linux-generic-hwe-24.04\n",[57,1414,1416],{"id":1415},"install-systemd-boot-into-esp","Install systemd-boot into ESP",[10,1418,1419],{},"Next we install the bootloader with bootctl. This allows our \"Linux System Loader\" to appear in our UEFI menu.",[65,1421,1423],{"className":67,"code":1422,"language":69,"meta":70,"style":70},"bootctl install && bootctl list\n\n",[72,1424,1425],{"__ignoreMap":70},[75,1426,1427,1430,1432,1435,1437],{"class":77,"line":78},[75,1428,1429],{"class":81},"bootctl",[75,1431,513],{"class":89},[75,1433,1434],{"class":637}," && ",[75,1436,1429],{"class":81},[75,1438,1439],{"class":89}," list\n",[42,1441],{},[45,1443,1445],{"id":1444},"add-users","Add Users",[10,1447,1448],{},"Now if you know your users, it's time to set them up.",[57,1450,1452],{"id":1451},"setup-users","Setup Users",[65,1454,1456],{"className":67,"code":1455,"language":69,"meta":70,"style":70},"chown -R 2202:2202 \u002Fhome\u002Fcprevoe\naddgroup --gid 2202 cprevoe\nadduser --uid 2202 --gid 2202 --gecos \"Christopher Prevoe,,,,prevoe.com\" cprevoe\nadduser cprevoe sudo\n",[72,1457,1458,1472,1486,1508],{"__ignoreMap":70},[75,1459,1460,1463,1466,1469],{"class":77,"line":78},[75,1461,1462],{"class":81},"chown",[75,1464,1465],{"class":85}," -R",[75,1467,1468],{"class":89}," 2202:2202",[75,1470,1471],{"class":89}," \u002Fhome\u002Fcprevoe\n",[75,1473,1474,1477,1480,1483],{"class":77,"line":96},[75,1475,1476],{"class":81},"addgroup",[75,1478,1479],{"class":85}," --gid",[75,1481,1482],{"class":85}," 2202",[75,1484,1485],{"class":89}," cprevoe\n",[75,1487,1488,1491,1494,1496,1498,1500,1503,1506],{"class":77,"line":105},[75,1489,1490],{"class":81},"adduser",[75,1492,1493],{"class":85}," --uid",[75,1495,1482],{"class":85},[75,1497,1479],{"class":85},[75,1499,1482],{"class":85},[75,1501,1502],{"class":85}," --gecos",[75,1504,1505],{"class":89}," \"Christopher Prevoe,,,,prevoe.com\"",[75,1507,1485],{"class":89},[75,1509,1510,1512,1515],{"class":77,"line":120},[75,1511,1490],{"class":81},[75,1513,1514],{"class":89}," cprevoe",[75,1516,1517],{"class":89}," sudo\n",[42,1519],{},[45,1521,1523],{"id":1522},"reboot-and-test","Reboot And Test",[10,1525,1526],{},"And now we finish it off with a reboot. Exit out of the chroot, then restart the machine.\nNote, if you're following along using virsh, you might need to execute a virsh start\ndirectly.",[57,1528,1530],{"id":1529},"reboot","Reboot!",[65,1532,1534],{"className":67,"code":1533,"language":69,"meta":70,"style":70},"reboot\n",[72,1535,1536],{"__ignoreMap":70},[75,1537,1538],{"class":77,"line":78},[75,1539,1533],{"class":81},[42,1541],{},[45,1543,1545],{"id":1544},"final-thoughts","Final Thoughts",[10,1547,1548],{},"And there we have it. Ubuntu 24.04 installed with BTRFS subvolumes used for critical\ncomponents. You can now instantly snapshot the entire OS and even swap out the OS for other\nversions by mounting the btrfs-root and playing around in there.",[10,1550,1551],{},"And all this, just because someone once asked how I setup Ubuntu leveraging BTRFS subvolumes. And there we have it.",[10,1553,1554],{},"Hope this helps",[1556,1557,1558],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":70,"searchDepth":96,"depth":96,"links":1560},[1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580],{"id":59,"depth":96,"text":60},{"id":161,"depth":96,"text":162},{"id":187,"depth":96,"text":188},{"id":229,"depth":96,"text":230},{"id":269,"depth":96,"text":270},{"id":397,"depth":96,"text":398},{"id":499,"depth":96,"text":500},{"id":553,"depth":96,"text":554},{"id":571,"depth":96,"text":572},{"id":680,"depth":96,"text":681},{"id":735,"depth":96,"text":736},{"id":998,"depth":96,"text":999},{"id":1039,"depth":96,"text":1040},{"id":1108,"depth":96,"text":1109},{"id":1223,"depth":96,"text":1224},{"id":1239,"depth":96,"text":1240},{"id":1361,"depth":96,"text":1362},{"id":1415,"depth":96,"text":1416},{"id":1451,"depth":96,"text":1452},{"id":1529,"depth":96,"text":1530},"2026-03-18 20:00:00","md",{"author":1584},"Christopher Prevoe","ubuntu-the-hard-way",{"title":5,"description":12},[1585,1588],"2026-03-19-ubuntu-the-hard-way","journal\u002F2026-03-19-ubuntu-the-hard-way",[1591,1592,331,1593,1594,1595,1596,1597,1598,1599,1600,1601],"linux","ubuntu","luks2","full-disk-encryption","tpm2","secure-boot","systemd-boot","dracut","uki","uefi","manual-installation","L3Sw2JcenvJxHKgxfncJHy9gYkIEJ5oTYtYDrkTGuq8",1778891847452]