Compare commits

...

7 commits

Author SHA1 Message Date
e1c4f3cb4f
debian 2022-12-01 15:56:15 +08:00
5bd769aedb
archlinux 2022-11-26 21:05:55 +08:00
0f269deebb
fix iso path 2022-11-25 22:05:44 +08:00
3365186b6c
change mirror 2021-08-05 16:16:55 +08:00
ca277b8d88
arch ??
copying home to overlayfs might not be a good idea
2021-08-05 16:16:55 +08:00
James Swineson
73302490c5
fix typo 2021-03-09 11:17:29 +08:00
James Swineson
f9e76c5981
remove typo 2021-03-09 11:16:36 +08:00

View file

@ -3,68 +3,25 @@ set -Eeuo pipefail
# disable command path hashing as we are going to move fast and break things # disable command path hashing as we are going to move fast and break things
set +h set +h
# config
WORKDIR="/tmp/menhera" WORKDIR="/tmp/menhera"
ROOTFS="" MIRROR="https://iso.meson.cc/ultralite/archlinux"
ROOTFS="${MIRROR}/iso/latest/arch/x86_64/airootfs.sfs"
declare -A ARCH_MAP=(
["x86_64"]="amd64"
)
# internal global variables # internal global variables
OLDROOT="/" OLDROOT="/"
NEWROOT="" NEWROOT=""
MACHINE_TYPE=$(uname -m) [[ "$(uname -m)" == "x86_64" ]] || { echo "error: wrong arch $(uname -m) (not x86_64)"; exit 1; }
ARCH_ID=${ARCH_MAP[$MACHINE_TYPE]:-$MACHINE_TYPE}
# fix possible PATH pMYMAP[missing]+_roblems PUBKEY="./key.pub"
export PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" [ -f "$PUBKEY" ] || { echo "error: you should put your ssh public key at ${PUBKEY} in order to ssh with root account and this key later"; exit 1; }
menhera::reset_sshd_config() { if [[ $EUID -ne 0 ]]; then
cat > /etc/ssh/sshd_config <<EOF echo "This script must be run as root"
PermitRootLogin yes exit 1
AcceptEnv LANG LC_* fi
EOF
}
# environment compatibility systemctl status > /dev/null || { echo "error: no systemd"; exit 1; }
menhera::__compat_restart_ssh() {
if [ -x "$(command -v systemctl)" ]; then
systemctl daemon-reload
if ! systemctl restart ssh; then
echo "SSH daemon start failed, try resetting config..."
menhera::reset_sshd_config
if ! systemctl restart ssh; then
echo "SSH daemon fail to start, dropping you to a shell..."
sh
fi
fi
elif [ -x "$(command -v service)" ]; then
if ! service ssh restart; then
echo "SSH daemon start failed, try resetting config..."
menhera::reset_sshd_config
if ! service ssh restart; then
echo "SSH daemon fail to start, dropping you to a shell..."
sh
fi
fi
else
echo "ERROR: Cannot restart SSH server, init system not recoginzed" >&2
exit 1
fi
}
menhera::__compat_reload_init() {
if [ -x "$(command -v systemctl)" ]; then
systemctl daemon-reexec
elif [ -x "$(command -v telinit)" ]; then
telinit u
else
echo "ERROR: Cannot re-exec init, init system not recoginzed" >&2
exit 1
fi
}
# helper functions # helper functions
# https://stackoverflow.com/a/3232082/2646069 # https://stackoverflow.com/a/3232082/2646069
@ -81,159 +38,6 @@ menhera::confirm() {
esac esac
} }
# jobs
menhera::get_rootfs() {
if [ -n ${ROOTFS} ]; then
echo "Getting rootfs URL..."
# forgive me for parsing HTML with these shit
# and hope it works
ROOTFS_TIME=$(wget -qO- --show-progress "https://images.linuxcontainers.org/images/debian/buster/${ARCH_ID}/default/?C=M;O=D" | grep -oP '(\d{8}_\d{2}:\d{2})' | head -n 1)
ROOTFS="https://images.linuxcontainers.org/images/debian/buster/${ARCH_ID}/default/${ROOTFS_TIME}/rootfs.squashfs"
else
echo "\$ROOTFS is set to '$ROOTFS'"
fi
}
menhera::sync_filesystem() {
echo "Syncing..."
sync
sync
}
menhera::prepare_environment() {
echo "Loading kernel modules..."
modprobe overlay
modprobe squashfs
sysctl kernel.panic=10
echo "Creating workspace in '${WORKDIR}'..."
# workspace
mkdir -p "${WORKDIR}"
mount -t tmpfs -o size=100% tmpfs "${WORKDIR}"
# new rootfs
mkdir -p "${WORKDIR}/newroot"
# readonly part of new rootfs
mkdir -p "${WORKDIR}/newrootro"
# writeable part of new rootfs
mkdir -p "${WORKDIR}/newrootrw"
# overlayfs workdir
mkdir -p "${WORKDIR}/overlayfs_workdir"
echo "Downloading temporary rootfs..."
wget -q --show-progress -O "${WORKDIR}/rootfs.squashfs" "${ROOTFS}"
}
menhera::mount_new_rootfs() {
echo "Mounting temporary rootfs..."
mount -t squashfs "${WORKDIR}/rootfs.squashfs" "${WORKDIR}/newrootro"
mount -t overlay overlay -o rw,lowerdir="${WORKDIR}/newrootro",upperdir="${WORKDIR}/newrootrw",workdir="${WORKDIR}/overlayfs_workdir" "${WORKDIR}/newroot"
NEWROOT="${WORKDIR}/newroot"
}
menhera::install_software() {
echo "Installing OpenSSH Server into new rootfs..."
# disable APT cache
echo -e 'Dir::Cache "";\nDir::Cache::archives "";' > "${NEWROOT}/etc/apt/apt.conf.d/00_disable-cache-directories"
DEBIAN_FRONTEND=noninteractive chroot "${NEWROOT}" apt-get update -y
DEBIAN_FRONTEND=noninteractive chroot "${NEWROOT}" apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install -y openssh-server
}
menhera::copy_config() {
echo "Copying important config into new rootfs..."
! cp -axL "${OLDROOT}/etc/resolv.conf" "${NEWROOT}/etc"
! cp -axr "${OLDROOT}/etc/ssh" "${NEWROOT}/etc"
! cp -ax "${OLDROOT}/etc/"{passwd,shadow} "${NEWROOT}/etc"
! cp -axr "${OLDROOT}/root/.ssh" "${NEWROOT}/root"
chroot "${NEWROOT}" chsh -s /bin/bash root
cat > "${NEWROOT}/etc/motd" <<EOF
Download menhera.sh at https://github.com/Jamesits/menhera.sh
!!!NOTICE!!!
This is a minimal RAM system created by menhera.sh. Feel free to format your disk, but don't blame anyone
except yourself if you lost important files or your system is broken.
If you think you've done something wrong, reboot immediately -- there is still hope.
Your original rootfs is at /mnt/oldroot. Be careful dealing with it.
Have a lot of fun...
EOF
}
menhera::swap_root() {
echo "Swapping rootfs..."
# prepare future mount point for our old rootfs
mkdir -p "${WORKDIR}/newroot/mnt/oldroot"
mount --make-rprivate /
# swap root
pivot_root "${WORKDIR}/newroot" "${WORKDIR}/newroot/mnt/oldroot"
OLDROOT="/mnt/oldroot"
NEWROOT="/"
# move mounts
for i in dev proc sys run; do
if [ -d "${OLDROOT}/$i" ]; then
mount --move "${OLDROOT}/$i" "${NEWROOT}/$i"
fi
done
mount -t tmpfs -o size=100% tmpfs "${NEWROOT}/tmp"
mkdir -p "${WORKDIR}"
mount --move "${OLDROOT}/${WORKDIR}" "${WORKDIR}"
echo "Restarting SSH daemon..."
menhera::__compat_restart_ssh
}
menhera::clear_processes() {
echo "Disabling swap..."
swapoff -a
echo "Restarting init process..."
menhera::__compat_reload_init
# hope 15s is enough
sleep 15
echo "Killing all programs still using the old root..."
fuser -kvm "${OLDROOT}" -15
# in most cases the parent process of this script will be killed, so goodbye
}
# main procedure
LIBRARY_ONLY=0
while test $# -gt 0
do
case "$1" in
--lib) LIBRARY_ONLY=1
;;
esac
shift
done
if [[ $LIBRARY_ONLY -eq 1 ]]; then
# acting as a library only
return 0
fi
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
echo -e "We will start a temporary RAM system as your recovery environment." echo -e "We will start a temporary RAM system as your recovery environment."
echo -e "Note that this script will kill programs and umount filesystems without prompting." echo -e "Note that this script will kill programs and umount filesystems without prompting."
echo -e "Please confirm:" echo -e "Please confirm:"
@ -241,23 +45,82 @@ echo -e "\tYou have closed all programs you can, and backed up all important dat
echo -e "\tYou can SSH into your system as root user" echo -e "\tYou can SSH into your system as root user"
menhera::confirm || exit -1 menhera::confirm || exit -1
menhera::get_rootfs # fix possible PATH problems
menhera::sync_filesystem export PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
menhera::prepare_environment echo "Loading kernel modules..."
menhera::mount_new_rootfs modprobe overlay
menhera::copy_config modprobe squashfs
menhera::install_software sysctl kernel.panic=10
menhera::swap_root
echo "Creating workspace in '${WORKDIR}'..."
# workspace
mkdir -p "${WORKDIR}"
mount -t tmpfs -o size=100% tmpfs "${WORKDIR}"
mkdir -p "${WORKDIR}/newroot" # where iso is stored
mkdir -p "${WORKDIR}/newrootro" # lower
mkdir -p "${WORKDIR}/newrootrw" # upper
mkdir -p "${WORKDIR}/overlayfs_workdir" # work
echo "Downloading temporary rootfs..."
wget -O "${WORKDIR}/rootfs.squashfs" "${ROOTFS}"
echo "Mounting temporary rootfs..."
mount -t squashfs "${WORKDIR}/rootfs.squashfs" "${WORKDIR}/newrootro"
mount -t overlay overlay -o rw,lowerdir="${WORKDIR}/newrootro",upperdir="${WORKDIR}/newrootrw",workdir="${WORKDIR}/overlayfs_workdir" "${WORKDIR}/newroot"
NEWROOT="${WORKDIR}/newroot"
rm -f "${NEWROOT}/etc/resolv.conf"
cat "${OLDROOT}/etc/resolv.conf" > "${NEWROOT}/etc/resolv.conf"
install -DTm0600 <(cat "$PUBKEY") "${NEWROOT}/root/.ssh/authorized_keys"
chmod 0700 "${NEWROOT}/root/.ssh"
sync && sync # why sync twice? idk
echo "Swapping rootfs..."
# prepare future mount point for our old rootfs
mkdir -p "${WORKDIR}/newroot/mnt/oldroot"
mount --make-rprivate /
# swap root
pivot_root "${WORKDIR}/newroot" "${WORKDIR}/newroot/mnt/oldroot"
OLDROOT="/mnt/oldroot"
NEWROOT="/"
# move mounts
for i in dev proc sys run; do
if [ -d "${OLDROOT}/$i" ]; then
mount --move "${OLDROOT}/$i" "${NEWROOT}/$i"
fi
done
mount -t tmpfs -o size=100% tmpfs "${NEWROOT}/tmp"
mkdir -p "${WORKDIR}"
mount --move "${OLDROOT}/${WORKDIR}" "${WORKDIR}"
echo "Restarting SSH daemon..."
systemctl daemon-reload
systemctl is-active ssh && systemctl stop ssh || true
systemctl restart sshd
echo "Disabling swap..."
swapoff -a
echo "Restarting init process..."
systemctl daemon-reexec
systemctl --quiet is-system-running || true
echo -e "If you are connecting from SSH, please create a second session to this host use root and" echo -e "If you are connecting from SSH, please create a second session to this host use root and"
echo -e "confirm you can get a shell." echo -e "confirm you can get a shell."
echo -e "After your confirmation, we are going to kill the old SSH server." echo -e "After your confirmation, we are going to kill the old SSH server."
if menhera::confirm; then if menhera::confirm; then
menhera::clear_processes echo "Killing all programs still using the old root..."
fuser -kvm "${OLDROOT}" -15
# in most cases the parent process of this script will be killed, so goodbye
else else
echo -e "Please manually issue a reboot to recover your old OS. If you believe there is a bug in menhera.sh, " echo -e "Please manually issue a reboot to recover your old OS. If you believe there is a bug in menhera.sh, "
echo -e "raise a ticket at https://github.com/Jamesits/menhera.sh/issues ." echo -e "raise a ticket at https://github.com/Jamesits/menhera.sh/issues ."
exit 1
fi fi