detached c37a8f5

build(images): add the guest kernel config, the Ubuntu 24.04 image and build scripts

commit
c37a8f59dea3af5ee1a1c68ce0b802faca45c179
author
brice · · 2026-10-12 15:35 UTC
parent
885c03f
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
6 files · +361 -0
A images/kernel/config-6.18 +163 -0
@@ -0,0 +1,163 @@
1+# Minimal Linux 6.18 guest configuration for Firecracker micro-VMs running
2+# Docker (ermite-runner). This is a configuration *fragment*: scripts/build-kernel.sh
3+# merges it over `make tinyconfig` and resolves dependencies with olddefconfig,
4+# then fails if an option listed here did not survive. Per-architecture options
5+# are in config-6.18.x86_64 and config-6.18.arm64, merged after this file.
6+
7+# --- Core ---
8+CONFIG_64BIT=y
9+CONFIG_SMP=y
10+CONFIG_NR_CPUS=64
11+CONFIG_EXPERT=y
12+CONFIG_PRINTK=y
13+CONFIG_PRINTK_TIME=y
14+CONFIG_KALLSYMS=y
15+CONFIG_BUG=y
16+CONFIG_TTY=y
17+CONFIG_UNIX98_PTYS=y
18+CONFIG_MULTIUSER=y
19+CONFIG_FUTEX=y
20+CONFIG_EPOLL=y
21+CONFIG_EVENTFD=y
22+CONFIG_SIGNALFD=y
23+CONFIG_TIMERFD=y
24+CONFIG_AIO=y
25+CONFIG_FHANDLE=y
26+CONFIG_FILE_LOCKING=y
27+CONFIG_ADVISE_SYSCALLS=y
28+CONFIG_MEMBARRIER=y
29+CONFIG_POSIX_TIMERS=y
30+CONFIG_HIGH_RES_TIMERS=y
31+CONFIG_NO_HZ_IDLE=y
32+CONFIG_BINFMT_ELF=y
33+CONFIG_BINFMT_SCRIPT=y
34+CONFIG_SYSVIPC=y
35+CONFIG_POSIX_MQUEUE=y
36+CONFIG_KEYS=y
37+CONFIG_SECCOMP=y
38+CONFIG_SECCOMP_FILTER=y
39+CONFIG_BPF_SYSCALL=y
40+CONFIG_BPF_JIT=y
41+CONFIG_INOTIFY_USER=y
42+CONFIG_FANOTIFY=y
43+CONFIG_SHMEM=y
44+CONFIG_MODULES=n
45+
46+# --- Guest basics (x86-64 only options live in config-6.18.x86_64) ---
47+CONFIG_SERIAL_8250=y
48+CONFIG_SERIAL_8250_CONSOLE=y
49+CONFIG_HW_RANDOM=y
50+CONFIG_HW_RANDOM_VIRTIO=y
51+
52+# --- virtio (Firecracker uses virtio-mmio) ---
53+CONFIG_VIRTIO_MENU=y
54+CONFIG_VIRTIO=y
55+CONFIG_VIRTIO_MMIO=y
56+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
57+CONFIG_VIRTIO_BLK=y
58+CONFIG_VIRTIO_NET=y
59+CONFIG_VSOCKETS=y
60+CONFIG_VIRTIO_VSOCKETS=y
61+
62+# --- Block, filesystems ---
63+CONFIG_BLOCK=y
64+CONFIG_BLK_DEV=y
65+CONFIG_PROC_FS=y
66+CONFIG_PROC_SYSCTL=y
67+CONFIG_SYSFS=y
68+CONFIG_TMPFS=y
69+CONFIG_TMPFS_POSIX_ACL=y
70+CONFIG_TMPFS_XATTR=y
71+CONFIG_DEVTMPFS=y
72+CONFIG_DEVTMPFS_MOUNT=y
73+CONFIG_SYSCTL=y
74+CONFIG_EXT4_FS=y
75+CONFIG_EXT4_FS_POSIX_ACL=y
76+CONFIG_EXT4_FS_SECURITY=y
77+CONFIG_OVERLAY_FS=y
78+CONFIG_FUSE_FS=y
79+CONFIG_CRYPTO=y
80+CONFIG_CRYPTO_CRC32C=y
81+
82+# --- Namespaces and cgroups v2 (Docker, runc) ---
83+CONFIG_NAMESPACES=y
84+CONFIG_UTS_NS=y
85+CONFIG_IPC_NS=y
86+CONFIG_USER_NS=y
87+CONFIG_PID_NS=y
88+CONFIG_NET_NS=y
89+CONFIG_TIME_NS=y
90+CONFIG_CGROUPS=y
91+CONFIG_CGROUP_PIDS=y
92+CONFIG_CGROUP_SCHED=y
93+CONFIG_FAIR_GROUP_SCHED=y
94+CONFIG_CFS_BANDWIDTH=y
95+CONFIG_CPUSETS=y
96+CONFIG_MEMCG=y
97+CONFIG_BLK_CGROUP=y
98+CONFIG_CGROUP_DEVICE=y
99+CONFIG_CGROUP_FREEZER=y
100+CONFIG_CGROUP_CPUACCT=y
101+CONFIG_CGROUP_BPF=y
102+CONFIG_HUGETLBFS=y
103+CONFIG_HUGETLB_PAGE=y
104+CONFIG_CGROUP_HUGETLB=y
105+
106+# --- Network ---
107+CONFIG_NET=y
108+CONFIG_NETDEVICES=y
109+CONFIG_NET_CORE=y
110+CONFIG_INET=y
111+CONFIG_IP_PNP=y
112+CONFIG_IPV6=y
113+CONFIG_UNIX=y
114+CONFIG_PACKET=y
115+CONFIG_TUN=y
116+CONFIG_VETH=y
117+CONFIG_BRIDGE=y
118+CONFIG_BRIDGE_NETFILTER=y
119+CONFIG_VLAN_8021Q=y
120+CONFIG_INET_DIAG=y
121+CONFIG_INET_UDP_DIAG=y
122+CONFIG_UNIX_DIAG=y
123+CONFIG_NETLINK_DIAG=y
124+CONFIG_SYN_COOKIES=y
125+
126+# --- netfilter: nftables, iptables compatibility, NAT ---
127+CONFIG_NETFILTER=y
128+CONFIG_NETFILTER_ADVANCED=y
129+CONFIG_NETFILTER_NETLINK=y
130+CONFIG_NF_CONNTRACK=y
131+CONFIG_NF_NAT=y
132+CONFIG_NF_TABLES=y
133+CONFIG_NF_TABLES_INET=y
134+CONFIG_NF_TABLES_IPV4=y
135+CONFIG_NFT_CT=y
136+CONFIG_NFT_NAT=y
137+CONFIG_NFT_MASQ=y
138+CONFIG_NFT_REJECT=y
139+CONFIG_NFT_LIMIT=y
140+CONFIG_NFT_LOG=y
141+CONFIG_NFT_COMPAT=y
142+CONFIG_NETFILTER_XTABLES=y
143+CONFIG_NETFILTER_XTABLES_LEGACY=y
144+CONFIG_NETFILTER_XT_NAT=y
145+CONFIG_NETFILTER_XT_MARK=y
146+CONFIG_NETFILTER_XT_CONNMARK=y
147+CONFIG_NETFILTER_XT_TARGET_MASQUERADE=y
148+CONFIG_NETFILTER_XT_TARGET_MARK=y
149+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=y
150+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
151+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
152+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
153+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
154+CONFIG_NETFILTER_XT_MATCH_MARK=y
155+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
156+CONFIG_IP_NF_IPTABLES_LEGACY=y
157+CONFIG_IP_NF_IPTABLES=y
158+CONFIG_IP_NF_FILTER=y
159+CONFIG_IP_NF_MANGLE=y
160+CONFIG_IP_NF_RAW=y
161+CONFIG_IP_NF_NAT=y
162+CONFIG_IP_NF_TARGET_MASQUERADE=y
163+CONFIG_IP_NF_TARGET_REJECT=y
@@ -0,0 +1,163 @@
1+# Minimal Linux 6.18 guest configuration for Firecracker micro-VMs running
2+# Docker (ermite-runner). This is a configuration *fragment*: scripts/build-kernel.sh
3+# merges it over `make tinyconfig` and resolves dependencies with olddefconfig,
4+# then fails if an option listed here did not survive. Per-architecture options
5+# are in config-6.18.x86_64 and config-6.18.arm64, merged after this file.
6+
7+# --- Core ---
8+CONFIG_64BIT=y
9+CONFIG_SMP=y
10+CONFIG_NR_CPUS=64
11+CONFIG_EXPERT=y
12+CONFIG_PRINTK=y
13+CONFIG_PRINTK_TIME=y
14+CONFIG_KALLSYMS=y
15+CONFIG_BUG=y
16+CONFIG_TTY=y
17+CONFIG_UNIX98_PTYS=y
18+CONFIG_MULTIUSER=y
19+CONFIG_FUTEX=y
20+CONFIG_EPOLL=y
21+CONFIG_EVENTFD=y
22+CONFIG_SIGNALFD=y
23+CONFIG_TIMERFD=y
24+CONFIG_AIO=y
25+CONFIG_FHANDLE=y
26+CONFIG_FILE_LOCKING=y
27+CONFIG_ADVISE_SYSCALLS=y
28+CONFIG_MEMBARRIER=y
29+CONFIG_POSIX_TIMERS=y
30+CONFIG_HIGH_RES_TIMERS=y
31+CONFIG_NO_HZ_IDLE=y
32+CONFIG_BINFMT_ELF=y
33+CONFIG_BINFMT_SCRIPT=y
34+CONFIG_SYSVIPC=y
35+CONFIG_POSIX_MQUEUE=y
36+CONFIG_KEYS=y
37+CONFIG_SECCOMP=y
38+CONFIG_SECCOMP_FILTER=y
39+CONFIG_BPF_SYSCALL=y
40+CONFIG_BPF_JIT=y
41+CONFIG_INOTIFY_USER=y
42+CONFIG_FANOTIFY=y
43+CONFIG_SHMEM=y
44+CONFIG_MODULES=n
45+
46+# --- Guest basics (x86-64 only options live in config-6.18.x86_64) ---
47+CONFIG_SERIAL_8250=y
48+CONFIG_SERIAL_8250_CONSOLE=y
49+CONFIG_HW_RANDOM=y
50+CONFIG_HW_RANDOM_VIRTIO=y
51+
52+# --- virtio (Firecracker uses virtio-mmio) ---
53+CONFIG_VIRTIO_MENU=y
54+CONFIG_VIRTIO=y
55+CONFIG_VIRTIO_MMIO=y
56+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
57+CONFIG_VIRTIO_BLK=y
58+CONFIG_VIRTIO_NET=y
59+CONFIG_VSOCKETS=y
60+CONFIG_VIRTIO_VSOCKETS=y
61+
62+# --- Block, filesystems ---
63+CONFIG_BLOCK=y
64+CONFIG_BLK_DEV=y
65+CONFIG_PROC_FS=y
66+CONFIG_PROC_SYSCTL=y
67+CONFIG_SYSFS=y
68+CONFIG_TMPFS=y
69+CONFIG_TMPFS_POSIX_ACL=y
70+CONFIG_TMPFS_XATTR=y
71+CONFIG_DEVTMPFS=y
72+CONFIG_DEVTMPFS_MOUNT=y
73+CONFIG_SYSCTL=y
74+CONFIG_EXT4_FS=y
75+CONFIG_EXT4_FS_POSIX_ACL=y
76+CONFIG_EXT4_FS_SECURITY=y
77+CONFIG_OVERLAY_FS=y
78+CONFIG_FUSE_FS=y
79+CONFIG_CRYPTO=y
80+CONFIG_CRYPTO_CRC32C=y
81+
82+# --- Namespaces and cgroups v2 (Docker, runc) ---
83+CONFIG_NAMESPACES=y
84+CONFIG_UTS_NS=y
85+CONFIG_IPC_NS=y
86+CONFIG_USER_NS=y
87+CONFIG_PID_NS=y
88+CONFIG_NET_NS=y
89+CONFIG_TIME_NS=y
90+CONFIG_CGROUPS=y
91+CONFIG_CGROUP_PIDS=y
92+CONFIG_CGROUP_SCHED=y
93+CONFIG_FAIR_GROUP_SCHED=y
94+CONFIG_CFS_BANDWIDTH=y
95+CONFIG_CPUSETS=y
96+CONFIG_MEMCG=y
97+CONFIG_BLK_CGROUP=y
98+CONFIG_CGROUP_DEVICE=y
99+CONFIG_CGROUP_FREEZER=y
100+CONFIG_CGROUP_CPUACCT=y
101+CONFIG_CGROUP_BPF=y
102+CONFIG_HUGETLBFS=y
103+CONFIG_HUGETLB_PAGE=y
104+CONFIG_CGROUP_HUGETLB=y
105+
106+# --- Network ---
107+CONFIG_NET=y
108+CONFIG_NETDEVICES=y
109+CONFIG_NET_CORE=y
110+CONFIG_INET=y
111+CONFIG_IP_PNP=y
112+CONFIG_IPV6=y
113+CONFIG_UNIX=y
114+CONFIG_PACKET=y
115+CONFIG_TUN=y
116+CONFIG_VETH=y
117+CONFIG_BRIDGE=y
118+CONFIG_BRIDGE_NETFILTER=y
119+CONFIG_VLAN_8021Q=y
120+CONFIG_INET_DIAG=y
121+CONFIG_INET_UDP_DIAG=y
122+CONFIG_UNIX_DIAG=y
123+CONFIG_NETLINK_DIAG=y
124+CONFIG_SYN_COOKIES=y
125+
126+# --- netfilter: nftables, iptables compatibility, NAT ---
127+CONFIG_NETFILTER=y
128+CONFIG_NETFILTER_ADVANCED=y
129+CONFIG_NETFILTER_NETLINK=y
130+CONFIG_NF_CONNTRACK=y
131+CONFIG_NF_NAT=y
132+CONFIG_NF_TABLES=y
133+CONFIG_NF_TABLES_INET=y
134+CONFIG_NF_TABLES_IPV4=y
135+CONFIG_NFT_CT=y
136+CONFIG_NFT_NAT=y
137+CONFIG_NFT_MASQ=y
138+CONFIG_NFT_REJECT=y
139+CONFIG_NFT_LIMIT=y
140+CONFIG_NFT_LOG=y
141+CONFIG_NFT_COMPAT=y
142+CONFIG_NETFILTER_XTABLES=y
143+CONFIG_NETFILTER_XTABLES_LEGACY=y
144+CONFIG_NETFILTER_XT_NAT=y
145+CONFIG_NETFILTER_XT_MARK=y
146+CONFIG_NETFILTER_XT_CONNMARK=y
147+CONFIG_NETFILTER_XT_TARGET_MASQUERADE=y
148+CONFIG_NETFILTER_XT_TARGET_MARK=y
149+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=y
150+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
151+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
152+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
153+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
154+CONFIG_NETFILTER_XT_MATCH_MARK=y
155+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
156+CONFIG_IP_NF_IPTABLES_LEGACY=y
157+CONFIG_IP_NF_IPTABLES=y
158+CONFIG_IP_NF_FILTER=y
159+CONFIG_IP_NF_MANGLE=y
160+CONFIG_IP_NF_RAW=y
161+CONFIG_IP_NF_NAT=y
162+CONFIG_IP_NF_TARGET_MASQUERADE=y
163+CONFIG_IP_NF_TARGET_REJECT=y
A images/kernel/config-6.18.arm64 +11 -0
@@ -0,0 +1,11 @@
1+# arm64 specific guest options, merged after config-6.18. Not exercised in CI-1
2+# (no arm64 host); kept so that the build is reproducible there.
3+CONFIG_ARM64=y
4+CONFIG_ARM64_VA_BITS_48=y
5+CONFIG_ARM_GIC_V3=y
6+CONFIG_ARM_PSCI_FW=y
7+CONFIG_ARM_ARCH_TIMER=y
8+CONFIG_SERIAL_AMBA_PL011=y
9+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
10+CONFIG_RTC_CLASS=y
11+CONFIG_RTC_DRV_PL031=y
@@ -0,0 +1,11 @@
1+# arm64 specific guest options, merged after config-6.18. Not exercised in CI-1
2+# (no arm64 host); kept so that the build is reproducible there.
3+CONFIG_ARM64=y
4+CONFIG_ARM64_VA_BITS_48=y
5+CONFIG_ARM_GIC_V3=y
6+CONFIG_ARM_PSCI_FW=y
7+CONFIG_ARM_ARCH_TIMER=y
8+CONFIG_SERIAL_AMBA_PL011=y
9+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
10+CONFIG_RTC_CLASS=y
11+CONFIG_RTC_DRV_PL031=y
A images/kernel/config-6.18.x86_64 +11 -0
@@ -0,0 +1,11 @@
1+# x86-64 specific guest options, merged after config-6.18.
2+CONFIG_HYPERVISOR_GUEST=y
3+CONFIG_PARAVIRT=y
4+CONFIG_KVM_GUEST=y
5+CONFIG_IA32_EMULATION=y
6+CONFIG_SERIO=y
7+CONFIG_SERIO_I8042=y
8+CONFIG_ACPI=y
9+CONFIG_X86_MPPARSE=y
10+CONFIG_X86_LOCAL_APIC=y
11+CONFIG_X86_IO_APIC=y
@@ -0,0 +1,11 @@
1+# x86-64 specific guest options, merged after config-6.18.
2+CONFIG_HYPERVISOR_GUEST=y
3+CONFIG_PARAVIRT=y
4+CONFIG_KVM_GUEST=y
5+CONFIG_IA32_EMULATION=y
6+CONFIG_SERIO=y
7+CONFIG_SERIO_I8042=y
8+CONFIG_ACPI=y
9+CONFIG_X86_MPPARSE=y
10+CONFIG_X86_LOCAL_APIC=y
11+CONFIG_X86_IO_APIC=y
A images/ubuntu-24.04/Dockerfile +43 -0
@@ -0,0 +1,43 @@
1+# SPDX-License-Identifier: MIT
2+#
3+# ermite-runner-ubuntu-24.04: the minimal CI-1 runner image. The same
4+# filesystem is used as an OCI image (container isolation) and exported to an
5+# ext4 base image (vm isolation) by scripts/build-image.sh. It holds the OS
6+# only: the runner executable is attached by the host at start (never baked
7+# in), so a runner upgrade does not need an image rebuild.
8+FROM ubuntu:24.04
9+
10+ARG DEBIAN_FRONTEND=noninteractive
11+
12+RUN apt-get update \
13+ && apt-get install -y --no-install-recommends \
14+ bash build-essential ca-certificates curl e2fsprogs git gnupg iproute2 \
15+ iptables jq kmod procps python3 sudo tzdata unzip xz-utils zip \
16+ && rm -rf /var/lib/apt/lists/*
17+
18+# Docker Engine from Docker's apt repository (the job gets its own daemon).
19+RUN install -m 0755 -d /etc/apt/keyrings \
20+ && curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc \
21+ && chmod a+r /etc/apt/keyrings/docker.asc \
22+ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" \
23+ > /etc/apt/sources.list.d/docker.list \
24+ && apt-get update \
25+ && apt-get install -y --no-install-recommends \
26+ docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \
27+ && rm -rf /var/lib/apt/lists/*
28+
29+# Like GitHub-hosted runners: user "runner" (uid 1001), passwordless sudo,
30+# member of "docker", with the job layout directories.
31+RUN useradd --create-home --uid 1001 --shell /bin/bash runner \
32+ && usermod -aG docker runner \
33+ && echo 'runner ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/runner \
34+ && chmod 0440 /etc/sudoers.d/runner \
35+ && mkdir -p /home/runner/work /opt/hostedtoolcache /opt/ermite \
36+ && chown -R runner:runner /home/runner /opt/hostedtoolcache
37+
38+ENV RUNNER_TOOL_CACHE=/opt/hostedtoolcache \
39+ LANG=C.UTF-8
40+
41+# The runner executable is bind-mounted (container) or provided by the init
42+# disk (vm) here; its init subcommand starts the job's own Docker daemon.
43+ENTRYPOINT ["/opt/ermite/ermite-runner", "init"]
@@ -0,0 +1,43 @@
1+# SPDX-License-Identifier: MIT
2+#
3+# ermite-runner-ubuntu-24.04: the minimal CI-1 runner image. The same
4+# filesystem is used as an OCI image (container isolation) and exported to an
5+# ext4 base image (vm isolation) by scripts/build-image.sh. It holds the OS
6+# only: the runner executable is attached by the host at start (never baked
7+# in), so a runner upgrade does not need an image rebuild.
8+FROM ubuntu:24.04
9+
10+ARG DEBIAN_FRONTEND=noninteractive
11+
12+RUN apt-get update \
13+ && apt-get install -y --no-install-recommends \
14+ bash build-essential ca-certificates curl e2fsprogs git gnupg iproute2 \
15+ iptables jq kmod procps python3 sudo tzdata unzip xz-utils zip \
16+ && rm -rf /var/lib/apt/lists/*
17+
18+# Docker Engine from Docker's apt repository (the job gets its own daemon).
19+RUN install -m 0755 -d /etc/apt/keyrings \
20+ && curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc \
21+ && chmod a+r /etc/apt/keyrings/docker.asc \
22+ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" \
23+ > /etc/apt/sources.list.d/docker.list \
24+ && apt-get update \
25+ && apt-get install -y --no-install-recommends \
26+ docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \
27+ && rm -rf /var/lib/apt/lists/*
28+
29+# Like GitHub-hosted runners: user "runner" (uid 1001), passwordless sudo,
30+# member of "docker", with the job layout directories.
31+RUN useradd --create-home --uid 1001 --shell /bin/bash runner \
32+ && usermod -aG docker runner \
33+ && echo 'runner ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/runner \
34+ && chmod 0440 /etc/sudoers.d/runner \
35+ && mkdir -p /home/runner/work /opt/hostedtoolcache /opt/ermite \
36+ && chown -R runner:runner /home/runner /opt/hostedtoolcache
37+
38+ENV RUNNER_TOOL_CACHE=/opt/hostedtoolcache \
39+ LANG=C.UTF-8
40+
41+# The runner executable is bind-mounted (container) or provided by the init
42+# disk (vm) here; its init subcommand starts the job's own Docker daemon.
43+ENTRYPOINT ["/opt/ermite/ermite-runner", "init"]
A scripts/build-image.sh +56 -0
@@ -0,0 +1,56 @@
1+#!/usr/bin/env bash
2+# SPDX-License-Identifier: MIT
3+#
4+# Build the ermite-runner-ubuntu-24.04 image as an OCI image (container
5+# isolation) and as a sparse ext4 base image (vm isolation). No root needed:
6+# the OCI build uses docker or podman (rootless is fine), the ext4 image is
7+# written by `mkfs.ext4 -d` from the exported rootfs tarball.
8+#
9+# scripts/build-image.sh [OUT_DIR]
10+#
11+# Environment:
12+# ENGINE docker or podman (default: first found)
13+# IMAGE_TAG OCI tag (default ermite-runner-ubuntu-24.04:dev)
14+# EXT4_SLACK free space added to the base image in MiB (default 512)
15+#
16+# Output: OUT_DIR/base.ext4 (read-only shared base disk; its UUID and size are
17+# stable per build) and the OCI image IMAGE_TAG in the engine's store.
18+set -euo pipefail
19+
20+root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
21+out=${1:-$root/tmp/image}
22+tag=${IMAGE_TAG:-ermite-runner-ubuntu-24.04:dev}
23+slack=${EXT4_SLACK:-512}
24+engine=${ENGINE:-}
25+
26+if [ -z "$engine" ]; then
27+ for e in docker podman; do
28+ if command -v "$e" >/dev/null 2>&1; then engine=$e; break; fi
29+ done
30+fi
31+[ -n "$engine" ] || { echo "need docker or podman" >&2; exit 1; }
32+command -v mkfs.ext4 >/dev/null || { echo "need mkfs.ext4 (e2fsprogs >= 1.47.1 for tarball input)" >&2; exit 1; }
33+
34+mkdir -p "$out"
35+out=$(cd "$out" && pwd)
36+"$engine" build -t "$tag" "$root/images/ubuntu-24.04"
37+
38+cid=$("$engine" create "$tag")
39+tmp=$(mktemp -d)
40+cleanup() { "$engine" rm -f "$cid" >/dev/null 2>&1 || true; rm -rf "$tmp"; }
41+trap cleanup EXIT
42+
43+"$engine" export "$cid" > "$tmp/rootfs.tar"
44+bytes=$(stat -c %s "$tmp/rootfs.tar")
45+# ext4 metadata overhead is about 5 %; the slack leaves room for the guest's
46+# own writes into the (read-only mounted) base only when someone remounts it.
47+mib=$(( bytes / 1024 / 1024 * 110 / 100 + slack ))
48+
49+img="$out/base.ext4.part"
50+rm -f "$img"
51+truncate -s "${mib}M" "$img"
52+# No journal: the base is mounted read-only and shared between VMs.
53+mkfs.ext4 -q -F -L ermite-base -O ^has_journal -E lazy_itable_init=1,nodiscard \
54+ -d "$tmp/rootfs.tar" "$img"
55+mv "$img" "$out/base.ext4"
56+echo "base image: $out/base.ext4 (${mib} MiB sparse), OCI image: $tag"
@@ -0,0 +1,56 @@
1+#!/usr/bin/env bash
2+# SPDX-License-Identifier: MIT
3+#
4+# Build the ermite-runner-ubuntu-24.04 image as an OCI image (container
5+# isolation) and as a sparse ext4 base image (vm isolation). No root needed:
6+# the OCI build uses docker or podman (rootless is fine), the ext4 image is
7+# written by `mkfs.ext4 -d` from the exported rootfs tarball.
8+#
9+# scripts/build-image.sh [OUT_DIR]
10+#
11+# Environment:
12+# ENGINE docker or podman (default: first found)
13+# IMAGE_TAG OCI tag (default ermite-runner-ubuntu-24.04:dev)
14+# EXT4_SLACK free space added to the base image in MiB (default 512)
15+#
16+# Output: OUT_DIR/base.ext4 (read-only shared base disk; its UUID and size are
17+# stable per build) and the OCI image IMAGE_TAG in the engine's store.
18+set -euo pipefail
19+
20+root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
21+out=${1:-$root/tmp/image}
22+tag=${IMAGE_TAG:-ermite-runner-ubuntu-24.04:dev}
23+slack=${EXT4_SLACK:-512}
24+engine=${ENGINE:-}
25+
26+if [ -z "$engine" ]; then
27+ for e in docker podman; do
28+ if command -v "$e" >/dev/null 2>&1; then engine=$e; break; fi
29+ done
30+fi
31+[ -n "$engine" ] || { echo "need docker or podman" >&2; exit 1; }
32+command -v mkfs.ext4 >/dev/null || { echo "need mkfs.ext4 (e2fsprogs >= 1.47.1 for tarball input)" >&2; exit 1; }
33+
34+mkdir -p "$out"
35+out=$(cd "$out" && pwd)
36+"$engine" build -t "$tag" "$root/images/ubuntu-24.04"
37+
38+cid=$("$engine" create "$tag")
39+tmp=$(mktemp -d)
40+cleanup() { "$engine" rm -f "$cid" >/dev/null 2>&1 || true; rm -rf "$tmp"; }
41+trap cleanup EXIT
42+
43+"$engine" export "$cid" > "$tmp/rootfs.tar"
44+bytes=$(stat -c %s "$tmp/rootfs.tar")
45+# ext4 metadata overhead is about 5 %; the slack leaves room for the guest's
46+# own writes into the (read-only mounted) base only when someone remounts it.
47+mib=$(( bytes / 1024 / 1024 * 110 / 100 + slack ))
48+
49+img="$out/base.ext4.part"
50+rm -f "$img"
51+truncate -s "${mib}M" "$img"
52+# No journal: the base is mounted read-only and shared between VMs.
53+mkfs.ext4 -q -F -L ermite-base -O ^has_journal -E lazy_itable_init=1,nodiscard \
54+ -d "$tmp/rootfs.tar" "$img"
55+mv "$img" "$out/base.ext4"
56+echo "base image: $out/base.ext4 (${mib} MiB sparse), OCI image: $tag"
A scripts/build-kernel.sh +77 -0
@@ -0,0 +1,77 @@
1+#!/usr/bin/env bash
2+# SPDX-License-Identifier: MIT
3+#
4+# Build the Firecracker guest kernel (Linux 6.18 LTS) from kernel.org.
5+#
6+# scripts/build-kernel.sh [OUT_DIR]
7+#
8+# Environment:
9+# KERNEL_VERSION version to build (default 6.18.56)
10+# ARCH_NAME x86_64 (default: uname -m) or arm64 (aarch64)
11+# WORK_DIR download and build directory (default tmp/kernel, gitignored)
12+# JOBS make parallelism (default: nproc)
13+#
14+# Output: OUT_DIR/vmlinux (x86_64 ELF, accepted by Firecracker) or
15+# OUT_DIR/Image (arm64), plus OUT_DIR/kernel.config. No root needed. The tarball
16+# is verified against the sha256sums.asc published next to it on kernel.org
17+# (integrity over TLS; the PGP signature is not checked, see README).
18+set -euo pipefail
19+
20+root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
21+version=${KERNEL_VERSION:-6.18.56}
22+major=${version%%.*}
23+work=${WORK_DIR:-$root/tmp/kernel}
24+out=${1:-$root/tmp/image}
25+jobs=${JOBS:-$(nproc)}
26+arch_name=${ARCH_NAME:-$(uname -m)}
27+
28+case "$arch_name" in
29+ x86_64|amd64) karch=x86; arch_frag=x86_64; target=vmlinux; artifact=vmlinux ;;
30+ aarch64|arm64) karch=arm64; arch_frag=arm64; target=Image; artifact=arch/arm64/boot/Image ;;
31+ *) echo "unsupported architecture: $arch_name" >&2; exit 2 ;;
32+esac
33+
34+mkdir -p "$work" "$out"
35+work=$(cd "$work" && pwd)
36+out=$(cd "$out" && pwd)
37+tarball="linux-$version.tar.xz"
38+base="https://cdn.kernel.org/pub/linux/kernel/v${major}.x"
39+
40+if [ ! -f "$work/$tarball" ]; then
41+ curl -fsSL -o "$work/$tarball.part" "$base/$tarball"
42+ mv "$work/$tarball.part" "$work/$tarball"
43+fi
44+if [ ! -f "$work/sha256sums.asc" ] || ! grep -q " $tarball\$" "$work/sha256sums.asc"; then
45+ curl -fsSL -o "$work/sha256sums.asc" "$base/sha256sums.asc"
46+fi
47+want=$(grep " $tarball\$" "$work/sha256sums.asc" | awk '{print $1}' | head -n1)
48+have=$(sha256sum "$work/$tarball" | awk '{print $1}')
49+if [ -z "$want" ] || [ "$want" != "$have" ]; then
50+ echo "checksum mismatch for $tarball (want '$want', have '$have')" >&2
51+ exit 1
52+fi
53+
54+src="$work/linux-$version"
55+[ -d "$src" ] || tar -C "$work" -xf "$work/$tarball"
56+
57+cd "$src"
58+export ARCH=$karch
59+make tinyconfig >/dev/null
60+scripts/kconfig/merge_config.sh -m .config \
61+ "$root/images/kernel/config-6.18" "$root/images/kernel/config-6.18.$arch_frag" >/dev/null
62+make olddefconfig >/dev/null
63+
64+# Fail if an option of the fragments was dropped by a missing dependency.
65+missing=0
66+while IFS== read -r key val; do
67+ if grep -q "^$key=$val\$" .config; then continue; fi
68+ if [ "$val" = n ] && ! grep -q "^$key=" .config; then continue; fi
69+ echo "kernel option not applied: $key=$val" >&2
70+ missing=1
71+done < <(cat "$root/images/kernel/config-6.18" "$root/images/kernel/config-6.18.$arch_frag" | grep -E '^CONFIG_[A-Z0-9_]+=')
72+[ "$missing" = 0 ] || exit 1
73+
74+make -j"$jobs" "$target"
75+cp "$artifact" "$out/$(basename "$artifact")"
76+cp .config "$out/kernel.config"
77+echo "kernel: $out/$(basename "$artifact")"
@@ -0,0 +1,77 @@
1+#!/usr/bin/env bash
2+# SPDX-License-Identifier: MIT
3+#
4+# Build the Firecracker guest kernel (Linux 6.18 LTS) from kernel.org.
5+#
6+# scripts/build-kernel.sh [OUT_DIR]
7+#
8+# Environment:
9+# KERNEL_VERSION version to build (default 6.18.56)
10+# ARCH_NAME x86_64 (default: uname -m) or arm64 (aarch64)
11+# WORK_DIR download and build directory (default tmp/kernel, gitignored)
12+# JOBS make parallelism (default: nproc)
13+#
14+# Output: OUT_DIR/vmlinux (x86_64 ELF, accepted by Firecracker) or
15+# OUT_DIR/Image (arm64), plus OUT_DIR/kernel.config. No root needed. The tarball
16+# is verified against the sha256sums.asc published next to it on kernel.org
17+# (integrity over TLS; the PGP signature is not checked, see README).
18+set -euo pipefail
19+
20+root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
21+version=${KERNEL_VERSION:-6.18.56}
22+major=${version%%.*}
23+work=${WORK_DIR:-$root/tmp/kernel}
24+out=${1:-$root/tmp/image}
25+jobs=${JOBS:-$(nproc)}
26+arch_name=${ARCH_NAME:-$(uname -m)}
27+
28+case "$arch_name" in
29+ x86_64|amd64) karch=x86; arch_frag=x86_64; target=vmlinux; artifact=vmlinux ;;
30+ aarch64|arm64) karch=arm64; arch_frag=arm64; target=Image; artifact=arch/arm64/boot/Image ;;
31+ *) echo "unsupported architecture: $arch_name" >&2; exit 2 ;;
32+esac
33+
34+mkdir -p "$work" "$out"
35+work=$(cd "$work" && pwd)
36+out=$(cd "$out" && pwd)
37+tarball="linux-$version.tar.xz"
38+base="https://cdn.kernel.org/pub/linux/kernel/v${major}.x"
39+
40+if [ ! -f "$work/$tarball" ]; then
41+ curl -fsSL -o "$work/$tarball.part" "$base/$tarball"
42+ mv "$work/$tarball.part" "$work/$tarball"
43+fi
44+if [ ! -f "$work/sha256sums.asc" ] || ! grep -q " $tarball\$" "$work/sha256sums.asc"; then
45+ curl -fsSL -o "$work/sha256sums.asc" "$base/sha256sums.asc"
46+fi
47+want=$(grep " $tarball\$" "$work/sha256sums.asc" | awk '{print $1}' | head -n1)
48+have=$(sha256sum "$work/$tarball" | awk '{print $1}')
49+if [ -z "$want" ] || [ "$want" != "$have" ]; then
50+ echo "checksum mismatch for $tarball (want '$want', have '$have')" >&2
51+ exit 1
52+fi
53+
54+src="$work/linux-$version"
55+[ -d "$src" ] || tar -C "$work" -xf "$work/$tarball"
56+
57+cd "$src"
58+export ARCH=$karch
59+make tinyconfig >/dev/null
60+scripts/kconfig/merge_config.sh -m .config \
61+ "$root/images/kernel/config-6.18" "$root/images/kernel/config-6.18.$arch_frag" >/dev/null
62+make olddefconfig >/dev/null
63+
64+# Fail if an option of the fragments was dropped by a missing dependency.
65+missing=0
66+while IFS== read -r key val; do
67+ if grep -q "^$key=$val\$" .config; then continue; fi
68+ if [ "$val" = n ] && ! grep -q "^$key=" .config; then continue; fi
69+ echo "kernel option not applied: $key=$val" >&2
70+ missing=1
71+done < <(cat "$root/images/kernel/config-6.18" "$root/images/kernel/config-6.18.$arch_frag" | grep -E '^CONFIG_[A-Z0-9_]+=')
72+[ "$missing" = 0 ] || exit 1
73+
74+make -j"$jobs" "$target"
75+cp "$artifact" "$out/$(basename "$artifact")"
76+cp .config "$out/kernel.config"
77+echo "kernel: $out/$(basename "$artifact")"

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 11

↑↓ moveenter openesc close