diff --git a/.gitignore b/.gitignore index 323a02a..9c27f10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .reasonix -*.asc \ No newline at end of file +*.asc +image/*.raw +*.raw diff --git a/BUILD.sh b/BUILD.sh index 4e6b0f0..39b0739 100755 --- a/BUILD.sh +++ b/BUILD.sh @@ -1,45 +1,48 @@ -#!/bin/sh +#!/bin/bash set -eo pipefail hasunset=0 +if [ "$UID" != "0" ]; then + echo "This script must be run in root." + exit 2 +fi + +PATH="$PWD/scripts:$PATH" + if [[ "$CLOUD_CONFIG_REPO" -eq "" ]]; then echo "CLOUD_CONFIG_REPO is not set." + CLOUD_CONFIG_REPO="https://git.sfclub.cc/cloud/bearnet" hasunset=1 fi if [[ "$CLOUD_CONFIG_REVISION" -eq "" ]]; then echo "CLOUD_CONFIG_REVISION is not set." + CLOUD_CONFIG_REVISION="wish" hasunset=1 fi if [[ "$CLOUD_GATEWAY_ADDRESS" -eq "" ]]; then echo "CLOUD_GATEWAY_ADDRESS is not set." + CLOUD_GATEWAY_ADDRESS="10.0.0.119" hasunset=1 fi +TMP_DIR=$(mktemp -d) + if [[ "$hasunset" -ne 0 ]]; then echo "" echo "Default values will be used for unset environments:" echo "" - grep -E "^ENV" ./Dockerfile + set | grep -E "^CLOUD_" fi cleanup_() { - if [[ "$GPG_PRIVATE_KEY" -ne "" ]]; then - rm ./bot-gpg-key.asc - fi + rm -rf $TMP_DIR } -trap cleanup_ INT TERM - -if [[ "$GPG_PRIVATE_KEY" -ne "" ]]; then - echo "$GPG_PRIVATE_KEY" > ./bot-gpg-key.asc -elif [[ ! -f ./bot-gpg-key.asc ]]; then - echo "GPG key not found. Terminating.." - exit -1 -fi +trap cleanup_ INT TERM EXIT IMAGE_TAG=$(git rev-parse --short HEAD) IMAGE_NAME=${IMAGE_NAME:-bearcloud} @@ -49,5 +52,25 @@ echo "Additional arguments: $@" echo "Continue?" read -sudo docker build -t "$IMAGE_NAME:$IMAGE_TAG" -t "$IMAGE_NAME:latest" $@ . +rm -rf "$TMP_DIR" +cp -r ./image $TMP_DIR +sed -i "s#_REPO_#$CLOUD_CONFIG_REPO#g" $TMP_DIR/overlay/daemon/update-keys.sh && \ +sed -i "s#_REVISION_#$CLOUD_CONFIG_REVISION#g" $TMP_DIR/overlay/daemon/update-keys.sh && \ +sed -i "s#GATEWAY_ADDRESS#$CLOUD_GATEWAY_ADDRESS#g" $TMP_DIR/overlay/etc/dhcp/dhclient.conf + +pushd $PWD >/dev/null + +cd $TMP_DIR +export IMAGE_ARTIFACT="$PWD/vm.raw" +rm -f vm.raw && ./build-image.sh +if [ ! -f $IMAGE_ARTIFACT ]; then + exit 2 +fi + +popd > /dev/null + +mv $IMAGE_ARTIFACT ./data/ +IMAGE_ARTIFACT="$PWD/data/vm.raw" + +docker build -t "$IMAGE_NAME:$IMAGE_TAG" -t "$IMAGE_NAME:latest" $@ . diff --git a/Dockerfile b/Dockerfile index 4ff4089..efd422a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,10 @@ -FROM alpine:latest AS rootfs-builder - -ENV CLOUD_CONFIG_REPO=https://git.sfclub.cc/cloud/bearnet -ENV CLOUD_CONFIG_REVISION=wish -ENV CLOUD_GATEWAY_ADDRESS=10.0.0.119 -RUN apk update && apk add alpine-make-vm-image make -COPY /image /kitchen -COPY ./scripts/orchestrate.py /kitchen/overlay/daemon/orchestrate.py -COPY bot-gpg-key.asc /kitchen/overlay/root/gpg-key.asc -RUN sed -i "s#_REPO_#$CLOUD_CONFIG_REPO#g" /kitchen/overlay/daemon/update.sh && \ - sed -i "s#_REVISION_#$CLOUD_CONFIG_REVISION#g" /kitchen/overlay/daemon/update.sh && \ - sed -i "s#GATEWAY_ADDRESS#$CLOUD_GATEWAY_ADDRESS#g" /kitchen/overlay/etc/dhcp/dhclient.conf -RUN cd /kitchen && make build && mkdir /image && cp ./vm.raw /image - FROM alpine:latest AS hypervisor ADD ./scripts/setup-hypervisor.sh /setup.sh # Download cloud hypervisor RUN apk update && apk add bash curl jq tini linux-virt && sh /setup.sh && rm /setup.sh && mkdir /app -COPY --from=rootfs-builder /image /image COPY ./scripts/entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/usr/bin/tini", "/entrypoint.sh"] +ENTRYPOINT ["/sbin/tini", "/entrypoint.sh"] diff --git a/README.md b/README.md deleted file mode 100644 index 55f5d91..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ - -todo: -1. specify id for vm disks -2. figure out if we need direct=on on --disk options -3. test on my homelab? diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e75dd03 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +# for testing and reference only +services: + cloud: + build: . + volumes: + - "./data:/image" + - "./test.sh:/test.sh" + devices: + - "/dev/kvm:/dev/kvm" + entrypoint: ["/sbin/tini", "/test.sh"] + cap_add: + - CAP_SYS_ADMIN + tty: true + stdin_open: true diff --git a/image/Makefile b/image/Makefile deleted file mode 100644 index 247b32e..0000000 --- a/image/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -SHELL := /bin/sh - -# --- configurable ---------------------------------------------------- -IMAGE_NAME = alpine-vm -IMAGE_SIZE ?= 1G -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) ..." - alpine-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 "git curl docker docker-cli-buildx docker-cli-compose cronie" \ - $(IMAGE_FILE) \ - $(CONFIGURE_SH) - @echo ">>> Image built: $(IMAGE_FILE)" - @ls -lh $(IMAGE_FILE) - -.PHONY: build diff --git a/image/build-image.sh b/image/build-image.sh new file mode 100755 index 0000000..938e61b --- /dev/null +++ b/image/build-image.sh @@ -0,0 +1,39 @@ +#!/bin/sh +IMAGE_NAME="${IMAGE_NAME:=alpine-vm}" +IMAGE_SIZE="${IMAGE_SIZE:-1G}" +IMAGE_FORMAT="${IMAGE_FORMAT:=raw}" +ALPINE_BRANCH="${ALPINE_BRANCH:=latest-stable}" +KERNEL_FLAVOR="${KERNEL_FLAVOR:=virt}" +IMAGE_FILE="vm.${IMAGE_FORMAT}" +SCRIPT_DIR="$PWD" +OVERLAY_DIR="${SCRIPT_DIR}/overlay" +CONFIGURE_SH="${SCRIPT_DIR}/configure.sh" + +TMP=$(mktemp) + +cleanup() { + rm $TMP +} + +trap cleanup INT TERM EXIT + +# We use BIOS here to skip creating partitions + +alpine-make-vm-image \ + --boot-mode "BIOS" \ + --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 "git curl docker cronie" \ + "$IMAGE_FILE" \ + "$CONFIGURE_SH" | tee $TMP + +if grep -q "ERROR" $TMP; then + echo "BUILD FAILED" + exit 114514 +fi diff --git a/image/configure.sh b/image/configure.sh index b4c83e8..44a5305 100755 --- a/image/configure.sh +++ b/image/configure.sh @@ -32,7 +32,6 @@ rc-update add net.eth0 default rc-update add acpid default rc-update add docker default rc-update add cronie default -rc-update add mount boot step 'Clean up APK cache and documents' rm -rf /var/cache/apk/* || true @@ -43,8 +42,8 @@ rm -rf \ /usr/share/info step 'Setup git user' -git config --user.email bearnet+keeper@sab.ee -git config --user.name "B.B.K.K.B.K.K" +git config --global user.email bearnet+keeper@sab.ee +git config --global user.name "B.B.K.K.B.K.K" adduser -S keeper mkdir /users chown keeper /users diff --git a/image/overlay/daemon/update-keys.sh b/image/overlay/daemon/update-keys.sh index 193a153..8a82cca 100755 --- a/image/overlay/daemon/update-keys.sh +++ b/image/overlay/daemon/update-keys.sh @@ -4,14 +4,12 @@ set -euo pipefail mkdir -p /users && chown keeper /users && chmod 644 /users -su keeper - init_repo(){ - git clone -b _REVISION_ _REPO_ /users + su - keeper 'git clone -b _REVISION_ _REPO_ /users' } if [[ ! -d /users/.git ]]; then init_repo -elif [[ -d /users && cd /users && ! git pull origin _REVISION_ ]]; then +elif [[ -d /users && cd /users && ! su - keeper 'git pull origin _REVISION_' ]]; then init_repo fi \ No newline at end of file diff --git a/scripts/alpine-make-vm-image b/scripts/alpine-make-vm-image new file mode 100755 index 0000000..07e5149 --- /dev/null +++ b/scripts/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] [--] [