From ecc027a685374a43caae6f6218dfa4f6c1511da1 Mon Sep 17 00:00:00 2001 From: iceBear67 Date: Wed, 3 Jun 2026 16:04:41 +0800 Subject: [PATCH] init --- .gitignore | 26 ++ Makefile | 142 +++++++ alpine-make-vm-image | 749 +++++++++++++++++++++++++++++++++ configure.sh | 69 +++ gen-gpg-key.sh | 63 +++ overlay/data/PLACEHOLDER | 2 + overlay/etc/docker/daemon.json | 9 + overlay/etc/fstab | 5 + overlay/etc/network/interfaces | 5 + packages | 9 + repositories | 2 + 11 files changed, 1081 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100755 alpine-make-vm-image create mode 100755 configure.sh create mode 100755 gen-gpg-key.sh create mode 100644 overlay/data/PLACEHOLDER create mode 100644 overlay/etc/docker/daemon.json create mode 100644 overlay/etc/fstab create mode 100644 overlay/etc/network/interfaces create mode 100644 packages create mode 100644 repositories diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e7a52e --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Build artifacts +*.qcow2 +*.raw +*.img + +# Extracted kernel / initramfs +*-vmlinuz +*-initramfs +*-boot/ + +# Downloaded tool +alpine-make-vm-image + +# Generated GPG keys (secrets) +overlay/root/gpg-key.asc +overlay/root/gpg-pubkey.asc + +# Build marker +.gpg-done + +# Editor / OS +.DS_Store +*.swp +*.swo +*~ +.reasonix/** diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..83952df --- /dev/null +++ b/Makefile @@ -0,0 +1,142 @@ +# Alpine VM Image Builder +# ------------------------ +# Builds a bootable Alpine Linux disk image for Cloud Hypervisor direct boot. +# +# Usage: +# make build — generate GPG key + build qcow2 image +# make build-raw — build raw image (for Cloud Hypervisor direct boot) +# make extract-kernel — extract kernel + initramfs from image +# make clean — remove build artifacts +# +# Configurable variables (override on command line): +# IMAGE_SIZE Size of the disk image (default: 4G) +# ALPINE_BRANCH Alpine release branch (default: latest-stable) +# KERNEL_FLAVOR Kernel variant (default: virt) +# ALPINE_MIRROR APK mirror (default: http://dl-cdn.alpinelinux.org/alpine) + +SHELL := /bin/sh + +# --- configurable ---------------------------------------------------- +IMAGE_NAME ?= alpine-vm +IMAGE_SIZE ?= 4G +IMAGE_FORMAT ?= qcow2 +ALPINE_BRANCH ?= latest-stable +KERNEL_FLAVOR ?= virt +ALPINE_MIRROR ?= http://dl-cdn.alpinelinux.org/alpine +INITFS_FEATURES ?= kms scsi virtio + +IMAGE_FILE = $(IMAGE_NAME).$(IMAGE_FORMAT) +SCRIPT_DIR = $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) +OVERLAY_DIR = $(SCRIPT_DIR)/overlay +CONFIGURE_SH = $(SCRIPT_DIR)/configure.sh +GEN_GPG_SH = $(SCRIPT_DIR)/gen-gpg-key.sh + +# alpine-make-vm-image — download if not found +MAKE_VM_IMAGE = $(SCRIPT_DIR)/alpine-make-vm-image +MAKE_VM_IMAGE_URL = https://raw.githubusercontent.com/alpinelinux/alpine-make-vm-image/v0.13.4/alpine-make-vm-image + +# --- helper ---------------------------------------------------------- + +$(MAKE_VM_IMAGE): + @echo ">>> Downloading alpine-make-vm-image ..." + wget -q -O $@ $(MAKE_VM_IMAGE_URL) + chmod +x $@ + +# --- GPG key --------------------------------------------------------- + +.gpg-done: $(GEN_GPG_SH) + @echo ">>> Generating GPG key ..." + cd $(SCRIPT_DIR) && $(GEN_GPG_SH) + @touch $@ + +# --- build ----------------------------------------------------------- + +build: .gpg-done $(MAKE_VM_IMAGE) + @echo ">>> Building $(IMAGE_FILE) ..." + @test -f $(OVERLAY_DIR)/root/gpg-key.asc || { \ + echo "ERROR: GPG key not found. Run 'make gpg-key' first." >&2; \ + exit 1; \ + } + $(MAKE_VM_IMAGE) \ + --branch $(ALPINE_BRANCH) \ + --image-format $(IMAGE_FORMAT) \ + --image-size $(IMAGE_SIZE) \ + --kernel-flavor $(KERNEL_FLAVOR) \ + --mirror-uri $(ALPINE_MIRROR) \ + --initfs-features '$(INITFS_FEATURES)' \ + --serial-console \ + --fs-skel-dir $(OVERLAY_DIR) \ + --fs-skel-chown root:root \ + --script-chroot \ + --packages "python3 py3-yaml py3-pydantic git curl gnupg docker docker-cli-buildx docker-cli-compose" \ + $(IMAGE_FILE) \ + $(CONFIGURE_SH) + @echo ">>> Image built: $(IMAGE_FILE)" + @ls -lh $(IMAGE_FILE) + +# Raw image (best for Cloud Hypervisor) +build-raw: + $(MAKE) build IMAGE_FORMAT=raw + +# Build without GPG key (for testing / CI without GPG) +build-no-gpg: $(MAKE_VM_IMAGE) + @echo ">>> Building $(IMAGE_FILE) without GPG key ..." + $(MAKE_VM_IMAGE) \ + --branch $(ALPINE_BRANCH) \ + --image-format $(IMAGE_FORMAT) \ + --image-size $(IMAGE_SIZE) \ + --kernel-flavor $(KERNEL_FLAVOR) \ + --mirror-uri $(ALPINE_MIRROR) \ + --initfs-features '$(INITFS_FEATURES)' \ + --serial-console \ + --fs-skel-dir $(OVERLAY_DIR) \ + --fs-skel-chown root:root \ + --script-chroot \ + --packages "python3 py3-yaml py3-pydantic git curl gnupg docker docker-cli-buildx docker-cli-compose" \ + $(IMAGE_FILE) \ + $(CONFIGURE_SH) + @echo ">>> Image built: $(IMAGE_FILE)" + @ls -lh $(IMAGE_FILE) + +# --- kernel extraction ----------------------------------------------- + +extract-kernel: $(IMAGE_FILE) + @echo ">>> Extracting kernel and initramfs from $(IMAGE_FILE) ..." + @which guestmount >/dev/null 2>&1 || { \ + echo "ERROR: guestmount (libguestfs) required. Install: apk add libguestfs" >&2; \ + exit 1; \ + } + @mkdir -p $(IMAGE_NAME)-boot + guestmount -a $(IMAGE_FILE) -m /dev/sda --ro $(IMAGE_NAME)-boot + cp $(IMAGE_NAME)-boot/boot/vmlinuz-$(KERNEL_FLAVOR) $(IMAGE_NAME)-vmlinuz + cp $(IMAGE_NAME)-boot/boot/initramfs-$(KERNEL_FLAVOR) $(IMAGE_NAME)-initramfs + guestunmount $(IMAGE_NAME)-boot + rmdir $(IMAGE_NAME)-boot + @echo ">>> Kernel : $(IMAGE_NAME)-vmlinuz" + @echo ">>> Initrd : $(IMAGE_NAME)-initramfs" + +# --- utilities ------------------------------------------------------- + +gpg-key: .gpg-done + @echo ">>> GPG key ready" + +gpg-fingerprint: + @gpg --batch --fingerprint "builder@localhost" || echo "GPG key not found in host keyring" + +# --- cleanup --------------------------------------------------------- + +clean: + rm -f $(IMAGE_FILE) + rm -f $(IMAGE_NAME).raw + rm -f $(IMAGE_NAME)-vmlinuz $(IMAGE_NAME)-initramfs + rm -f .gpg-done + rm -f $(MAKE_VM_IMAGE) + rm -rf $(IMAGE_NAME)-boot + @echo ">>> Cleaned (GPG key in overlay/ preserved — use 'make clean-all' to remove)" + +clean-all: clean + rm -f $(OVERLAY_DIR)/root/gpg-key.asc + rm -f $(OVERLAY_DIR)/root/gpg-pubkey.asc + @echo ">>> All artifacts cleaned" + +.PHONY: build build-raw build-no-gpg extract-kernel gpg-key gpg-fingerprint clean clean-all diff --git a/alpine-make-vm-image b/alpine-make-vm-image new file mode 100755 index 0000000..52620f5 --- /dev/null +++ b/alpine-make-vm-image @@ -0,0 +1,749 @@ +#!/bin/sh +# vim: set ts=4 sw=4: +# SPDX-FileCopyrightText: © 2017 Jakub Jirutka +# SPDX-License-Identifier: MIT +#---help--- +# Usage: alpine-make-vm-image [options] [--] [