Initramfs

This tuto explain how to create an initramfs with :

  • secured remote connection through ssh
  • mount raid devices
  • mount cryptsetup encrypted partitions
  • screen to control initramfs boot process through ssh (same screen on both sides)

Creation of you initramfs :

livecd / # mkdir /usr/src/initramfs
livecd / # cd /usr/src/initramfs
livecd initramfs # mkdir -p bin dev etc lib64 lib64/modules new proc sbin sys usr usr/bin var
livecd initramfs # ln -s lib64 lib

Install softwares to the initramfs

Emerge packages

unmask packages :

/etc/portage/package.keywords

sys-fs/cryptsetup ~amd64
sys-fs/lvm2 ~amd64
sys-fs/udev ~amd64

set flags :

/etc/portage/package.use

net-misc/openssh static
sys-apps/busybox static
sys-fs/mdadm static

we are going to emerge some packages :

livecd / # emerge -a openssh mdadm cryptsetup busybox screen

Check libs used by a software if you want to add dynamic executable :

livecd initramfs # ldd /usr/bin/nano
        linux-vdso.so.1 =>  (0x00007fff1e9fe000)
        libncursesw.so.5 => /lib/libncursesw.so.5 (0x00007f7516551000)
        libc.so.6 => /lib/libc.so.6 (0x00007f75161fc000)
        libdl.so.2 => /lib/libdl.so.2 (0x00007f7515ff8000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f75167be000)

warning: There is also applications that are using libs even if its compiled in static mode, so pay attention if you add other applications

Copy applications to initramfs

copy executable to initramfs:

livecd initramfs # cp /bin/busybox /usr/src/initramfs/bin
livecd initramfs # cp /sbin/mdadm /usr/src/initramfs/bin
livecd initramfs # cp /sbin/cryptsetup /usr/src/initramfs/bin
livecd initramfs # cp /usr/sbin/sshd /usr/src/initramfs/bin/
livecd initramfs # cp /usr/sbin/MAKEDEV /usr/src/initramfs/bin/

Sshd

livecd initramfs # mkdir /usr/src/initramfs/etc/ssh
livecd initramfs # cd /usr/src/initramfs/etc/ssh
livecd ssh # echo "Protocol 2" > sshd_config
livecd ssh # echo "PermitRootLogin yes" >> sshd_config
livecd ssh # echo "UsePrivilegeSeparation no" >> sshd_config
livecd ssh # /usr/bin/ssh-keygen -t rsa1 -f /usr/src/initramfs/etc/ssh/ssh_host_key -N ""
livecd ssh # /usr/bin/ssh-keygen -t dsa -f /usr/src/initramfs/etc/ssh/ssh_host_dsa_key -N ""
livecd ssh # /usr/bin/ssh-keygen -t rsa -f /usr/src/initramfs/etc/ssh/ssh_host_rsa_key -N ""

Screen

we are going to use screen to have the same terminal on computer screen but also by ssh:

livecd initramfs # cp /usr/bin/screen /usr/src/initramfs/usr/bin/
livecd initramfs # mkdir -p /usr/src/initramfs/etc/terminfo/x/
livecd initramfs # mkdir -p /usr/src/initramfs/etc/terminfo/l/
livecd initramfs # cp /etc/terminfo/x/xterm /usr/src/initramfs/etc/terminfo/x/
livecd initramfs # cp /etc/terminfo/l/linux /usr/src/initramfs/etc/terminfo/l/
livecd initramfs # mkdir -p /usr/src/initramfs/var/run/screen
livecd initramfs # cd /usr/src/initramfs/bin
livecd bin # ln -s busybox sh
livecd bin # echo '#!/bin/sh' > screensh
livecd bin # echo 'screen -Rx' >> screensh
livecd bin # chmod +x screensh
livecd bin # echo "root:x:0:0:Linux User,,,:/:/bin/screensh" > /usr/src/initramfs/etc/passwd
livecd bin # echo "root:x:0:" > /usr/src/initramfs/etc/group
livecd bin # echo "root:x:14698:0:99999:7:::" > /usr/src/initramfs/etc/shadow

udev

livecd bin # cp /sbin/udev* /usr/src/initramfs/sbin/
livecd bin # cd /usr/src/initramfs/dev
livecd dev # mknod console c 5 1
livecd dev # mknod null c 1 3

Copy libs

livecd dev # cp -d /lib/* /usr/src/initramfs/lib/

Creation of init script

/usr/src/initramfs/init

#!/bin/busybox sh

SSH_IP=192.168.42.253
SSH_PORT=4224
SSH_IFACE=eth0
ROOT_DEVICE=/dev/mapper/md2
ROOT_PASSWD="password"
ALLOW_SH=1

###################################################################
## func
###################################################################

rshell() {
    echo "## bringing network on $SSH_IFACE:$SSH_IP"
    ifconfig $SSH_IFACE $SSH_IP up
        /bin/sshd -p $SSH_PORT
}

mydev() {
    [ -c /dev/console ] || mknod -m 600 /dev/console c 5 1
    [ -c /dev/tty1 ] || mknod -m 620 /dev/tty1 c 4 1
    [ -c /dev/tty ] || mknod -m 666 /dev/tty c 5 0
    [ -c /dev/null ] || mknod -m 666 /dev/null c 1 3
    [ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11
    ln -snf /proc/self/fd /dev/fd
    ln -snf fd/0 /dev/stdin
    ln -snf fd/1 /dev/stdout
    ln -snf fd/2 /dev/stderr
    [ -e /proc/kcore ] && ln -snf /proc/kcore /dev/core
    mkdir -p /dev/pts /dev/shm
    udevd --daemon
    udevadm control --env do_not_run_plug_service=1
    udevadm trigger --attr-match=dev
    udevadm trigger --subsystem-match=net
    udevadm settle  --timeout=60
    udevadm control --env do_not_run_plug_service=
    mount -n -t devpts devpts /dev/pts
    MAKEDEV -d ptmx
}

sysinit() {
    echo "#############################################################"
    echo "##Awired initramfs"
    echo "#############################################################"

    echo "## Loading keyboard map"
    loadkmap < keymap.bin

    echo "## Install busybox"
    busybox --install -s

    echo "## Mount the /proc and /sys filesystems"
    mount -n -t proc proc /proc
    mount -n -t sysfs sysfs /sys

    echo "## Populating /dev with udev"
    mydev

    echo "## change root password"
    echo "root:$ROOT_PASSWD" | chpasswd

    echo "## Running remote shell with sshd"
    rshell

    echo "## run screen"
    screen ./init "lets go"

    while [ `cat /proc/mounts | grep /new | wc -l` == 0 ]
    do
        screen ./init "Trying to switch_root but /new is not mounted !!!!!!" "1"
    done

        echo "## Clean up"
        killall sshd
        killall udevd
        umount /dev/pts
        umount /proc
        umount /sys

    echo "## switch root to /new"
    exec switch_root /new /sbin/init
}

tshell() {
    if [ $ALLOW_SH == "1" ]; then
        echo "## drop you to a shell : $1"
        /bin/sh --noprofile
    fi
}

ucryptdd() {
    cd /dev/
    # uncrypt raid drives
    for i in $( ls -1 md? ); do
            if [[ "$i" == "md0" || "$i" == "md1" ]] ; then
                    echo "## skipping $i";
            else
                    echo "## trying to uncrypt : $i";
                    cryptsetup luksOpen /dev/$i $i;
            fi
    done

    # uncrypt non raid drives
    for i in $( ls -1 sd?? ); do
            if grep -q "$i" "/proc/mdstat"; then
                    echo "## skip $i as its in use by a raid array";
            else
                    echo "## trying to uncrypt : $i";
                    cryptsetup luksOpen /dev/$i $i;
            fi
    done
}

###########################################################################

if [ -z "$1" ]; then
    sysinit
else

   if [ -z "$2" ]; then

        echo "## Loading raid devices"
        mdadm --auto-detect || tshell

        echo "## uncrypt drives"
        ucryptdd

        echo "## mount swap"
        cryptsetup -d /dev/urandom create swap /dev/md2
        mkswap /dev/mapper/swap
        swapon /dev/mapper/swap

        echo "## Mount $ROOT_DEVICE"
        mount -n $ROOT_DEVICE /new
    else
        tshell "$1"
    fi

    exit
fi

Allow init script to be executed :

livecd dev # chmod +x /usr/src/initramfs/init

Add keymap

Create your keymap

livecd dev # busybox dumpkmap > /usr/src/initramfs/keymap.bin

Generate initramfs image out of kernel

/usr/src/initramfs/gen.sh

mount /boot
find . -print0 | cpio -ov -0 --format=newc | gzip -9 > /boot/initramfs.gz

Allow generate script to be executed :

livecd dev # chmod +x /usr/src/initramfs/gen.sh

genererate initramfs

livecd dev # cd /usr/src/initramfs/
livecd initramfs # ./gen.sh

Rebuild openssh

Openssh was compiled as static and you will not work on default gentoo configuration, so we will reemerge it without static flag

/etc/portage/package.use

#net-misc/openssh static
sys-apps/busybox static
sys-fs/mdadm static
livecd initramfs # emerge -a openssh
hive/system/gentoo/initramfs.txt · Last modified: 20/07/2010 12:01 by n0rad -
Top