You are not logged in.

#1 2023-10-18 19:36:16

bedtime
Member
Registered: 2019-02-12
Posts: 70

mkinitcpio: boot into tmpfs, overlay, squashfs, or a snapshot in btrfs

I've been messing around with some mkinitcpio hooks and managed to get several different things working:

Works for me on btrfs with the root subvolume as /@:

- run system in tmpfs (and after manually umounting /boot or /efi, you could remove the disk/USB)
- boot into snapshot
- boot into snapshot + overlay (to allow non-persistent changes to the system)
- boot from squashfs* image with overlay
- create squashfs image
- boot into overlay

Hibernation works for all of the above if you have a separate swap partition and it's set up properly. Just hibernate and boot back in using regular options. This also works with my USB installed arch, too.

* squashfs running using lz4hc compression (make sure lz4 is installed!)


WARNING: do NOT run this if you don't know what mkinitcpio is! Do NOT run on a production system!


/etc/mkinitcpio.conf:

...
HOOKS=(base udev keyboard kms autodetect modconf sd-vconsole block filesystems liveroot resume)
...

What my /etc/fstab looks like:

#/dev/sda3 LABEL=ROOT
UUID=1bbccece-789a-4a05-b114-abff3ba8b7c0       /               btrfs           rw,noatime,compress-force=zstd:1,ssd,discard=async,space_cache=v2,subvol=/@       0 0

#/dev/sda2 LABEL=SWAP
UUID=e5451d4d-f7d7-44f2-a0b1-ffdcd139d4a0 none swap defaults 0 0

# /dev/sda1 LABEL=EFI
UUID=7C78-8FB5          /efi            vfat            ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro     0 2

/usr/lib/initcpio/hooks/liveroot:

#!/usr/bin/bash

create_archive() {
            
   echo -e "Creating archive file...\n"

   cd $real_root/@/

   mksquashfs . $real_root/@/root.squashfs -noappend -no-recovery -mem-percent 50 -e root.squashfs -e boot/* -e efi/* -e dev/* -e proc/* -e sys/* -e tmp/* -e run/* -e mnt/ -e .snapshots/ -e var/tmp/* -e var/cache/* -e var/log/* -e etc/pacman.d/gnupg/* -e var/lib/systemd/random-seed

   ls -la $real_root/@/root.squashfs

}

create_overlay() {

   local lower_dir=$(mktemp -d -p /)
   local ram_dir=$(mktemp -d -p /)
   mount --move ${new_root} ${lower_dir}
   mount -t tmpfs cowspace ${ram_dir}
   mkdir -p ${ram_dir}/upper ${ram_dir}/work
   mount -t overlay -o lowerdir=${lower_dir},upperdir=${ram_dir}/upper,workdir=${ram_dir}/work rootfs ${new_root}

}

run_latehook() {

   echo -e "\nPress any key for extra boot options.\n"

   if read -t 4 -s -n 1; then

      echo -e "\nPlease choose an option:\n\n\
<s> run snapshot\n\
<w> run snapshot + overlay\n\
<o> run in overlay mode\n\
<e> run squashfs + overlay\n\
<n> create & run squashfs + overlay\n\
<c> copy / to tmpfs\n\
<d> emergency shell\n\n\
<enter> continue boot\n"

      read -n 1 -s key

      new_root=/new_root
      mkdir -p $new_root

      if [[ "$key" = "s" ]] || [[ "$key" = "w" ]]; then

         mount --mkdir -o subvolid=256 ${root} $new_root
      
         btrfs subvolume list -ts $new_root | less
         read -n 3 -p "Choose a snapshot (256 is current system): " subvol 

         echo -e "\nPlease enter extra mount options (ex., ro ):"
         read options 
         [ ! "$options" = "" ] && options=","$options

         echo -e "\nWill proceed with the following mount:\n\nmount -o subvolid=$subvol$options ${root} /\n"
         sleep 4

         umount $new_root
         mount --mkdir -o subvolid=$subvol$options ${root} $new_root

         if [ "$?" -ne 0 ]; then
            echo "Could not mount subvol ($subvol). Chosing default (256)."
            sleep 2
            mount --mkdir -o subvolid=256 ${root} $new_root 
         fi

         [[ "$key" = "w" ]] && create_overlay

      elif [[ "$key" = "o" ]]; then

         create_overlay

      elif [[ "$key" = "e" ]] || [[ "$key" = "n" ]] || [[ "$key" = "c" ]]; then

         real_root=/real_root
         mkdir $real_root
         mount ${root} $real_root

         if [[ "$key" = "e" ]] || [[ "$key" = "n" ]]; then

            [[ ! -f "$real_root/@/root.squashfs" ]] || [[ "$key" = "n" ]] && create_archive

            echo "Extracting archive to RAM..."

            #unsquashfs -d @new_root -f $real_root/@/root.squashfs
            
            mount "$real_root/@/root.squashfs" $new_root -t squashfs -o loop

            create_overlay

            umount -l $real_root

         elif [[ "$key" = "c" ]]; then

            mount -t tmpfs -o size=80% none $new_root

            echo "Copying root filesystem to RAM. Please be patient..."

            rsync -a --exclude=root.squashfs --exclude=/dev/ --exclude=/proc/ --exclude=/sys/ --exclude=/tmp/ --exclude=/run/ --exclude=/mnt/ --exclude=/.snapshots/* --exclude=/var/tmp/ --exclude=/var/cache/ --exclude=/var/log/ --exclude=/mnt/ $real_root/@/ $new_root

         fi

      elif [[ "$key" = "d" ]]; then

         echo "Entering emergency shell."

         bash

      else

         echo "Continuing boot..."

      fi

   fi

}

/usr/lib/initcpio/install/liveroot :

#!/bin/sh

build() {
  add_binary rsync
  add_binary bash
  add_binary btrfs
  add_binary unsquashfs 
  add_binary mksquashfs
  add_binary unionfs
  add_module overlay
  add_module loop
  add_module squashfs
  add_module lz4hc
  add_runscript
}

help() {
  cat << HELPEOF
Run Arch in tmpfs, overlay, squashfs, or snapshot.
HELPEOF
}

update:

mkinitcpio -P

Note: the code has nigh zero error capture, so you MUST read and understand it before running. The script is not meant to handle any deviations other than my setup posted above. It's just a barebones thing.

I made this script because I wasn't able to find much out there that was able to run btrfs in tmpfs, overlay, and squashfs, and I thought I'd share. These hooks should work in grub and rEFInd. It might not work if you have other special hooks enabled, such as booster. The ability to run snapshots is a bonus.

I'm looking for input and critiques.

Offline

Board footer

Powered by FluxBB