diff --git a/90-overlayroot.hook b/90-overlayroot.hook new file mode 100644 index 0000000..9a1d29b --- /dev/null +++ b/90-overlayroot.hook @@ -0,0 +1,11 @@ +[Trigger] +Type = File +Operation = Install +Operation = Upgrade +Target = boot/kernel*.img +Target = usr/lib/initcpio/* + +[Action] +Description = Updating overlayroot initcpios... +When = PostTransaction +Exec = /usr/bin/mkinitcpio -p overlayroot diff --git a/PKGBUILD b/PKGBUILD index b866abb..84d4302 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ pkgname=overlayroot pkgver=0.2 -pkgrel=1 +pkgrel=2 pkgdesc="overlayFS root file system" arch=('any') url="https://github.com/nils-werner/arch-overlayroot" @@ -9,24 +9,36 @@ depends=( 'mkinitcpio' 'arch-install-scripts' ) -install=overlayroot.install source=( - 'overlayroot.install' 'initcpio-install-overlayroot' 'initcpio-hooks-overlayroot' 'rwrootfs' 'fsck.overlay' 'journald-volatile-storage.conf' 'overlayroot-motd.sh' + 'mkinitcpio-overlayroot.conf' + 'mkinitcpio-overlayroot.preset' + '90-overlayroot.hook' ) sha256sums=( - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' + # 'initcpio-install-overlayroot' + '3f197246d31439c84d7433609628126354c02bc496b72291cf884a21d1e1d492' + # 'initcpio-hooks-overlayroot' + '7e8e5a9e813e46aa679a276b7475c0601d4124f3c35d21797330769a9b21d21d' + # 'rwrootfs' + '75b8c2ebe9e08e58f207a82aa93cfdd0b46a2255e49493cf6fedfe97cc61bd98' + # 'fsck.overlay' + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' + # 'journald-volatile-storage.conf' + 'c0c9a711f7554fdd02650409b098fc0636b8f3f574f03d927c6df84f5ec82a7f' + # 'overlayroot-motd.sh' + 'e2e917ab85d44abfc8e4c504cd8925d6fec5d26c452198303e2238464552e9a1' + # 'mkinitcpio-overlayroot.conf' + '27c68a520ad657f6d404bc5c2df4b7f5fb77f048b21bbfc8989d3360a1306251' + # 'mkinitcpio-overlayroot.preset' + '9c0293c1edb3f9662b09a5618361457934a82f04ed8aef11786ed54abe33dab7' + # '90-overlayroot.hook' + '0a81b378572ea6e2de20d9b52f2a1f6271a98aae31fe01f6c4a386df9ddf56aa' ) build() { @@ -36,8 +48,11 @@ build() { package() { install -Dm644 "$srcdir/initcpio-install-overlayroot" "$pkgdir/usr/lib/initcpio/install/overlayroot" install -Dm644 "$srcdir/initcpio-hooks-overlayroot" "$pkgdir/usr/lib/initcpio/hooks/overlayroot" - install -Dm644 "$srcdir/journald-volatile-storage.conf" "$pkgdir/etc/systemd/journald.conf.d/volatile-storage.conf" +# install -Dm644 "$srcdir/journald-volatile-storage.conf" "$pkgdir/etc/systemd/journald.conf.d/volatile-storage.conf" install -Dm755 "$srcdir/rwrootfs" "$pkgdir/usr/bin/rwrootfs" install -Dm755 "$srcdir/fsck.overlay" "$pkgdir/usr/bin/fsck.overlay" + install -Dm644 "$srcdir/mkinitcpio-overlayroot.conf" "$pkgdir/etc/mkinitcpio-overlayroot.conf" + install -Dm644 "$srcdir/mkinitcpio-overlayroot.preset" "$pkgdir/etc/mkinitcpio.d/overlayroot.preset" install -Dm644 "$srcdir/overlayroot-motd.sh" "$pkgdir/etc/profile.d/overlayroot-motd.sh" + install -Dm644 "$srcdir/90-overlayroot.hook" "$pkgdir/usr/share/libalpm/hooks/90-overlayroot.hook" } diff --git a/README.md b/README.md index f1b0c1a..8ad3b02 100644 --- a/README.md +++ b/README.md @@ -32,34 +32,46 @@ Install this package makepkg -si ``` -Then try rebooting, it should boot as normal. +After installation, a new `initramfs-overlayroot.img` initramfs will be automatically created but not used. +Try rebooting, it should boot as normal. ### Enable overlayroot hook -Then add `overlayroot` to your `HOOKS` array in `/etc/mkinitcpio.conf` and rebuild the initramfs by running +To enable overlayroot hook, you need to change the `initramfs` command in `/boot/config.txt`: ``` -mkinitcpio -P +initramfs initramfs-overlayroot.img followkernel ``` -and reboot. It should boot as normal. +Try rebooting, it should boot as normal because there is no `overlayroot` on the commandline yet. -### Enable overlayroot in commandline +### Enable overlayroot backed on RAM (tmpfs) -With the initramfs in place, you can now enable overlayroot by adding `overlayroot` to the end of `/boot/cmdline.txt` +To boot with overlayroot over tmpfs, just add `overlayroot=tmpfs` to the end of `/boot/cmdline.txt`. ``` -root=/dev/mmcblk0p2 rw rootwait console=ttyAMA0,115200 console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop overlayroot +root=/dev/mmcblk0p2 rw rootwait console=ttyAMA0,115200 console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop overlayroot=tmpfs ``` and reboot. You should see a warning during login that any changes you make to your filesystem will be non-persistent after this point. +### Enable overlayroot backed on USB + +To boot with overlayroot backed on USB, just add `overlayroot=` to the end of `/boot/cmdline.txt`. You can specify the device to use by device name or tag, e.g. `/dev/sda2`, `LABEL=ROOT_USB`, `UUID=xxx`, refer to mount(8) manpage for details. + +``` +root=/dev/mmcblk0p2 rw rootwait console=ttyAMA0,115200 console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop overlayroot=LABEL=ROOT_USB +``` + +and reboot. You will not see a warning during login because any changes you make to your filesystem will be stored on the USB device. + + ### Set filesystems readonly You can now also set the entire root filesystem as readonly by changing `rw` to `ro` in `/boot/cmdline.txt` ``` -root=/dev/mmcblk0p2 ro rootwait console=ttyAMA0,115200 console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop overlayroot +root=/dev/mmcblk0p2 ro rootwait console=ttyAMA0,115200 console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop overlayroot=tmpfs ``` and adding `ro` to `/etc/fstab` @@ -74,10 +86,14 @@ and adding `ro` to `/etc/fstab` ## Editing the root filesystem -You can run `rwrootfs` to remount all file systems as read-write and change into an interactive shell in your SD card file system. After exiting that shell, the fileystems will remain read-write until next reboot. +You can run `rwrootfs` to remount all file systems as read-write and change into an interactive shell in your SD card file system. After exiting that shell, the filesystems will remain read-write until next reboot. Alternatively you can undo all changes from [Enable overlayroot in commandline](#enable-overlayroot-in-commandline) and [Set filesystems readonly](#set-filesystems-readonly) and reboot. This is the recommended way of system upgrades. +## Resyncing the SDCARD + +When using USB backend, you can resync automatically the SDCARD by creating a file named `/overlayroot.resync`. Upon reboot, files (virtually) removed from the SDCARD will be removed from the SDCARD for real and the content of the USB backend will be moved to the SDCARD. + ## Debugging Sometimes, overlayroot may cause trouble during boot time. To boot without it simply remove `overlayroot` from `/boot/cmdline.txt`. @@ -85,7 +101,7 @@ Sometimes, overlayroot may cause trouble during boot time. To boot without it si If you still have problems, you can also try removing the initramfs by removing ``` -initramfs initramfs-linux.img followkernel +initramfs initramfs-overlayroot.img followkernel ``` from `/boot/config.txt`. diff --git a/initcpio-hooks-overlayroot b/initcpio-hooks-overlayroot index ea41d86..671e653 100755 --- a/initcpio-hooks-overlayroot +++ b/initcpio-hooks-overlayroot @@ -2,9 +2,20 @@ run_hook() { if [ "${overlayroot}" ]; then - # Create overlay tree in RAM mkdir -p /overlay - mount -t tmpfs overlayroot /overlay + if [ "${overlayroot}" = "tmpfs" ]; then + mount -t tmpfs overlayroot /overlay + else + # Allow up to 5 seconds for device to be available + mounted=0 + for i in 1 2 3 4 5; do + mount ${overlayroot} /overlay + [ $? -eq 0 ] && mounted=1 && break + sleep 1 + done + # Otherwise mount tmpfs anyway + [ $mounted -eq 1 ] || mount -t tmpfs overlayroot /overlay + fi mkdir -p /overlay/upper mkdir -p /overlay/work mkdir -p /overlay/lower @@ -22,6 +33,45 @@ run_latehook() { rm /new_root mkdir -p /new_root + if [ -e "/overlay/upper/overlayroot.resync" ]; then + + echo "overlayroot: Resyncing lower and upper ..." + + awk '$2 == "/overlay/lower" && $4 ~ /ro,/ { exit 1 }' /proc/mounts + is_ro=$? + + if [ $is_ro -eq 1 ]; then + mount -o rw,remount /overlay/lower + fi + + # Delete all files which have been whited out from upper + echo "overlayroot: Deleting all files from lower that have been wiped from upper ..." + (cd /overlay/upper && find . -type c -print) | while read path; do + [ "$(stat -c '%t %T' /overlay/upper/$path)" = "0 0" ] || continue + rm -fr /overlay/lower/$path /overlay/upper/$path + done + + # Delete all files from lower that exist in upper + echo "overlayroot: Deleting all files from lower that exist in upper ..." + (cd /overlay/upper && find . ! -type d -print0) | (cd /overlay/lower && xargs -0 rm -fr) + + # Copy upper to lower + echo "overlayroot: Copying all files from upper to lower ..." + (cd /overlay/upper && tar cf - --exclude="*/log/*" .) | (cd /overlay/lower && tar xf -) + + # Delete overlayroot.resync from lower + rm /overlay/lower/overlayroot.resync + + # Delete all files from upper + echo "overlayroot: Deleting all files from upper ..." + rm -fr /overlay/upper/* /overlay/upper/.* + + # Remount 'ro' after we are finished + if [ $is_ro -eq 1 ]; then + mount -o ro,remount /overlay/lower + fi + fi + # Build overlay FS and mount it to /new_root mount -t overlay overlay -o lowerdir=/overlay/lower,upperdir=/overlay/upper,workdir=/overlay/work /new_root diff --git a/mkinitcpio-overlayroot.conf b/mkinitcpio-overlayroot.conf new file mode 100644 index 0000000..a8c0607 --- /dev/null +++ b/mkinitcpio-overlayroot.conf @@ -0,0 +1,5 @@ +. /etc/mkinitcpio.conf + +MODULES+=( overlay ) +BINARIES+=( find mount rm tar xargs e2fsck ) +HOOKS+=( overlayroot ) diff --git a/mkinitcpio-overlayroot.preset b/mkinitcpio-overlayroot.preset new file mode 100644 index 0000000..72ec18b --- /dev/null +++ b/mkinitcpio-overlayroot.preset @@ -0,0 +1,19 @@ +_overlayroot_found=0 +for file in /etc/mkinitcpio.d/*.preset; do + if grep -q "^ALL_" $file; then + . $file + _overlayroot_found=1 + break + fi +done + +if [ $_overlayroot_found -eq 0 ]; then + echo "Failed to find base preset!" >&2 + exit 1 +fi +unset _overlayroot_found + +PRESETS=('default') + +default_config="/etc/mkinitcpio-overlayroot.conf" +default_image="/boot/initramfs-overlayroot.img" diff --git a/overlayroot-motd.sh b/overlayroot-motd.sh index 7fc5bb0..08a4438 100644 --- a/overlayroot-motd.sh +++ b/overlayroot-motd.sh @@ -1,10 +1,10 @@ -if grep -qs 'overlayroot' /proc/cmdline; then +if [ "$(awk '$2 == "/overlay" { print $3 }' /proc/mounts)" = "tmpfs" ]; then cat << EOF -==> WARNING: Overlayroot in effect. -None of the changes you make will be preseved after reboot. +==> WARNING: overlayroot backed on tmpfs in effect. None of the changes you +make will be preserved after reboot. -To disable overlayroot remove the 'overlayroot' argument -from the kernel commandline. +To disable overlayroot remove the 'overlayroot' argument from the kernel +commandline. EOF fi diff --git a/overlayroot.install b/overlayroot.install deleted file mode 100644 index 6289316..0000000 --- a/overlayroot.install +++ /dev/null @@ -1,12 +0,0 @@ -post_install() { - echo " > Please add 'overlayroot' to your HOOKS array in /etc/mkinitcpio.conf and run mkinitcpio -P." -} - -post_remove() { - if grep -qs 'overlayroot' /proc/cmdline; then - echo " > Please remove 'overlayroot' from your kernel commandline." - fi - if grep -qs 'overlayroot' /etc/mkinitcpio.conf; then - echo " > Please remove 'overlayroot' from your HOOKS array in /etc/mkinitcpio.conf and run mkinitcpio -P." - fi -}