init
This commit is contained in:
26
image/.gitignore
vendored
Normal file
26
image/.gitignore
vendored
Normal file
@@ -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/**
|
||||
72
image/Makefile
Normal file
72
image/Makefile
Normal file
@@ -0,0 +1,72 @@
|
||||
# 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 = raw
|
||||
ALPINE_BRANCH ?= latest-stable
|
||||
KERNEL_FLAVOR ?= virt
|
||||
#INITFS_FEATURES ?= kms scsi virtio
|
||||
|
||||
IMAGE_FILE = vm.$(IMAGE_FORMAT)
|
||||
SCRIPT_DIR = $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
OVERLAY_DIR = $(SCRIPT_DIR)/overlay
|
||||
CONFIGURE_SH = $(SCRIPT_DIR)/configure.sh
|
||||
|
||||
build:
|
||||
@echo ">>> Building $(IMAGE_FILE) ..."
|
||||
@test -f $(OVERLAY_DIR)/root/gpg-key.asc || { \
|
||||
echo "ERROR: GPG key not found. Generate key first" >&2; \
|
||||
exit 1; \
|
||||
}
|
||||
$(MAKE_VM_IMAGE) \
|
||||
--branch $(ALPINE_BRANCH) \
|
||||
--image-format $(IMAGE_FORMAT) \
|
||||
--image-size $(IMAGE_SIZE) \
|
||||
--kernel-flavor $(KERNEL_FLAVOR) \
|
||||
--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
|
||||
|
||||
# --- 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) vmlinuz
|
||||
cp $(IMAGE_NAME)-boot/boot/initramfs-$(KERNEL_FLAVOR) initramfs
|
||||
guestunmount $(IMAGE_NAME)-boot
|
||||
rmdir $(IMAGE_NAME)-boot
|
||||
|
||||
.PHONY: build build-raw build-no-gpg extract-kernel gpg-key gpg-fingerprint
|
||||
57
image/configure.sh
Executable file
57
image/configure.sh
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
# configure.sh — runs inside chroot after base install and overlay copy.
|
||||
# Invoked via alpine-make-vm-image --script-chroot.
|
||||
set -eu
|
||||
|
||||
_step_counter=0
|
||||
step() {
|
||||
_step_counter=$(( _step_counter + 1 ))
|
||||
printf '\n\033[1;36m%d) %s\033[0m\n' $_step_counter "$@" >&2
|
||||
}
|
||||
|
||||
uname -a
|
||||
|
||||
step 'Set timezone to UTC'
|
||||
setup-timezone -z UTC
|
||||
|
||||
step 'Set up networking'
|
||||
# The interfaces file was placed by --fs-skel-dir; link init.d scripts.
|
||||
ln -sf networking /etc/init.d/net.lo
|
||||
ln -sf networking /etc/init.d/net.eth0
|
||||
|
||||
step 'Adjust rc.conf'
|
||||
sed -Ei \
|
||||
-e 's/^[# ](rc_depend_strict)=.*/\1=NO/' \
|
||||
-e 's/^[# ](rc_logger)=.*/\1=YES/' \
|
||||
-e 's/^[# ](unicode)=.*/\1=YES/' \
|
||||
/etc/rc.conf
|
||||
|
||||
step 'Enable base services'
|
||||
rc-update add net.lo boot
|
||||
rc-update add net.eth0 default
|
||||
rc-update add acpid default
|
||||
rc-update add docker default
|
||||
rc-update add cronie default
|
||||
|
||||
step 'Import GPG key for root'
|
||||
GPG_KEY_FILE="/root/gpg-key.asc"
|
||||
if [ -f "$GPG_KEY_FILE" ]; then
|
||||
echo "Found GPG key file: $GPG_KEY_FILE"
|
||||
gpg --batch --import "$GPG_KEY_FILE"
|
||||
# Mark the imported key as ultimately trusted (non-interactive)
|
||||
fingerprint=$(gpg --batch --with-colons --fingerprint \
|
||||
| grep '^fpr:' | head -1 | cut -d: -f10)
|
||||
if [ -n "$fingerprint" ]; then
|
||||
echo "$fingerprint:6:" | gpg --batch --import-ownertrust
|
||||
echo " * GPG key trusted: $fingerprint"
|
||||
fi
|
||||
rm -f "$GPG_KEY_FILE"
|
||||
else
|
||||
echo "WARNING: GPG key file not found at $GPG_KEY_FILE — skipping import" >&2
|
||||
fi
|
||||
|
||||
step 'Clean up APK cache'
|
||||
rm -rf /var/cache/apk/* || true
|
||||
|
||||
echo ''
|
||||
echo '=== Configure script completed ==='
|
||||
16
image/overlay/daemon/update.sh
Executable file
16
image/overlay/daemon/update.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
mkdir -p /app
|
||||
cd /app
|
||||
rm -rf ./template ./snapshot
|
||||
mkdir /app/template /app/snapshot
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
git clone -b _REVISION_ _REPO_ template
|
||||
|
||||
python3 /daemon/orchestrate.py \
|
||||
--root /app/template \
|
||||
--network cloud \
|
||||
--volume-parent /data/volumes \
|
||||
--snapshot-root /app/snapshot
|
||||
2
image/overlay/data/PLACEHOLDER
Normal file
2
image/overlay/data/PLACEHOLDER
Normal file
@@ -0,0 +1,2 @@
|
||||
# This directory is the virtiofs mount point for host-shared data.
|
||||
# Do not store critical data here before the virtiofs share is mounted.
|
||||
3
image/overlay/etc/dhcp/dhclient.conf
Normal file
3
image/overlay/etc/dhcp/dhclient.conf
Normal file
@@ -0,0 +1,3 @@
|
||||
interface "eth0" {
|
||||
supersede routers GATEWAY_ADDRESS;
|
||||
}
|
||||
9
image/overlay/etc/docker/daemon.json
Normal file
9
image/overlay/etc/docker/daemon.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"data-root": "/data/docker",
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "10m",
|
||||
"max-file": "3"
|
||||
},
|
||||
"storage-driver": "overlay2"
|
||||
}
|
||||
5
image/overlay/etc/fstab
Normal file
5
image/overlay/etc/fstab
Normal file
@@ -0,0 +1,5 @@
|
||||
# /etc/fstab: static file system information
|
||||
#
|
||||
# <file system> <mount point> <type> <options> <dump> <pass>
|
||||
/dev/root / ext4 rw,noatime 0 1
|
||||
data /data virtiofs rw,noatime,_netdev 0 0
|
||||
7
image/overlay/etc/network/interfaces
Normal file
7
image/overlay/etc/network/interfaces
Normal file
@@ -0,0 +1,7 @@
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet manual
|
||||
post-up dhclient -v eth0
|
||||
pre-down dhclient -x eth0
|
||||
2
image/overlay/var/spool/cron/crontabs/root
Normal file
2
image/overlay/var/spool/cron/crontabs/root
Normal file
@@ -0,0 +1,2 @@
|
||||
# min hour day month weekday command
|
||||
*/15 * * * * /usr/bin/sh /daemon/update.sh
|
||||
10
image/packages
Normal file
10
image/packages
Normal file
@@ -0,0 +1,10 @@
|
||||
python3
|
||||
py3-yaml
|
||||
py3-pydantic
|
||||
git
|
||||
curl
|
||||
gnupg
|
||||
docker
|
||||
docker-cli-buildx
|
||||
docker-cli-compose
|
||||
cronie
|
||||
2
image/repositories
Normal file
2
image/repositories
Normal file
@@ -0,0 +1,2 @@
|
||||
https://dl-cdn.alpinelinux.org/alpine/latest-stable/main
|
||||
https://dl-cdn.alpinelinux.org/alpine/latest-stable/community
|
||||
Reference in New Issue
Block a user