summaryrefslogtreecommitdiffstats
path: root/recipes-extended
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-02-10 04:33:48 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-02-10 21:04:20 +0000
commit6f53d7763906f24d86e89da4da744421c52d591c (patch)
treef37ff082e424b1e4aaa820c8e2db07b31146f091 /recipes-extended
parenta71e7b0499c51c74686e41e7810e2f202d851ce6 (diff)
downloadmeta-virtualization-6f53d7763906f24d86e89da4da744421c52d591c.tar.gz
container-yocto-builder: add Yocto build container with systemd
Multi-layer OCI container image that can compile the Yocto Project. Three layers: systemd-base, build-tools, yocto-extras. Features CROPS-style dynamic user creation matching /workdir volume owner UID/GID. Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-extended')
-rw-r--r--recipes-extended/builder-container-config/builder-container-config_1.0.bb23
-rw-r--r--recipes-extended/builder-container-config/files/builder-entry.sh48
-rw-r--r--recipes-extended/images/container-yocto-builder.bb37
3 files changed, 108 insertions, 0 deletions
diff --git a/recipes-extended/builder-container-config/builder-container-config_1.0.bb b/recipes-extended/builder-container-config/builder-container-config_1.0.bb
new file mode 100644
index 00000000..6b023caa
--- /dev/null
+++ b/recipes-extended/builder-container-config/builder-container-config_1.0.bb
@@ -0,0 +1,23 @@
1SUMMARY = "Entrypoint and user configuration for Yocto builder container"
2DESCRIPTION = "CROPS-style entrypoint script that creates a builder user \
3 matching the /workdir mount owner, then hands off to systemd."
4LICENSE = "MIT"
5LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
6
7SRC_URI = "file://builder-entry.sh"
8
9S = "${UNPACKDIR}"
10RDEPENDS:${PN} = "bash sudo shadow"
11
12inherit allarch
13
14do_install() {
15 # Entrypoint script (CROPS-style user creation -> exec /sbin/init)
16 install -d ${D}${bindir}
17 install -m 0755 ${UNPACKDIR}/builder-entry.sh ${D}${bindir}/
18
19 # Create /workdir mount point
20 install -d ${D}/workdir
21}
22
23FILES:${PN} = "${bindir}/builder-entry.sh /workdir"
diff --git a/recipes-extended/builder-container-config/files/builder-entry.sh b/recipes-extended/builder-container-config/files/builder-entry.sh
new file mode 100644
index 00000000..a23d8dae
--- /dev/null
+++ b/recipes-extended/builder-container-config/files/builder-entry.sh
@@ -0,0 +1,48 @@
1#!/bin/bash
2# builder-entry.sh - Container entrypoint for Yocto builder
3# Creates a 'builder' user matching the /workdir owner's UID/GID,
4# then exec's /sbin/init (systemd).
5#
6# Usage:
7# docker run --privileged -v /home/user/yocto:/workdir builder-image
8# docker run --privileged -e BUILDER_UID=1000 -e BUILDER_GID=1000 builder-image
9
10WORKDIR="/workdir"
11DEFAULT_UID=1000
12DEFAULT_GID=1000
13
14# Determine UID/GID
15if [ -n "$BUILDER_UID" ] && [ -n "$BUILDER_GID" ]; then
16 TARGET_UID="$BUILDER_UID"
17 TARGET_GID="$BUILDER_GID"
18elif [ -d "$WORKDIR" ] && [ "$(stat -c %u "$WORKDIR")" != "0" ]; then
19 TARGET_UID=$(stat -c %u "$WORKDIR")
20 TARGET_GID=$(stat -c %g "$WORKDIR")
21else
22 TARGET_UID=$DEFAULT_UID
23 TARGET_GID=$DEFAULT_GID
24fi
25
26# Refuse UID/GID 0 (root)
27[ "$TARGET_UID" = "0" ] && TARGET_UID=$DEFAULT_UID
28[ "$TARGET_GID" = "0" ] && TARGET_GID=$DEFAULT_GID
29
30# Create group and user if they don't exist
31if ! getent group builder >/dev/null 2>&1; then
32 groupadd -g "$TARGET_GID" builder 2>/dev/null || groupadd builder
33fi
34if ! getent passwd builder >/dev/null 2>&1; then
35 useradd -m -u "$TARGET_UID" -g builder -s /bin/bash builder
36fi
37
38# Ensure /workdir is accessible
39[ -d "$WORKDIR" ] && chown builder:builder "$WORKDIR"
40
41# Grant passwordless sudo
42if [ -d /etc/sudoers.d ]; then
43 echo "builder ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/builder
44 chmod 0440 /etc/sudoers.d/builder
45fi
46
47# Hand off to systemd
48exec /sbin/init "$@"
diff --git a/recipes-extended/images/container-yocto-builder.bb b/recipes-extended/images/container-yocto-builder.bb
new file mode 100644
index 00000000..0dba4c31
--- /dev/null
+++ b/recipes-extended/images/container-yocto-builder.bb
@@ -0,0 +1,37 @@
1SUMMARY = "Yocto Project builder container with systemd"
2DESCRIPTION = "A self-hosting Yocto build container. Includes compiler \
3 toolchain, Python 3, Git, and all tools needed to compile the Yocto \
4 Project. Uses systemd init and supports CROPS-style dynamic user \
5 creation for volume-mounted builds."
6LICENSE = "MIT"
7LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
8
9IMAGE_FSTYPES = "container oci"
10inherit image
11inherit image-oci
12
13# Multi-layer OCI image
14OCI_LAYER_MODE = "multi"
15OCI_LAYERS = "\
16 systemd-base:packages:packagegroup-yocto-builder-base \
17 build-tools:packages:packagegroup-yocto-builder-toolchain \
18 yocto-extras:packages:packagegroup-yocto-builder-extras \
19"
20
21# Entrypoint: user setup script -> systemd
22OCI_IMAGE_ENTRYPOINT = "/usr/bin/builder-entry.sh"
23
24# OCI metadata
25OCI_IMAGE_AUTHOR ?= "meta-virtualization"
26OCI_IMAGE_TAG ?= "latest"
27
28# All packages listed here to trigger builds (multi-layer requirement)
29IMAGE_INSTALL = "packagegroup-yocto-builder"
30
31# No kernel needed for container
32IMAGE_CONTAINER_NO_DUMMY = "1"
33
34# Minimize image
35IMAGE_FEATURES = ""
36IMAGE_LINGUAS = ""
37NO_RECOMMENDATIONS = "1"