Skip to content

Instantly share code, notes, and snippets.

@pottedplant
Last active November 15, 2017 21:29
Show Gist options
  • Save pottedplant/2afff9442de1caeb0f2ae2aa495dd04a to your computer and use it in GitHub Desktop.
Save pottedplant/2afff9442de1caeb0f2ae2aa495dd04a to your computer and use it in GitHub Desktop.
#!/bin/bash
# static apk: tar xf apk-tools-static-*.apk # http://dl-cdn.alpinelinux.org/alpine/latest-stable/main/x86_64/
# setup alpine folder: apk.static -X http://dl-cdn.alpinelinux.org/alpine/latest-stable/main -U --allow-untrusted --root root --initdb add alpine-base util-linux btrfs-progs bash
# remove all tty\d+ consoles from /etc/inittab (inits will conflict otherwise)
# mk initramfs: (cd root && find . -print0 | cpio --null -ov --format=newc | xz --check=crc32 ) > ./initramfs
# append kernel modules: (cd / && find "./lib/modules/${KERNEL}" -print0 | cpio --null -ov --format=newc | xz --check=crc32 ) >> ./initramfs
function step() {
echo "step: $*"
}
function panic() {
echo "PANIC: $*"
sleep 5
echo b >/proc/sysrq-trigger
exit -1
}
# prepare /next
step "prepare next directory"
test -e /next || mkdir /next || panic "unable to create /next"
mount --bind /next /next || panic "unable to bind mount /next"
mount --make-shared /next || panic "unable to make mount /next shared"
# spawn alpine init
step "spawn alpine init in new namespace"
unshare --mount --propagation unchanged --uts --cgroup --ipc --pid --fork /sbin/init &
# wait for switch signal
while [ ! -e /next/do_switch ]; do
sleep 1
kill -0 %1 || panic "alpine init vanished"
done
echo "/next/do_switch found"
# kill everything
step "terminating all processes"
kill -s KILL -- -1
step "waiting for alpine to die"
wait
# custom init
step "custom init?"
test -e /next/init && exec /next/init
# temp proc, sys
step "temporarily mounting proc and sys"
mount -t proc proc /proc || panic "unable to mount /proc"
mount -t sysfs none /sys || panic "unable to mount /sys"
# flush net
step "flushing network devices"
for i in /sys/class/net/*; do
i=`basename $i`
ip address flush $i
ip route flush dev $i
done
# move root
step "moving /next/root to /newroot"
test ! -e /newroot && mkdir /newroot || panic "unable to create /newroot"
mount --rbind /next/root /newroot || panic "rbind mount failed"
mount --make-private /newroot || panic "unable to make newroot mount private"
umount -R /next/root || panic "unable to umount /next/root"
# cleanup
echo "cleanup: unmounting sys, proc"
umount -R /sys || panic "unable to umount /sys"
umount -R /proc || panic "unable to umount /proc"
# switch root
step "switching root"
exec busybox switch_root /newroot /sbin/init
panic "unable to call switch_root"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment