An initramfs, short for initial ram file system, is a mini userspace that is directly "baked" into the kernel. After the kernel has been loaded by the UEFI/BIOS, it itself loads the the initramfs into memory. Thus, a small userspace is available before any storage medium has been mounted.
The initramfs can be useful to e.g. decrypt storage media that hold the actual userspace of the machine.
Create the following directory structure:
/usr/src/initramfs ├── bin ├── init ├── dev ├── lib ├── proc └── sys
The directories can then be populated with the desired userspace software. The file "init" needs to be executable and contain the program to initially start.
Additionally, the kernel configuration must be adapted so the initramfs is actually "baked" into the kernel image. This is done as follows:
make menuconfig:
General setup -> Initial RAM filesystem and RAM disk (initramfs/initrd) support,
set General setup -> Initramfs source file(s) to /usr/src/initramfs.
.config file:
INITRAMFS_SOURCE=/usr/src/initramfs
Then, recompile the kernel.
Note: if the initramfs is changed,
make sure to run make clean
before recompiling the kernel.
Otherwise, the changes are not applied.
Compile and statically link the following software:
ls, cp, ...
To prepare the directory tree:
busybox and cryptsetup
to the directory /usr/src/initramfs/bin.
/usr/src/initramfs/dev/console
exists: mknod -m 600 /usr/src/initramfs/dev/console c 5 1
/usr/src/initramfs/bin.
for f in $(./busybox --list); do ln -s busybox $f; done,
to create the symlinks of the individual tools to the busybox
multicall binary.
Add the following code to /usr/src/initramfs/init
and make sure it is executable:
#!/bin/sh
die() {
unset i
echo "Something went wrong. Dropping to a shell."
exec sh
}
# Mount the /proc, /sys and /dev filesystems.
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
# Be a little bit more quiet.
echo 0 > /proc/sys/kernel/printk
wait # For dev.
# Decrypt root partition and possible secondary partition.
i=0
while true; do
# Open encrypted partition, and place at /dev/mapper/root.
read -s -p "Password: " password
echo $password | cryptsetup open --allow-discards --perf-no_read_workqueue --perf-no_write_workqueue /path/to/rootdevnode root && break
i=$((i+1))
[ $i -gt 4 ] && break && die
done
mount -o ro /dev/mapper/root /mnt/root
echo $password | cryptsetup open --allow-discards --perf-no_read_workqueue --perf-no_write_workqueue /path/to/devnode2 @NAME2@ && break
echo $password | cryptsetup open --allow-discards --perf-no_read_workqueue --perf-no_write_workqueue /path/to/devnode3 @NAME3@ && break
# ... As many as desired
unset password
unset i
mount -o ro /dev/mapper/@NAME2@ /path/to/mountpoint2
mount -o ro /dev/mapper/@NAME3@ /path/to/mountpoint3
# ... As many as desired
# It's okay to speak again.
echo 1 > /proc/sys/kernel/printk
# Clean up
umount /proc
umount /sys
umount /dev
# Switch to real root.
exec switch_root /mnt/root /sbin/init || die
Here, /path/to/devnode{2,3,...} are the device nodes
of an additional storage devices encrypted with the same password.
Finally, recompile the kernel to have it contain the initramfs.
Compile and statically link the following software:
ls, cp, ...
To prepare the directory tree:
busybox, dropbear,
dbclient and dropbearkey
to the directory /usr/src/initramfs/bin.
/usr/src/initramfs/bin.
for f in $(./busybox --list); do ln -s busybox $f; done,
to create the symlinks of the individual tools to the busybox
multicall binary.
/etc/dropbear/dropbear_ed25519_host_key
by running
dropbearkey -t ecdsa -f /etc/dropbear/dropbear_ed25519_host_key.
/etc/passwd exists
and contains at least:
root:x:0:0:root:/home/root:/bin/sh
/etc/group
and have it contain at least:
root:x:0:root
/home/root/.ssh/authorized_keys
and add the auth key of the form:
ssh-ed25519 AAAAB3NzaC1yc2EAAAABIwAAAIEAwVa6M6cGVmUcLl2cFzkxEoJd06Ub4bVDsYrWvXhvUV+ZAM9uGuewZBDoAqNKJxoIn0Hyd0NkyU99UVv6NWV/5YSHtnf35LKds56j7cuzoQpFIdjNwdxAN0PCET/MG8qyskG/2IE2DPNIaJ3Wy+Ws4IZEgdJgPlTYUBWWtCWOGc= USER@HOST
Add the following code to /usr/src/initramfs/init
and make sure it is executable:
#!/bin/sh
die() {
unset i
unset pwd
echo "Something went wrong. Dropping to a shell."
exec sh
}
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
mkdir -p /dev/pts
mount -t devpts none /dev/pts
# Be a little bit more quiet.
echo 0 > /proc/sys/kernel/printk
ifconfig @IFACE@ up
ifconfig @IFACE@ @IP@ netmask @NETMASK@ broadcast @BRD@
route add default gw @GATEWAY@
wait
/bin/dropbear -s | die