#!/bin/bash link() { ls -l $1 | cut -d '>' -f 2- | cut -d ' ' -f 2 } injectFileAndLink() { local b=$(basename $1) local d=$(dirname $1) local l #echo "--> $1" [ ! -d $DST/$d ] && mkdir -p $DST/$d [ ! -e $DST/$1 ] && { #echo "cp $1 $DST/$1" cp -a $1 $DST/$1 } if [ -L $1 ]; then l=$(link $1) # Absolute link if ! echo $l | grep -q '^/'; then l=$d/$l fi injectFileAndLink $l fi } injectDepends() { local b d l ld #echo "deps : $1" ! file $1 | grep -q 'dynamically linked' && return # Dynmamic linker l=$(ldd $1 | grep -v '=>' | grep ld-linux | sed -re 's/^[[:space:]]*//' | cut -d ' ' -f 1) #echo " $l" injectFileAndLink $l # Libraries for l in $(ldd $1 | grep '=>' | cut -d '>' -f 2 | cut -d ' ' -f 2); do #echo " -> $l" injectFileAndLink $l done } injectCommandWithDepends() { local f=$1 if ! echo $1 | grep -q '/'; then f=$(whereis -b -B $SEARCH_DIRS -f $1 | cut -d ' ' -f 2) fi #echo "*** $f" [ -z "$f" ] && error "Command $f not found in $SEARCH_DIRS !" injectFileAndLink $f injectDepends $f if [ -L $f ]; then f=$(link $f) injectCommandWithDepends $f fi } getRandomPasswd() { local k while :; do k=$(tr -dc _A-Z-a-z-0-9 < /dev/urandom 2> /dev/null | head -c${1:-32} ) if [ $(echo -n $k | wc -c) = 32 ]; then break fi echo "Wait for entropy avail : $(cat /proc/sys/kernel/random/entropy_avail)" >&2 sleep 1 done echo -n $k } debootstrap() { #if [ -e $VDN_PATH/files/$HDA ]; then # echo "Warning : $VDN_PATH/files/$HDA exist. Skip debootstrap !" # return #fi ID=$(echo $GUEST_SYS|cut -d '/' -f 1) VERSION_CODENAME=$(echo $GUEST_SYS|cut -d '/' -f 2) TMP_DIR=/tmp/bootstrap-$VERSION_CODENAME-$USER KVERS=$(uname -r) [ -n "$KVERS" ] || { error "KVERS is empty !?! "; } LOCAL_KERNEL=$(ls /boot/vmlinuz*$KVERS | head -n 1) [ -n "$LOCAL_KERNEL" ] || { error "No kernel found in /boot for $KVERS"; } LOCAL_INITRD=$(ls /boot/initrd*$KVERS | head -n 1) [ -n "$LOCAL_INITRD" ] || { error "No initrd found in /boot for $KVERS"; } FORMAT=$(file $LOCAL_INITRD) case "$FORMAT" in *gzip*) FORMAT=gzip;; *cpio*) FORMAT=asciiCpio;; *Zstandard*) FORMAT=zStandard;; *) echo "Unknown initrd format ($FORMAT)" >&2 exit 1 esac if [ $FORMAT = zStandard ]; then [ -z "$(which zstdcat)" ] && error "zstdcat not found ! Need zstd package !" [ -z "$(which zstd)" ] && error "zstd not found ! Need zstd package !" fi [ ! -d $TMP_DIR/initrd ] && mkdir -p $TMP_DIR/initrd export DST=$TMP_DIR/initrd ( set -eu cd $TMP_DIR if [ ! -e $TMP_DIR/initrd/init ]; then echo "Extract $LOCAL_INITRD..." case $FORMAT in asciiCpio|gzip) ( cd initrd && zcat $LOCAL_INITRD | cpio -idm > /dev/null);; zStandard) ( cd initrd && zstdcat $LOCAL_INITRD | cpio -idm > /dev/null ) esac fi [ -e $TMP_DIR/initrd/init.bak ] || cp $TMP_DIR/initrd/init $TMP_DIR/initrd/init.bak #rm -f $DST/bin/busybox $DST/usr/bin/busybox echo "Inject packages..." #apt-get download haveged #dpkg -x haveged*.deb initrd #apt-get download libhavege2 #dpkg -x libhavege2*.deb initrd apt-get download busybox dpkg -x busybox_*.deb initrd apt-get download debootstrap dpkg -x debootstrap*.deb initrd apt-get download file dpkg -x file*.deb initrd apt-get download libmagic-mgc dpkg -x libmagic-mgc*.deb initrd #apt-get download haveged #dpkg -x haveged*.deb initrd echo "Inject files and program with depends..." [ ! -d $DST/bin ] && mkdir $DST/bin injectCommandWithDepends /bin/bash injectCommandWithDepends /sbin/modprobe injectCommandWithDepends /sbin/fdisk injectCommandWithDepends /sbin/mke2fs injectCommandWithDepends /usr/bin/gpgv injectCommandWithDepends /usr/bin/perl #injectCommandWithDepends /usr/bin/file #injectCommandWithDepends /usr/bin/ldd #injectCommandWithDepends /usr/bin/strace #injectCommandWithDepends /usr/bin/script injectFileAndLink /lib/x86_64-linux-gnu/libresolv.so.2 injectFileAndLink /lib/x86_64-linux-gnu/libnss_files.so.2 injectFileAndLink /lib/x86_64-linux-gnu/libnss_dns.so.2 #injectFileAndLink /usr/lib/x86_64-linux-gnu/libidn2.so cp /sbin/mke2fs $DST/bin/mke2fs #injectCommandWithDepends /bin/grep #mv $DST/usr/bin/grep $DST/bin/grep #injectCommandWithDepends /usr/bin/perl #injectCommandWithDepends /usr/bin/wget #cp /usr/bin/wget $DST/bin mkdir -p $DST/usr/share/keyrings cp /usr/share/keyrings/debian-archive-keyring.gpg $DST/usr/share/keyrings cp /etc/resolv.conf $DST/etc/resolv.conf ) echo "Inject scripts..." cp $VDN_PATH/scripts/on-boot $TMP_DIR/initrd set +u cat << EOF > $TMP_DIR/initrd/init #!/bin/bash #set -a #. /config #set +a [ -d /dev ] || mkdir -m 0755 /dev [ -d /proc ] || mkdir /proc [ -d /sys ] || mkdir /sys mkdir -p /var/lock mount -t sysfs -o nodev,noexec,nosuid sysfs /sys mount -t proc -o nodev,noexec,nosuid proc /proc mkdir /dev/pts mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts modprobe virtio_pci modprobe virtio_blk modprobe ext4 modprobe crc32c modprobe virtio-net mdev -s rm -f /dev/null; mknod -m 666 /dev/null c 1 3 if ! fdisk -l /dev/vda | grep -q /dev/vda1; then echo -e "n\np\n1\n\n\nw\n" | fdisk /dev/vda mdev -s /bin/mke2fs -j -t ext4 /dev/vda1 fi rm -f /dev/null; mknod -m 666 /dev/null c 1 3 mkdir -p /tmp/d mount /dev/vda1 /tmp/d || { echo "Can't mount partition !" >&2 echo "Repair + exit to continue or poweroff -f to halt !" /bin/busybox ash } ifconfig eth0 10.0.2.15 route add default gw 10.0.2.2 ln -sf /bin/bash /bin/sh [ -n "$http_proxy" ] && export http_proxy="$http_proxy" [ -n "$https_proxy" ] && export https_proxy="$https_proxy" #echo "Before debootstrap. exit to continue." #/bin/sh -i if [ ! -d /tmp/d/bin ]; then echo "Debootstrap $VERSION_CODENAME ..." debootstrap --arch=amd64 $VERSION_CODENAME /tmp/d fi mount -o bind /dev /tmp/d/dev mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /tmp/d/dev/pts mount -o bind /proc /tmp/d/proc mount -o bind /sys /tmp/d/sys #cp /config /tmp/d/root/config cp /base.sh /tmp/d/root/base.sh [ ! -d /tmp/d/etc/vdn ] && mkdir -p /tmp/d/etc/vdn cp /on-boot /tmp/d/etc/vdn chmod 755 /tmp/d/etc/vdn/on-boot #echo "Before chroot, exit to quit" #/bin/busybox ash chroot /tmp/d /root/base.sh #echo "In chroot exit to quit" #chroot /tmp/d /bin/bash #/bin/busybox ash poweroff -f EOF chmod 755 $TMP_DIR/initrd/init cat << EOF > $DST/base.sh #set -a #. /root/config #set +a export DEBIAN_FRONTEND=noninteractive [ -n "$http_proxy" ] && export http_proxy="$http_proxy" [ -n "$https_proxy" ] && export https_proxy="$https_proxy" apt-get -y update apt-get -y upgrade apt-get -y install linux-image-amd64 grub2 # Inject initramfs config scripts [ ! -d /etc/initramfs-tools ] && mkdir -p /etc/initramfs-tools echo "overlay" >> /etc/initramfs-tools/modules sed -i -re 's/^MODULES=.*$/MODULES=dep/' /etc/initramfs-tools/initramfs.conf update-initramfs -u update-grub rm -f /etc/initramfs-tools/scripts/init-premount/vdn cat << END > /etc/initramfs-tools/scripts/local-bottom/vdn #!/bin/sh PREREQ="lvm" prereqs() { echo "\\\$PREREQ" } case \\\$1 in prereqs) prereqs exit 0 ;; esac . /scripts/functions # Begin real processing below this line echo "ECHO : Starting vdn pre-mount, exit to quit !" >&2 log_begin_msg "Starting vdn pre-mount, exit to quit !" # Extract tgz lastDisk=\\\$(ls /dev/vd*| grep '/...$' | tail -n 1) if [ -n "\\\$lastDisk" ]; then if tar -C / -xzf \\\$lastDisk; then set -a . /etc/vdn/config set +a else echo >&2 echo "WARNING : no vdn config partition found !" >&2 sleep 3 exit 1 fi else echo 'Not a VDN VM (/dev/vd? !)' >&2 sleep 3 exit 1 fi #echo "/etc/initramfs-tools/scripts/local-bottom/vdn : before . /etc/vdn/on-initramfs" >&2 #/bin/busybox ash chown root:root / chmod 755 / . /etc/vdn/on-initramfs log_end_msg END chmod 755 /etc/initramfs-tools/scripts/local-bottom/vdn #echo "base.sh : after install kernel" #/bin/bash -i [ -n "$http_proxy" ] && export http_proxy="$http_proxy" [ -n "$https_proxy" ] && export https_proxy="$https_proxy" apt-get -y update apt-get -y upgrade apt-get -y install ssh locales mingetty file #grub-install /dev/vda #update-grub echo "root:$(getRandomPasswd)" | chpasswd [ ! -e /home/test ] && adduser --disabled-password --gecos '' test echo "test:$(getRandomPasswd)" | chpasswd apt-get -y install ssh # task-ssh-server #apt-get -y install task-xfce-desktop cat << END > /etc/fstab # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # # / was on /dev/vda1 during installation /dev/vda1 / ext4 errors=remount-ro 0 1 END [ ! -d /etc/vdn ] && mkdir /etc/vdn if [ ! -e /etc/rc.local ]; then cat << END > /etc/rc.local #!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. END fi if ! grep -q /etc/vdn/on-boot /etc/rc.local; then cat << END >> /etc/rc.local sh /etc/vdn/on-boot END fi chmod 755 /etc/rc.local echo "Allow root autologin on ttyS0" sed -i -re 's,^ExecStart=.*$,ExecStart=-/sbin/mingetty --noclear --autologin root %I,' /lib/systemd/system/serial-getty@.service echo "Allow net.ifnames=0 in GRUB + console" sed -i -re 's,^GRUB_CMDLINE_LINUX_DEFAULT=.*$,GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0 console=ttyS0\,115200n8 noresume blacklist=floppy\",' /etc/default/grub echo "Set 1s timout for Grub menu" sed -i -re 's,^GRUB_TIMEOUT=.*$,GRUB_TIMEOUT=0,' /etc/default/grub update-grub echo "Allow ssh root connection" if grep -q '^#?PermitRootLogin ' /etc/ssh/sshd_config; then sed -i -re 's/^#?PermitRootLogin/PermitRootLogin prohibit-password' /etc/ssh/sshd_config else echo 'PermitRootLogin prohibit-password' >> /etc/ssh/sshd_config fi #apt-get install -y --reinstall linux-image-amd64 update-initramfs -u grub-install /dev/vda #update-grub #echo "End of base.sh, exit to quit" #/bin/bash -i EOF chmod 755 $DST/base.sh [ ! -e $VDN_PATH/files/$HDA ] && { echo "Create sparse disk $VDN_PATH/files/$HDA ($HDA_SIZE M)..." dd of=$VDN_PATH/files/$HDA count=0 bs=1M seek=$HDA_SIZE } # Build $TMP_DIR/initrd.img #if [ ! -e $TMP_DIR/initrd.img ]; then echo "Create $TMP_DIR/initrd.img..." case $FORMAT in asciiCpio|gzip) ( cd $TMP_DIR/initrd && find . | cpio -o -H newc -R root:root | gzip -9 > $TMP_DIR/initrd.img);; zStandard) ( cd $TMP_DIR/initrd && find . | cpio -o -H newc -R root:root | zstd -9 > $TMP_DIR/initrd.img );; esac #fi #echo "Press return to continue !" #read echo "Boot and debootstrap..." qemu-system-x86_64 -kernel $LOCAL_KERNEL -smp 8 -enable-kvm -cpu host -device virtio-rng-pci,rng=rng0 -object rng-random,filename=/dev/urandom,id=rng0 -rtc base=localtime -m 3072M -nographic -serial mon:stdio -monitor null -initrd $TMP_DIR/initrd.img -append "root=/dev/vda boot=live ro console=ttyS0,115200n8 net.ifnames=0 noresume" -boot order=c -drive file=$VDN_PATH/files/$HDA,if=virtio,format=raw -device virtio-net-pci,netdev=n0,mac=52:56:0A:E8:00:02 -netdev user,id=n0 } # $1 : system name started cleanHistory() { echo "Clear /var/log, history, ..." vdn-ssh -t root@$1 ' #rm -Rf /etc/vdn set -a . /etc/vdn/config set +a rm -f /etc/vdn-$MODE-initialized #for i in $(find /var/log -type f); do cat /dev/null > $i; done find /var/log -name "*.gz" -delete echo "Clear .bash_history" rm -f /root/.bash_history touch /root/.bash_history chmod 600 /root/.bash_history rm -f /home/test/.bash_history touch /home/test/.bash_history chmod 600 /home/test/.bash_history echo "Clear .cache .mozilla" for d in /root /home/test; do rm -Rf $d/.cache rm -Rf $d/.mozilla done echo "$$$ Clear apt-cache..." apt autoremove -y sleep 1 apt-get clean echo "Clear authorized_keys (only user test)" for d in /root /home/test; do rm -f $d/.ssh/authorized_keys rm -Rf $d/.mozilla done echo end of cleaning ! echo "poweroff (in 3 s) !" poweroff -f ' }