diff --git a/90overlay/module-setup.sh b/90overlay/module-setup.sh new file mode 100755 index 0000000..2807b13 --- /dev/null +++ b/90overlay/module-setup.sh @@ -0,0 +1,19 @@ +#!/bin/bash +check() { + return 0 +} + +depends() { + echo "systemd-initrd" + return 0 +} + +install() { + inst_hook cmdline 20 "$moddir/parse-overlay.sh" + inst_hook cleanup 10 "$moddir/overlay-needshutdown.sh" + inst_script "$moddir/overlay-generator.sh" $systemdutildir/system-generators/dracut-overlay-generator +} + +installkernel() { + hostonly='' instmods overlay +} diff --git a/90overlay/overlay-generator.sh b/90overlay/overlay-generator.sh new file mode 100755 index 0000000..5d6454d --- /dev/null +++ b/90overlay/overlay-generator.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +GENERATOR_DIR="$2" +[ -z "$GENERATOR_DIR" ] && exit 1 +[ -z "$root" ] && root=$(getarg root=) +[ -z "$overlay" ] && overlay=$(getarg overlay=) +[ -z "$overlay" ] && return 0 + +derefed="" +function deref_dev() { +case "${1}" in + block:LABEL=*|LABEL=*) + derefed="${1#block:}" + derefed="$(echo $derefed | sed 's,/,\\x2f,g')" + derefed="/dev/disk/by-label/${derefed#LABEL=}" + ;; + block:UUID=*|UUID=*) + derefed="${1#block:}" + derefed="/dev/disk/by-uuid/${derefed#UUID=}" + ;; + block:PARTUUID=*|PARTUUID=*) + derefed="${1#block:}" + derefed="/dev/disk/by-partuuid/${derefed#PARTUUID=}" + ;; + block:PARTLABEL=*|PARTLABEL=*) + derefed="${1#block:}" + derefed="/dev/disk/by-partlabel/${derefed#PARTLABEL=}" + ;; + /dev/*) + derefed="block:${1}" + ;; +esac +} + +deref_dev "${overlay}" +overlay_data="${derefed}" +deref_dev "${root}" +overlay_root="${derefed}" +fsck_data="systemd-fsck@$(systemd-escape -p "${overlay_data}").service" +fsck_root="systemd-fsck@$(systemd-escape -p "${overlay_root}").service" + +{ + echo "# generated by dracut" + echo "[Unit]" + echo "Before=initrd-root-fs.target" + echo "RequiresMountsFor=/run" + echo "BindsTo=${fsck_data}" + echo "[Mount]" + echo "Where=/run/overlay" + echo "What=${overlay_data}" + echo "Options=defaults" +} > "$GENERATOR_DIR"/run-overlay.mount +{ + echo "# generated by dracut" + echo "[Unit]" + echo "Before=initrd-root-fs.target" + echo "RequiresMountsFor=/run/overlay" + echo "BindsTo=${fsck_root}" + echo "[Mount]" + echo "Where=/run/overlay/lower" + echo "What=${overlay_root}" + echo "Options=defaults,ro" +} > "$GENERATOR_DIR"/run-overlay-lower.mount +{ + echo "# generated by dracut" + echo "[Unit]" + echo "Before=initrd-root-fs.target" + echo "RequiresMountsFor=/run/overlay /run/overlay/lower" + echo "[Mount]" + echo "Where=/sysroot" + echo "What=overlay" + echo "Type=overlay" + echo "Options=lowerdir=/run/overlay/lower,upperdir=/run/overlay/upper,workdir=/run/overlay/work" +} > "$GENERATOR_DIR"/sysroot.mount diff --git a/90overlay/overlay-needshutdown.sh b/90overlay/overlay-needshutdown.sh new file mode 100755 index 0000000..937188f --- /dev/null +++ b/90overlay/overlay-needshutdown.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +if test "${root}" = "overlay"; then + need_shutdown + break +fi diff --git a/90overlay/parse-overlay.sh b/90overlay/parse-overlay.sh new file mode 100755 index 0000000..ac5f6f2 --- /dev/null +++ b/90overlay/parse-overlay.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +[ -z "$root" ] && root=$(getarg root=) +[ -z "$overlay" ] && overlay=$(getarg overlay=) +[ -z "$overlay" ] && return 0 + +rootok=1 +root="overlay" +export root rootok diff --git a/README.md b/README.md new file mode 100644 index 0000000..189674d --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +## dracut-overlayfs ## + +This is a custom dracut module designed to facilitate the use of a read-write overlayfs on top of a read-only root filesystem. + +It currently does the following: + +* Parse the kernel command line for the overlay= parameter, which should point to the writable layer of the overlayfs. +* Performs fsck via systemd units generated on the fly for both the root and the writable layer. If fsck cannot be performed, systemd will mention it but not stop the boot process. +* Setups the overlayfs using systemd generated mount units. + +## How to use ## + +Place the 90overlay module in /usr/lib/dracut/modules.d and generate your initramfs. It should get picked up automatically. +Then, add the overlay= setting to your kernel command line. It can be anything recognized by udev: + +* A partlabel in the form **overlay=PARTLABEL=...**. +* A partuuid in the form **overlay=PARTUUID=...**. +* An uuid in the form **overlay=UUID=...**. +* A label in the form **overlay=LABEL=...**. +* A device node in the form **overlay=/dev/sdX1** (not recommended). + +You might need to explicitly add additional drivers and fsck tools in your initramfs, as once you booted onto the overlayfs, when regenerating the initramfs, dracut will not notice which fs module you will require, nor which fsck tool.