summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile29
-rw-r--r--README56
-rwxr-xr-xcomp_bench21
-rw-r--r--cpio_list.txt12
-rw-r--r--init2
-rwxr-xr-xmake33
-rw-r--r--unlock2
7 files changed, 128 insertions, 27 deletions
diff --git a/Makefile b/Makefile
index 6832bbd..3a2f16b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,24 +1,27 @@
-CC = gcc
-CFLAGS ?= -O2 -pipe
-MAKEFLAGS += -L -R -r
-
all: initramfs.img
-initramfs.img: gen_init_cpio
+initramfs.img: gen_init_cpio dropbear_rsa_host_key dropbear_ecdsa_host_key
./make
--include initramfs.d
-
gen_init_cpio: gen_init_cpio.c
- $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) gen_init_cpio.c -o $@
+
+dropbear_rsa_host_key:
+ dropbearkey -t rsa -f $@
+
+dropbear_ecdsa_host_key:
+ dropbearkey -t ecdsa -f $@
install: initramfs.img
- rm -f /boot/$<.old /boot/$<.new
- cp $< /boot/$<.new || rm -f /boot/$<.new
- if [ -e /boot/$< ]; then mv /boot/$< /boot/$<.old; fi
- mv /boot/$<.new /boot/$<
+ rm -f /boot/initramfs.img.old /boot/initramfs.img.new
+ cp initramfs.img /boot/initramfs.img.new || rm -f /boot/initramfs.img.new
+ if [ -e /boot/initramfs.img ]; then mv /boot/initramfs.img /boot/initramfs.img.old; fi
+ mv /boot/initramfs.img.new /boot/initramfs.img
clean:
- rm -f -r initramfs.img initramfs.d gen_init_cpio
+ rm -f initramfs.img initramfs.d gen_init_cpio
+
+-include initramfs.d
.PHONY: all install clean
+MAKEFLAGS += -r # slightly faster
diff --git a/README b/README
new file mode 100644
index 0000000..4630f38
--- /dev/null
+++ b/README
@@ -0,0 +1,56 @@
+This is my initramfs generator. I use this on my desktop Gentoo system. For my
+laptop Arch system, I use mkinitcpio.
+
+Basically, it's a suckless initramfs generator: it does exactly what I need.
+You need something else? Patch it, it's only 117 lines.
+
+Features:
+
+- password LUKS unlock
+- SSH remote unlock
+- firmware loading
+- extremely fast initramfs creation: compression off: ~70ms cold cache, ~30ms
+ warm; lz4 --best: 1.6s
+- extremely fast initramfs runtime: ~zero overhead compared to direct kernel
+ loading
+- minimal code: 117 SLOC total (init + make + Makefile + unlock)
+- pure POSIX shell + POSIX Makefile
+
+Drawbacks:
+
+- no modprobe support. custom kernel is required to use myinitramfs. if you
+ want configurability, probably better to use mkinitcpio or dracut.
+- pure POSIX shell + POSIX Makefile
+
+Usage:
+
+0. Read (skim) https://wiki.gentoo.org/wiki/Custom_Initramfs.
+
+1. Install busybox, dropbear, e2fsprogs (if you use ext4).
+
+2. Adjust ./init as required:
+ a) Adjust networking as required (e.g. maybe static IP instead of DHCP, or
+ you don't use eth0)
+ b) Adjust UUID (probably yours is not the same as mine)
+ c) Adjust fsck as needed (if you are not using ext4)
+ d) Put whatever you want:
+
+3. Adjust ./make as required:
+ a) Put your needed commands in gen_cpio_list.
+ b) Select your desired compressor at the end. Try make comp_bench for a comparison.
+ summary: lz4 is usually best, xz if storage is important above all (saves
+ a few MB but adds ~0.5s to boot), gzip is mediocre on both size and
+ speed, lzo is almost always worse than lz4, never use bzip2 or lzma.
+
+4. Customize cpio_list.txt with your required files. Remember that commands
+ must go in ./make (for library detection), and device files except
+ /dev/console and non-empty directories can be omitted.
+
+5. Add your public keys to authorized_keys. Note that dropbear only supports
+ RSA and ECDSA keys.
+
+6. make
+
+7. sudo make install
+
+8. Configure your boot loader/boot manager to use initramfs.img.
diff --git a/comp_bench b/comp_bench
new file mode 100755
index 0000000..01387da
--- /dev/null
+++ b/comp_bench
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+set -e
+
+do_bench() {
+ tmpfile=$(mktemp)
+ trap 'rm -f "$tmpfile"' EXIT
+ compressor=cat outfile=/proc/self/fd/1 ./make | "$@" -c < initramfs.img > "$tmpfile"
+ printf '%s: %s bytes\n' "$1" "$(wc -c < "$tmpfile")"
+ time $1 -dc < "$tmpfile" >/dev/null
+ rm "$tmpfile"
+ trap '' EXIT
+ echo
+}
+
+do_bench gzip -9
+do_bench bzip2 -9
+do_bench lzma -9e --check=crc32
+do_bench xz --check=crc32 --x86 --lzma2=preset=9e
+do_bench lzop -9
+do_bench lz4 --best --favor-decSpeed -l
diff --git a/cpio_list.txt b/cpio_list.txt
index 79b38f0..016170f 100644
--- a/cpio_list.txt
+++ b/cpio_list.txt
@@ -1,5 +1,8 @@
-# basic directories. note that parent directories for files will be
-# auto-generated by make script, and everything will be sorted afterwards
+# myinitramfs cpio_list.txt
+# see ./gen_init_cpio for syntax
+
+# basic directories. note that all required parent directories will be
+# auto-generated by make, and everything will be sorted afterwards
dir /dev 0755 0 0
dir /mnt 0755 0 0
dir /proc 0755 0 0
@@ -7,7 +10,8 @@ dir /run 0755 0 0
dir /run/cryptsetup 0755 0 0
dir /sys 0755 0 0
-# kernel needs this to be available before /init
+# kernel does /init <>/dev/console and fails if it doesn't exist in initramfs
+# devtmpfs will provide other devices
nod /dev/console 0600 0 0 c 5 1
# symlinks
@@ -34,7 +38,7 @@ file /lib/firmware/amdgpu/polaris10_uvd.bin /lib/firmware/amdgpu/polaris10_uvd.b
file /lib/firmware/amdgpu/polaris10_vce.bin /lib/firmware/amdgpu/polaris10_vce.bin 0644 0 0
file /lib/firmware/rtl_nic/rtl8168h-2.fw /lib/firmware/rtl_nic/rtl8168h-2.fw 0644 0 0
-# dropbear support
+# remote unlock
file /etc/dropbear/dropbear_ecdsa_host_key ./dropbear_ecdsa_host_key 0600 0 0
file /etc/dropbear/dropbear_rsa_host_key ./dropbear_rsa_host_key 0600 0 0
file /etc/passwd ./passwd 0644 0 0
diff --git a/init b/init
index 8df2dda..de10111 100644
--- a/init
+++ b/init
@@ -18,7 +18,7 @@ udhcpc -i eth0
dropbear -p 2222
) >/dev/null 2>&1 &
-root=$(findfs UUID=26748575-d7a7-418b-8f68-21be7c937500) || exit
+root=$(findfs UUID=ec8fb072-1200-4275-9494-f6f869187806) || exit
cryptsetup open --tries 65535 --allow-discards "$root" root
# in case of /sbin/unlock
[ -e /dev/mapper/root ] || exit
diff --git a/make b/make
index 9f35483..1abf52b 100755
--- a/make
+++ b/make
@@ -1,17 +1,27 @@
#!/bin/sh
-set -e
+[ -n "$compressor" ] || compressor="lz4 --best --favor-decSpeed -l"
+#[ -n "$compressor" ] || compressor="xz -c --check=crc32 --x86 --lzma2=preset=9e"
-compressor="lz4 --best --favor-decSpeed -l"
+# for comp_bench
+[ -n "$outfile" ] || outfile=initramfs.img
+
+toppid=$$
+die() {
+ fmt=$1
+ shift
+ printf "error building initramfs: $fmt\n" "$@" >&2
+ kill "$toppid"
+ trap '' EXIT
+ exit 1
+}
# generate a cpio entry for a command
gen_cmd() {
cmd=$1
- cmdp="$(command -v "$cmd")"
- # builtin
- if [ "$cmd" = "$cmdp" ]; then
- return
- fi
+ cmdp="$(command -v "$cmd")" || die 'command not found: %s' "$cmd"
+ # ignore builtins
+ [ "$cmd" != "$cmdp" ] || return
printf 'file %s %s 0755 0 0\n' "$cmdp" "$cmdp"
ldd "$cmdp" | grep / | while read line; do
tmp=${line% *}
@@ -26,8 +36,11 @@ gen_cpio_list() {
sed -e '/^#/d' cpio_list.txt
gen_cmd e2fsck
gen_cmd dropbear
+ # cryptsetup argon2 uses pthread_cancel, glibc dlopens libgcc_s.so.1
+ # ldd will find the correct libgcc_s.so.1 based on ld.so.conf
export LD_PRELOAD=libgcc_s.so.1
gen_cmd cryptsetup
+ # LD_PRELOAD unset at end of subshell
}
# filter the list and insert parent directory entries
@@ -65,9 +78,13 @@ if ! [ -e cpio_list.txt ] || ! [ -e gen_init_cpio ]; then
cd "${0%/*}"
fi
+trap 'test -L initramfs.img || test -f initramfs.img && rm -f initramfs.img; exit 1' HUP INT QUIT TERM EXIT
+
gen_cpio_list | \
gen_dir_ents | \
sort -u | \
gen_depfile 3>initramfs.d | \
./gen_init_cpio -t 0 - | \
-$compressor > initramfs.img
+$compressor > $outfile
+
+trap '' EXIT
diff --git a/unlock b/unlock
index 50d282b..42e30d2 100644
--- a/unlock
+++ b/unlock
@@ -1,5 +1,5 @@
#!/bin/sh
-root=$(findfs UUID=26748575-d7a7-418b-8f68-21be7c937500) || exit
+root=$(findfs UUID=ec8fb072-1200-4275-9494-f6f869187806) || exit
cryptsetup open --allow-discards "$root" root || exit
pkill cryptsetup