Last active
July 8, 2026 14:50
-
-
Save fathonix/bfdaf496f643b33b022cfee392ccbba6 to your computer and use it in GitHub Desktop.
persistent-overlayroot - overlayfs as rootfs with persistent backing storage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # persistent-overlayroot - overlayfs as rootfs with persistent backing storage. | |
| # Licensed under MIT. (c) 2026 Aldo Adirajasa Fathoni | |
| # Install to /etc/initramfs-tools/hooks/fuse-overlayfs then chmod 755 | |
| # Make sure the fuse package has been installed | |
| set -e | |
| case "$1" in | |
| prereqs) echo "fuse"; exit 0;; | |
| esac | |
| . /usr/share/initramfs-tools/hook-functions | |
| copy_exec /usr/bin/fuse-overlayfs /usr/bin | |
| exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # persistent-overlayroot - overlayfs as rootfs with persistent backing storage. | |
| # Licensed under MIT. (c) 2026 Aldo Adirajasa Fathoni | |
| # Install this to /etc/initramfs-tools/scripts/init-bottom/, remember to chmod 755 | |
| # TODO: | |
| # - Multi-level upper dirs | |
| # - Port to other initramfs generators | |
| case $1 in | |
| prereqs) echo ""; exit 0;; | |
| esac | |
| . /scripts/functions | |
| ovlrootmnt="$rootmnt" | |
| ovlbasedir=/overlay | |
| ovllowerdir="${ovlbasedir}/lower" | |
| ovlupperdir="${ovlbasedir}/upper" | |
| ovlworkdir="${ovlbasedir}/work" | |
| ovldebug=0 | |
| ovlfuse=0 | |
| ovlskip=0 | |
| ovldesc="" | |
| log() { "log_${1}_msg" "persistent-overlayroot: $2"; } | |
| log_begin() { log begin "$*"; } | |
| log_end() { log end "$*"; } | |
| log_success() { log success "$*"; } | |
| log_warn() { log warning "$*"; } | |
| log_fail() { log failure "$*"; } | |
| fail() { log_fail "$*"; panic "persistent-overlayroot failed! Dropping to a shell..."; } | |
| exit_early() { log_end "$*"; exit 0; } | |
| add_desc() { [ -z "$ovldesc" ] && ovldesc="$*" || ovldesc=", ${*}"; } | |
| read_kernel_cmdline() { | |
| local cmdline="" ovlarg="" | |
| read cmdline < /proc/cmdline || | |
| fail "Failed to read kernel cmdline" | |
| for ovlarg in $cmdline; do | |
| case $ovlarg in | |
| overlayroot=*) | |
| ovldev="${ovlarg#overlayroot=}" | |
| ;; | |
| overlayrootflags=*) | |
| ovldevopts="${ovlarg#overlayrootflags=}" | |
| ;; | |
| overlayrootfstype=*) | |
| ovldevtype="${ovlarg#overlayrootfstype=}" | |
| ;; | |
| debugoverlayroot) | |
| ovldebug=1 | |
| ;; | |
| fuseoverlayroot) | |
| ovlfuse=1 | |
| ;; | |
| skipoverlayroot) | |
| ovlskip=1 | |
| ;; | |
| esac | |
| done | |
| [ -z "$ovldev" ] && exit_early "overlayroot= not set. Skipping..." | |
| [ $ovlskip -eq 1 ] && exit_early "skipoverlayroot was set. Skipping..." | |
| } | |
| mount_overlay() { | |
| local ovldir="" ovlfscmd="mount -t overlay overlay" | |
| [ ! -z "$ovldevtype" ] && ovldevtype="-t ${ovldevtype}" | |
| [ ! -z "$ovldevopts" ] && ovldevopts="-o ${ovldevopts}" | |
| mkdir -p "$ovlbasedir" | |
| mount $ovldevtype "$ovldev" "$ovlbasedir" $ovldevopts || | |
| fail "Error mounting overlayroot" | |
| for ovldir in "$ovllowerdir" "$ovlupperdir" "$ovlworkdir"; do | |
| mkdir -p "$ovldir" || | |
| fail "Error creating directory ${ovldir}" | |
| done | |
| if [ $ovlfuse -eq 1 ]; then | |
| log_begin "fuseoverlayroot was set, using fuse-overlayfs instead of kernel overlay" | |
| # Prevent systemd from killing fuse-overlayfs https://systemd.io/ROOT_STORAGE_DAEMONS/ | |
| ovlfscmd="start-stop-daemon -S -a @fuse-overlayfs -x fuse-overlayfs --" | |
| add_desc "fuse-overlayfs" | |
| fi | |
| mount --move "$ovlrootmnt" "$ovllowerdir" || | |
| fail "Error moving root mount to ${ovllowerdir}" | |
| $ovlfscmd "$ovlrootmnt" \ | |
| -o "lowerdir=${ovllowerdir},upperdir=${ovlupperdir},workdir=${ovlworkdir}" || | |
| fail "Error mounting overlayfs" | |
| mkdir -p "${ovlrootmnt}${ovlbasedir}" | |
| mount --move "$ovlbasedir" "${ovlrootmnt}${ovlbasedir}" || | |
| fail "Error moving overlayroot base mount into overlayroot mount" | |
| } | |
| post_mount_overlay() { | |
| [ $ovldebug -eq 1 ] && fail "Debugging was enabled, initiating crash..." | |
| [ ! -z "$ovldesc" ] && ovldesc=" with ${ovldesc}" | |
| } | |
| log_begin "Setting up overlayfs as rootfs" | |
| read_kernel_cmdline | |
| mount_overlay | |
| post_mount_overlay | |
| log_success "Configured overlayfs as rootfs with ${ovldev} on top of ${ROOT}${ovldesc}" | |
| exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment