-
Notifications
You must be signed in to change notification settings - Fork 12
feat: Add Cocoon-compatible Debian 13 images #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # Use the latest Debian 13 (Trixie) | ||
| FROM docker.io/library/debian:13 | ||
|
|
||
| ARG TARGETARCH | ||
| ENV DEBIAN_FRONTEND=noninteractive | ||
|
|
||
| # Combined System Setup & Optimization (Single Layer) | ||
| # Install packages first so /etc/initramfs-tools/scripts/ exists, then inject the hook. | ||
| RUN --mount=type=secret,id=cocoon_overlay \ | ||
| --mount=type=secret,id=cocoon_network \ | ||
| --mount=type=secret,id=cocoon_install_agent \ | ||
| apt-get update && apt-get install -y --no-install-recommends \ | ||
| linux-image-cloud-${TARGETARCH} \ | ||
| initramfs-tools \ | ||
| # initramfs-tools only recommends busybox and --no-install-recommends skips | ||
| # recommends; without it the initramfs has only klibc-utils (no tr, and | ||
| # klibc mount rejects options after operands). | ||
| busybox \ | ||
| systemd \ | ||
| systemd-sysv \ | ||
| systemd-timesyncd \ | ||
| systemd-resolved \ | ||
| udev \ | ||
| kmod \ | ||
| iproute2 iputils-ping curl wget arping tcpdump \ | ||
| openssh-server \ | ||
| ca-certificates \ | ||
| && \ | ||
| cp /run/secrets/cocoon_overlay /etc/initramfs-tools/scripts/cocoon-overlay && \ | ||
| chmod 0755 /etc/initramfs-tools/scripts/cocoon-overlay && \ | ||
| cp /run/secrets/cocoon_network /etc/initramfs-tools/scripts/init-bottom/cocoon-network && \ | ||
| chmod 0755 /etc/initramfs-tools/scripts/init-bottom/cocoon-network && \ | ||
| # [Kernel Setup] Force critical modules and set gzip compression | ||
| printf "erofs\noverlay\next4\nvirtio_blk\nvirtio_pci\nvirtio_ring\nvirtio_net\nvsock\nvmw_vsock_virtio_transport\n" >> /etc/initramfs-tools/modules && \ | ||
| sed -i 's/^COMPRESS=.*/COMPRESS=gzip/' /etc/initramfs-tools/initramfs.conf && \ | ||
| # [Networking] IP=off prevents initramfs from running DHCP during boot. | ||
| # Kernel ip= parameters (when present) override this and still trigger ipconfig. | ||
| # Without this, IP="" (default) causes dhcpcd to run unconditionally, which | ||
| # blocks boot on --nics 0 VMs and persists DHCP leases as static configs. | ||
| sed -i '/^IP=/d' /etc/initramfs-tools/initramfs.conf && \ | ||
| echo 'IP=off' >> /etc/initramfs-tools/initramfs.conf && \ | ||
| # Regenerate initramfs inside this layer (consumes the secret script) | ||
| update-initramfs -u -k all && \ | ||
| # [Shift-Left Hacks] Neuter systemd to avoid boot-time filesystem checks | ||
| truncate -s 0 /etc/fstab && \ | ||
| systemctl mask systemd-fsck-root.service systemd-remount-fs.service systemd-fsck@.service && \ | ||
| # [Networking] Enable networkd/resolved and configure DHCP | ||
| systemctl enable systemd-networkd systemd-resolved systemd-timesyncd && \ | ||
| mkdir -p /etc/systemd/network && \ | ||
| printf "[Match]\nName=e* v*\n[Network]\nDHCP=yes\n\n[DHCPv4]\nClientIdentifier=mac\n" > /etc/systemd/network/20-wired.network && \ | ||
| # [Cocoon agent + sshd] vsock exec daemon and SSH access. | ||
| sh /run/secrets/cocoon_install_agent && \ | ||
| # [Access] Set root password | ||
| echo 'root:cocoon' | chpasswd && \ | ||
| # [Cleanup] Purge APT cache to minimize EROFS size | ||
| rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Final configuration | ||
| CMD ["/sbin/init"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Cocoon-Compatible Debian 13 Image | ||
|
|
||
| This directory builds a bootable Debian 13 (`trixie`) OCI image for Cocoon on | ||
| `linux/amd64` and `linux/arm64`. Each platform includes its matching Debian | ||
| cloud kernel and checksum-verified Cocoon agent, plus the shared initramfs, | ||
| EROFS/overlay boot hooks, systemd networking, and SSH configuration. | ||
|
|
||
| ## Build and Validate Locally | ||
|
|
||
| The validator uses Podman directly when it is available and otherwise falls | ||
| back to Docker; set `CONTAINER_ENGINE=podman` or `CONTAINER_ENGINE=docker` to | ||
| select one explicitly. Building or validating a non-native platform also | ||
| requires QEMU user emulation with the corresponding `binfmt` handler | ||
| registered; Podman Desktop normally provides this, while Linux Podman hosts | ||
| must configure it separately. | ||
|
|
||
| Build each platform with its own tag so Podman stores both architecture-specific | ||
| images locally. Run from the repository root: | ||
|
|
||
| ```bash | ||
| AMD64_IMAGE=cocoon-debian-13:local-amd64 | ||
|
|
||
| podman build \ | ||
| --platform linux/amd64 \ | ||
| --no-cache \ | ||
| --file os-image/debian/13/Dockerfile \ | ||
| --secret id=cocoon_overlay,src=os-image/debian/overlay.sh \ | ||
| --secret id=cocoon_network,src=os-image/debian/network.sh \ | ||
| --secret id=cocoon_install_agent,src=os-image/debian/install-agent.sh \ | ||
| --tag "$AMD64_IMAGE" \ | ||
| os-image/debian | ||
|
|
||
| os-image/debian/validate-image.sh "$AMD64_IMAGE" | ||
|
|
||
| ARM64_IMAGE=cocoon-debian-13:local-arm64 | ||
|
|
||
| podman build \ | ||
| --platform linux/arm64 \ | ||
| --no-cache \ | ||
| --file os-image/debian/13/Dockerfile \ | ||
| --secret id=cocoon_overlay,src=os-image/debian/overlay.sh \ | ||
| --secret id=cocoon_network,src=os-image/debian/network.sh \ | ||
| --secret id=cocoon_install_agent,src=os-image/debian/install-agent.sh \ | ||
| --tag "$ARM64_IMAGE" \ | ||
| os-image/debian | ||
|
|
||
| os-image/debian/validate-image.sh "$ARM64_IMAGE" | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #!/bin/sh | ||
| # Vendored from cocoon/os-image/ubuntu/install-agent.sh at Cocoon v0.5.9 | ||
| # (144927060c3e90dbe2f3e1a15143572c402958de). | ||
| # Install cocoon-agent (vsock exec) and sshd into a Debian/Ubuntu image. | ||
| # Caller is expected to have already installed `openssh-server` via apt | ||
| # in the same RUN, and to have curl available. | ||
| # | ||
| # Idempotent: re-running the script overwrites the binary and unit file, | ||
| # `systemctl enable` is a no-op when the symlinks are already in place. | ||
| set -eu | ||
|
|
||
| AGENT_VERSION="${COCOON_AGENT_VERSION:-0.2.0}" | ||
| ARCH="${TARGETARCH:-$(dpkg --print-architecture)}" | ||
| case "$ARCH" in | ||
| amd64) AGENT_ARCH="x86_64"; AGENT_SHA256="73dc18e588828630f0ad5f3a1b86511f315d0df1f2efcbb409e821d258d45234" ;; | ||
| arm64) AGENT_ARCH="arm64"; AGENT_SHA256="548f4729a11797c4a6abe1b65d3791606a9a4f1de5592bf2ea367c573e0f6768" ;; | ||
| *) echo "install-agent: unsupported arch '$ARCH'" >&2; exit 1 ;; | ||
| esac | ||
|
|
||
| # 1. sshd: permit root login (cocoon images use root:cocoon by default). | ||
| mkdir -p /run/sshd | ||
| sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config | ||
| systemctl enable ssh | ||
|
|
||
| # 2. cocoon-agent binary: pinned-version tarball from upstream releases. | ||
| # Per-arch SHA256 — bumping AGENT_VERSION without updating both checksums | ||
| # fails the sha256sum -c check instead of silently shipping a wrong binary. | ||
| TARBALL="cocoon-agent_${AGENT_VERSION}_Linux_${AGENT_ARCH}.tar.gz" | ||
| URL="https://github.com/cocoonstack/cocoon-agent/releases/download/v${AGENT_VERSION}/${TARBALL}" | ||
| TMP_TARBALL="$(mktemp)" | ||
| trap 'rm -f "$TMP_TARBALL"' EXIT | ||
| curl -fsSL "$URL" -o "$TMP_TARBALL" | ||
| echo "$AGENT_SHA256 $TMP_TARBALL" | sha256sum -c - | ||
| tar -xz -C /usr/local/bin/ -f "$TMP_TARBALL" cocoon-agent | ||
| chmod 0755 /usr/local/bin/cocoon-agent | ||
|
|
||
| # 3. systemd unit. Mirrors upstream packaging/cocoon-agent.service so the | ||
| # in-VM service stays in sync with what cocoon-agent is tested against. | ||
| cat > /etc/systemd/system/cocoon-agent.service <<'EOF' | ||
| [Unit] | ||
| Description=Cocoon agent (vsock command exec) | ||
| Documentation=https://github.com/cocoonstack/cocoon-agent | ||
|
|
||
| [Service] | ||
| Type=simple | ||
| User=root | ||
| Group=root | ||
| # Best-effort load — most kernels build the transport in or auto-load on | ||
| # virtio-vsock device probe; the leading dash keeps the unit alive on | ||
| # minimal kernels (e.g. ubuntu linux-image-virtual). | ||
| ExecStartPre=-/sbin/modprobe vhost_vsock | ||
| ExecStart=/usr/local/bin/cocoon-agent serve | ||
| Environment=AGENT_LOG_LEVEL=info | ||
| Restart=always | ||
| RestartSec=2s | ||
| LimitNOFILE=65536 | ||
|
|
||
| [Install] | ||
| WantedBy=multi-user.target | ||
| EOF | ||
|
|
||
| systemctl enable cocoon-agent.service |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| #!/bin/sh | ||
| # Vendored from cocoon/os-image/ubuntu/network.sh at Cocoon v0.5.9 | ||
|
ppmzhang2 marked this conversation as resolved.
|
||
| # (144927060c3e90dbe2f3e1a15143572c402958de). | ||
| # Target path: /etc/initramfs-tools/scripts/init-bottom/cocoon-network | ||
| # | ||
| # Runs in init-bottom phase — AFTER configure_networking has parsed kernel ip= | ||
| # parameters into /run/net-*.conf, and AFTER mountroot has assembled the overlay. | ||
| # Converts initramfs network config into systemd-networkd .network files so | ||
| # the IP configuration persists after switch_root, and writes /etc/resolv.conf | ||
| # for immediate DNS availability regardless of init system. | ||
|
|
||
| PREREQ="" | ||
| prereqs() { echo "$PREREQ"; } | ||
| case "$1" in prereqs) prereqs; exit 0 ;; esac | ||
|
|
||
| . /scripts/functions | ||
|
|
||
| # $rootmnt is set by initramfs — points to the mounted root filesystem. | ||
| [ -z "$rootmnt" ] && exit 0 | ||
|
|
||
| # Set hostname from cocoon.hostname= kernel parameter. | ||
| for _arg in $(cat /proc/cmdline); do | ||
| case "$_arg" in | ||
| cocoon.hostname=*) echo "${_arg#cocoon.hostname=}" > "${rootmnt}/etc/hostname" ;; | ||
| esac | ||
| done | ||
|
|
||
| _dns_servers="" | ||
| _has_static=false | ||
|
|
||
| for conf_file in /run/net-*.conf; do | ||
| [ -f "$conf_file" ] || continue | ||
|
|
||
| unset DEVICE IPV4ADDR IPV4NETMASK IPV4GATEWAY IPV4DNS0 IPV4DNS1 HOSTNAME HWADDR | ||
| . "$conf_file" | ||
| [ -z "$DEVICE" ] && continue | ||
| [ -z "$IPV4ADDR" ] && continue | ||
|
|
||
| # Read MAC from sysfs if HWADDR not in conf (older klibc). | ||
| [ -z "$HWADDR" ] && [ -e "/sys/class/net/${DEVICE}/address" ] && HWADDR=$(cat "/sys/class/net/${DEVICE}/address") | ||
| [ -z "$HWADDR" ] && continue | ||
|
|
||
| _has_static=true | ||
|
|
||
| # Convert dotted netmask to prefix length. | ||
| prefix=0 | ||
| IFS=. read -r a b c d <<EOF | ||
| ${IPV4NETMASK} | ||
| EOF | ||
| for octet in $a $b $c $d; do | ||
| case $octet in | ||
| 255) prefix=$((prefix + 8)) ;; | ||
| 254) prefix=$((prefix + 7)) ;; | ||
| 252) prefix=$((prefix + 6)) ;; | ||
| 248) prefix=$((prefix + 5)) ;; | ||
| 240) prefix=$((prefix + 4)) ;; | ||
| 224) prefix=$((prefix + 3)) ;; | ||
| 192) prefix=$((prefix + 2)) ;; | ||
| 128) prefix=$((prefix + 1)) ;; | ||
| esac | ||
| done | ||
|
|
||
| # Use MAC-based matching so the config works regardless of device naming | ||
| # (eth0, enp0s4, or any name after hot-swap). File name uses MAC without | ||
| # colons to avoid collisions with old device-name-based files. | ||
| mac_sanitized=$(echo "$HWADDR" | tr -d ':') | ||
| mkdir -p "${rootmnt}/etc/systemd/network" | ||
| { | ||
| printf "[Match]\nMACAddress=%s\n\n[Network]\nAddress=%s/%d\n" "$HWADDR" "$IPV4ADDR" "$prefix" | ||
| [ -n "$IPV4GATEWAY" ] && [ "$IPV4GATEWAY" != "0.0.0.0" ] && printf "Gateway=%s\n" "$IPV4GATEWAY" | ||
| [ -n "$IPV4DNS0" ] && [ "$IPV4DNS0" != "0.0.0.0" ] && printf "DNS=%s\n" "$IPV4DNS0" | ||
| [ -n "$IPV4DNS1" ] && [ "$IPV4DNS1" != "0.0.0.0" ] && printf "DNS=%s\n" "$IPV4DNS1" | ||
| # Fallback DNS if none provided. | ||
| if [ -z "$IPV4DNS0" ] || [ "$IPV4DNS0" = "0.0.0.0" ]; then | ||
| printf "DNS=8.8.8.8\nDNS=8.8.4.4\n" | ||
| fi | ||
| } > "${rootmnt}/etc/systemd/network/10-${mac_sanitized}.network" | ||
|
|
||
| # Collect DNS servers for resolv.conf. | ||
| [ -n "$IPV4DNS0" ] && [ "$IPV4DNS0" != "0.0.0.0" ] && _dns_servers="${_dns_servers} ${IPV4DNS0}" | ||
| [ -n "$IPV4DNS1" ] && [ "$IPV4DNS1" != "0.0.0.0" ] && _dns_servers="${_dns_servers} ${IPV4DNS1}" | ||
|
|
||
| done | ||
|
|
||
| # Fallback: no kernel ip= configured — write DHCP config per NIC matched by MAC. | ||
| # This covers macvlan / external DHCP scenarios where CNI does not assign IPs. | ||
| if [ "$_has_static" = false ]; then | ||
| mkdir -p "${rootmnt}/etc/systemd/network" | ||
| for sysdev in /sys/class/net/*; do | ||
| [ -e "$sysdev" ] || continue | ||
| dev=$(basename "$sysdev") | ||
| # Skip loopback and virtual devices. | ||
| case "$dev" in lo|bonding_masters) continue ;; esac | ||
| [ -e "${sysdev}/address" ] || continue | ||
| mac=$(cat "${sysdev}/address") | ||
| # Skip zero/empty MACs. | ||
| case "$mac" in ""|00:00:00:00:00:00) continue ;; esac | ||
| mac_sanitized=$(echo "$mac" | tr -d ':') | ||
| { | ||
| printf "[Match]\nMACAddress=%s\n\n[Network]\nDHCP=ipv4\n\n[DHCPv4]\nClientIdentifier=mac\n" "$mac" | ||
| } > "${rootmnt}/etc/systemd/network/10-${mac_sanitized}.network" | ||
| done | ||
| fi | ||
|
|
||
| # Write /etc/resolv.conf from DNS servers collected above. | ||
| [ -z "$_dns_servers" ] && _dns_servers="8.8.8.8 8.8.4.4" | ||
| : > "${rootmnt}/etc/resolv.conf" | ||
| for _ns in $_dns_servers; do | ||
| printf "nameserver %s\n" "$_ns" >> "${rootmnt}/etc/resolv.conf" | ||
| done | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.