How to use rc.local-early in Qubes 4.2

Original forum link
https://forum.qubes-os.org/t/33989
Original poster
likeafox
Created at
2025-05-19 21:09:37
Last wiki edit
2025-05-20 19:27:48
Revisions
2 revisions
Posts count
5
Likes count
5
Tags
configuration, version-r42

/rw/config/rc.local-early is like /rw/config/rc.local with two important differences: - It runs much earlier in the qube startup process - It blocks until complete. This means that until the rc.local-early script exits, the qube is not considered to have started up, and subsequent systemd units and user gui apps will not run.

Even though it is described in QubesOS's live documentation, rc.local-early is not available in QubesOS's current release at time of writing (that being version 4.2-- and it remains to be seen if it will be backported to 4.2 at some point).

That said, you can plug in the functionality for rc.local-early yourself, and you don't even need to modify any templates; it can be done within /rw of your app qube, by creating two additional files:

  1. mkdir -p /rw/bind-dirs/usr/lib/qubes/init
  2. Create file /rw/bind-dirs/usr/lib/qubes/init/qubes-early-vm-config.sh with contents:
    #!/usr/bin/bash
    
    EARLY_SH=/usr/lib/qubes/init/qubes-early-vm-config.sh
    # undo bind mount
    umount -l "$EARLY_SH"
    
    # run rc.local-early scripts, but only if the original qubes-early-vm.config.sh
    # script doesn't provide this functionality
    grep -q -e "rc.local-early" "$EARLY_SH" || {
      for rc in /rw/config/rc.local-early.d/*.rc /rw/config/rc.local-early; do
        [ -f "$rc" ] || continue
        [ -x "$rc" ] || continue
        "$rc"
      done
      unset rc
    }
    
    # this clause not strictly necessary but can avoid some foot-shooting
    # with certain misconfigurations
    [ `findmnt -n -o MAJ:MIN -T "$EARLY_SH"` = `findmnt -n -o MAJ:MIN -T /` ] || {
      echo "file resides on unexpected block device: $EARLY_SH" >&2
      exit 1
    }
    
    # run original script (that the current one replaced)
    "$EARLY_SH"
    
  3. chmod +x /rw/bind-dirs/usr/lib/qubes/init/qubes-early-vm-config.sh
  4. mkdir -p /rw/config/qubes-bind-dirs.d
  5. Create file /rw/config/qubes-bind-dirs.d/rc-local-early.conf with contents:
    binds+=( '/usr/lib/qubes/init/qubes-early-vm-config.sh' )
    

That's it! You can now include your rc.local-early script.