aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlo Landmeter <clandmeter@alpinelinux.org>2018-06-27 12:55:19 +0000
committerCarlo Landmeter <clandmeter@alpinelinux.org>2018-06-27 13:25:50 +0000
commit35de699e005d183854f2cc0f9615d316c13fd657 (patch)
treeac397530a123d97c224d4bad8fd80a2b0dd8ea7c
parent0995c816219a8f6c700e58e6bcca32331cd5529c (diff)
downloadalpine-netboot-35de699e005d183854f2cc0f9615d316c13fd657.tar.bz2
alpine-netboot-35de699e005d183854f2cc0f9615d316c13fd657.tar.xz
use images from offical mirrorremote_images
Do not generate images locally but instead generate signatures locally and use images from offical mirror. - generate ipxe boot script from template - add option to start sshd with firstboot - add version information when selecting branch - verify netboot releases with gpg signature - added ncopa.asc gpg public key
-rw-r--r--README.md37
-rw-r--r--boot.ipxe105
-rw-r--r--boot.ipxe.tpl132
-rwxr-xr-xbuild.lua51
-rw-r--r--config.sample.yaml23
-rwxr-xr-xmknetboot.sh85
-rw-r--r--ncopa.asc52
-rwxr-xr-xsign_images.sh48
-rwxr-xr-xupdate-netboot.sh93
9 files changed, 319 insertions, 307 deletions
diff --git a/README.md b/README.md
index 65fe1aa..09da492 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,11 @@
Welcome to the Alpine Linux netboot server.
-Netboot provides kernel initramfs and modloop images to boot over the
-network/internet. Booting from netboot is provided by the IPXE binaries
-available in alpine-ipxe `apk add alpine-ipxe` or from
-[this location](alpine-ipxe) (x86_64 and aarch64).
+This netboot server provides a boot script and image signatures to securly boot
+Alpine Linux over the internet. To be able to boot you will need to have a copy
+of the iPXE bootloader available. You can get a copy of the bootloaders by
+installing alpine-ipxe `apk add alpine-ipxe` or from [this location](alpine-ipxe)
+(only x86_64).
## Boot script
@@ -16,28 +17,18 @@ build your own version of [ipxe](https://ipxe.org).
Some cloud providers (ie [packet.net](https://help.packet.net/technical/infrastructure/custom-ipxe))
support the loading of custom ipxe scripts/payloads to install an operating
-system. You can chainload one of the ipxe loaders from [alpine-ipxe](alpine-ipxe).
-Loading our default boot script from another firware will disable image
-verification.
+system. You can chainload one of the ipxe bootloaders from [alpine-ipxe](alpine-ipxe).
+Loading our boot script from another bootloader will disable image verification.
## Images
-Images are hosted in the [Images](images) directory on boot.alpinelinux.org.
-Current available images are:
-
-* **edge**
- * [x86](images/edge/x86)
- * [x86_64](images/edge/x86_64)
- * [aarch64](images/edge/aarch64)
-* **latest-stable**
- * [x86](images/latest-stable/x86)
- * [x86_64](images/latest-stable/x86_64)
- * [aarch64](images/latest-stable/aarch64)
+**NOTE**: since Alpine v3.8 this netboot server does not provide images anymore.
+You can find netboot images in the release directories on our [mirrors](https://mirrors.alpinelinux.org).
## Signed images
Alpine Linux images are signed and can be verified only by making use of
-[alpine-ipxe](alpine-ipxe). Using another ipxe loader will disable verification.
+[alpine-ipxe](alpine-ipxe). Using another ipxe bootloader will disable verification.
## Boot options
@@ -55,14 +46,12 @@ Alpine Linux images are signed and can be verified only by making use of
### UEFI (aarch64)
-* [snp.efi](alpine-ipxe/aarch64/snp.efi) UEFI executable
-
+* snp.efi UEFI executable
## Updates
-Netboot images are updated every night automatically if any package in the
-dependecy tree (kernel and alpine-base) has been updated. Regular packages are
-updated automatically via our package repositories.
+Currently we only support latest stable releases. We are working on adding montly
+edge snapshots.
## Testing netboot
diff --git a/boot.ipxe b/boot.ipxe
deleted file mode 100644
index 217d7b2..0000000
--- a/boot.ipxe
+++ /dev/null
@@ -1,105 +0,0 @@
-#!ipxe
-
-set os Alpine Linux
-iseq ${ipxe_cloud_config} packet && set provider (Packet.net) ||
-iseq ${alpine_loader} true && set img_verify true || set img_verify false
-set console tty0 ||
-set cmdline_extra none ||
-set release latest-stable ||
-iseq ${buildarch} arm64 && goto arm64 ||
-cpuid --ext 29 && goto x86_64 || goto x86
-
-:arm64
-set arch aarch64 ||
-set acpi acpi=force ||
-set console ttyAMA0 ||
-iseq ${ipxe_cloud_config} packet && set console ttyAMA0,115200 ||
-goto menu
-
-:x86_64
-set arch x86_64 ||
-iseq ${ipxe_cloud_config} packet && set console ttyS1,115200n8 ||
-goto menu
-
-:x86
-set arch x86 ||
-goto menu
-
-:menu
-set space:hex 20:20
-set space ${space:string}
-menu ${os} ${provider} [ ${arch} ]
-item --gap Boot options
-item release ${space} Choose release [ ${release} ]
-item console ${space} Set console [ ${console} ]
-iseq ${alpine_loader} true && item img_verify ${space} Image verification [ ${img_verify} ] ||
-item cmdline_extra ${space} Additional cmdline [ ${cmdline_extra} ]
-item boot ${space} Boot with above settings
-item --gap Utilities
-item shell ${space} iPXE Shell
-item reboot ${space} Reboot system
-choose item
-goto ${item}
-
-:release
-menu ${os} [ ${arch} ]
-item latest-stable Latest stable
-item edge Edge (development)
-choose release || goto alpine_exit
-goto menu
-
-:console
-menu ${os} [ ${arch} ]
-item tty0 Console on tty0
-item ttyS0 Console on ttyS0
-item ttyS1 Console on ttyS1
-item ttyAMA0 Console on ttyAMA0 (aarch64)
-item custom Enter custom console
-choose console || goto menu
-iseq ${console} custom && goto custom_console ||
-goto menu
-
-:custom_console
-clear console
-echo -n Enter console: && read console
-goto menu
-
-:shell
-echo Type "exit" to return to menu.
-shell
-goto menu
-
-:img_verify
-iseq ${img_verify} true && set img_verify false || set img_verify true
-goto menu
-
-:cmdline_extra
-clear cmdline_extra
-echo -n Enter extra cmdline options: && read cmdline_extra
-goto menu
-
-:boot
-iseq ${cmdline_extra} none && clear cmdline_extra ||
-isset ${console} && set console console=${console} ||
-set img-url https://boot.alpinelinux.org/images/${release}/${arch}
-set repo-url http://dl-cdn.alpinelinux.org/alpine/${release}/main
-imgfree
-kernel ${img-url}/vmlinuz-vanilla initrd=initramfs-vanilla pkgs=libressl alpine_repo=${repo-url} modules=loop,squashfs modloop=${img-url}/modloop-vanilla nomodeset ${console} ${acpi} ${cmdline_extra}
-initrd ${img-url}/initramfs-vanilla
-iseq ${img_verify} true && goto verify_img || goto no_img_verify
-:verify_img
-imgverify vmlinuz-vanilla ${img-url}/vmlinuz-vanilla.sig
-imgverify initramfs-vanilla ${img-url}/initramfs-vanilla.sig
-:no_img_verify
-boot
-goto alpine_exit
-
-:reboot
-reboot
-
-:poweroff
-poweroff
-
-:alpine_exit
-clear menu
-exit 0
diff --git a/boot.ipxe.tpl b/boot.ipxe.tpl
new file mode 100644
index 0000000..8f5db38
--- /dev/null
+++ b/boot.ipxe.tpl
@@ -0,0 +1,132 @@
+#!ipxe
+
+set os Alpine Linux
+iseq ${ipxe_cloud_config} packet && set provider (Packet.net) ||
+iseq ${alpine_loader} true && set img_verify enabled || set img_verify disabled
+set console tty0 ||
+set cmdline {{{cmdline}}} ||
+set default_cmdline default ||
+set start_sshd no ||
+set branch {{{default.branch}}} ||
+set version {{{default.version}}} ||
+set flavor {{{default.flavor}}} ||
+iseq ${buildarch} arm64 && goto arm64 ||
+cpuid --ext 29 && goto x86_64 || goto x86
+
+:arm64
+set arch aarch64 ||
+set acpi acpi=force ||
+set console ttyAMA0 ||
+iseq ${ipxe_cloud_config} packet && set console ttyAMA0,115200 ||
+goto menu
+
+:x86_64
+set arch x86_64 ||
+iseq ${ipxe_cloud_config} packet && set console ttyS1,115200n8 ||
+goto menu
+
+:x86
+set arch x86 ||
+goto menu
+
+:menu
+set space:hex 20:20
+set space ${space:string}
+menu ${os} ${provider} [ ${arch} ]
+item --gap Boot options
+item branch ${space} Alpine version [ ${branch} ]
+iseq ${arch} x86_64 && item flavor ${space} Kernel flavor [ ${flavor} ] ||
+iseq ${alpine_loader} true && item img_verify ${space} Image verification [ ${img_verify} ] ||
+item cmdline ${space} Linux cmdline [ ${default_cmdline} ]
+item console ${space} Set console [ ${console} ]
+item start_sshd ${space} Start sshd at first boot [ ${start_sshd} ]
+item --gap Booting
+item boot ${space} Boot with above settings
+item --gap Utilities
+item shell ${space} iPXE Shell
+item reboot ${space} Reboot system
+choose item
+goto ${item}
+
+:branch
+menu ${os} ${provider} [ ${arch} ]
+{{#releases}}
+item {{{branch}}} Version {{{version}}}
+{{/releases}}
+choose branch || goto shell
+{{#releases}}
+iseq branch {{{branch}}} && set version {{{version}}} ||
+{{/releases}}
+goto menu
+
+:flavor
+menu ${os} ${provider} [ ${arch} ]
+{{#flavors}}
+item {{{.}}} Linux {{{.}}}
+{{/flavors}}
+choose flavor || goto shell
+goto menu
+
+:console
+menu ${os} ${provider} [ ${arch} ]
+{{#consoles}}
+item {{{.}}} Console on {{{.}}}
+{{/consoles}}
+item custom Enter custom console
+choose console || goto menu
+iseq ${console} custom && goto custom_console ||
+goto menu
+
+:custom_console
+clear console
+echo -n Enter console: && read console
+goto menu
+
+:shell
+echo Type "exit" to return to menu.
+shell
+goto menu
+
+:img_verify
+iseq ${img_verify} enabled && set img_verify disabled || set img_verify enabled
+goto menu
+
+:cmdline
+echo -n Enter extra cmdline options:${space} && read cmdline
+set default_cmdline modified
+goto menu
+
+:start_sshd
+clear start_sshd
+echo -n Enter url to ssh key:${space} && read ssh_key
+isset ${ssh_key} && set start_sshd yes || set start_sshd no
+iseq ${start_sshd} yes && set ssh_key ssh_key=${ssh_key} || clear ssh_key
+goto menu
+
+:boot
+isset ${console} && set console console=${console} ||
+set mirror {{{mirror}}}
+set img-url ${mirror}/${branch}/releases/${arch}/netboot-${version}
+set sig-url sigs/${branch}/${arch}/${version}
+set repo-url ${mirror}/${branch}/main
+set modloop-url ${img-url}/modloop-${flavor}
+imgfree
+kernel ${img-url}/vmlinuz-${flavor} ${cmdline} alpine_repo=${repo-url} modloop=${modloop-url} ${console} ${acpi} ${ssh_key}
+initrd ${img-url}/initramfs-${flavor}
+iseq ${img_verify} enabled && goto verify_img || goto no_img_verify
+:verify_img
+imgverify vmlinuz-${flavor} ${sig-url}/vmlinuz-${flavor}.sig
+imgverify initramfs-${flavor} ${sig-url}/initramfs-${flavor}.sig
+:no_img_verify
+boot
+goto alpine_exit
+
+:reboot
+reboot
+
+:poweroff
+poweroff
+
+:alpine_exit
+clear menu
+exit 0
diff --git a/build.lua b/build.lua
new file mode 100755
index 0000000..c509502
--- /dev/null
+++ b/build.lua
@@ -0,0 +1,51 @@
+#!/usr/bin/lua5.3
+
+local yaml = require("lyaml")
+local http = require("socket.http")
+local pfile = require("pl.file")
+local ppath = require("pl.path")
+local lustache = require("lustache")
+
+local cf = yaml.load(pfile.read("config.yaml"))
+cf.releases = {}
+local info = {}
+
+function get_release_info(release, arch)
+ local url = ("%s/%s/releases/%s/latest-releases.yaml"):format(
+ cf.mirror, release, arch)
+ local body, code = http.request(url)
+ if not body then error(code) end
+
+ local res = yaml.load(body)
+ for k,v in ipairs(res) do
+ if v.flavor == "alpine-netboot" then return v end
+ end
+end
+
+for _,branch in ipairs(cf.branches) do
+ for _,arch in ipairs(cf.archs) do
+ info = get_release_info(branch, arch)
+ if info then
+ if ppath.exists(("/var/www/localhost/htdocs/sigs/%s/%s/%s"):format(
+ info.branch, info.arch, info.version)) then
+ print(("Skipping: %s/%s/%s"):format(
+ info.branch, info.arch, info.version))
+ else
+ info.origin_branch = branch
+ print(("Processing: %s/%s/%s"):format(
+ info.branch, info.arch, info.version))
+ os.execute(("./sign_images.sh \"%s\" \"%s\" \"%s\""):format(
+ info.branch, info.arch, info.version))
+ end
+ end
+ end
+ if branch == cf.default.branch then
+ cf.default.branch = info.branch
+ cf.default.version = info.version
+ end
+ table.insert(cf.releases, { branch=info.branch, version=info.version })
+end
+
+local tpl = pfile.read(cf.tpl)
+print("Updating ipxe script: "..cf.ipxe)
+pfile.write(cf.ipxe, lustache:render(tpl, cf))
diff --git a/config.sample.yaml b/config.sample.yaml
new file mode 100644
index 0000000..4af1dea
--- /dev/null
+++ b/config.sample.yaml
@@ -0,0 +1,23 @@
+---
+mirror: http://dl-cdn.alpinelinux.org/alpine
+tpl: boot.ipxe.tpl
+ipxe: /var/www/localhost/htdocs/boot-test.ipxe
+branches:
+ - latest-stable
+archs:
+ - x86
+ - x86_64
+ - aarch64
+consoles:
+ - tty0
+ - ttyS0
+ - ttyS1
+ - ttyAMA0
+flavors:
+ - vanilla
+ - virt
+cmdline: modules=loop,squashfs quiet nomodeset
+default:
+ flavor: vanilla
+ branch: latest-stable
+... \ No newline at end of file
diff --git a/mknetboot.sh b/mknetboot.sh
deleted file mode 100755
index 1c4d084..0000000
--- a/mknetboot.sh
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/bin/sh -e
-
-ARCH=$(apk --print-arch)
-FLAVOR="vanilla"
-FEATURE="base squashfs network zfs"
-PACKAGE="spl-vanilla zfs-vanilla"
-OUTDIR="$PWD/out"
-RELEASE="edge"
-MIRROR="http://dl-cdn.alpinelinux.org/alpine"
-
-usage() {
- local ws=$(printf %${#0}s)
- cat <<-EOF
-
- $0 [--arch ARCH] [--flavor FLAVOR] [--feature FEATURE]
- $ws [--outdir OUTDIR] [--release RELEASE] [--repository REPO]
- $0 --help
-
- options:
- --arch Specify which architecture images to build
- --flavor Specify which kernel flavor images to build
- --feature Specify which initramfs features to include
- --package Additional module or firmware package
- --outdir Specify directory for the created images
- --release Build images for specified release from main repository
- --repository Package repository to use (overides --release)
- --extra-repository Add repository to search packages from (overides --release)
-
- EOF
-}
-
-# parse parameters
-while [ $# -gt 0 ]; do
- opt="$1"
- shift
- case "$opt" in
- --arch) ARCH="$1"; shift ;;
- --flavor) FLAVOR="$1"; shift ;;
- --feature) FEATURE="$1"; shift ;;
- --outdir) OUTDIR="$1"; shift ;;
- --release) RELEASE="$1"; shift ;;
- --repository) REPO="$1"; shift ;;
- --extra-repository) EXTRAREPO="$EXTRAREPO $1"; shift ;;
- --) break ;;
- -*) usage; exit 1;;
- esac
-done
-
-rm -rf "$OUTDIR"
-mkdir -p "$OUTDIR"
-
-REPOFILE=$(mktemp)
-DEFAULT_REPO="$MIRROR/$RELEASE/main"
-echo "${REPO:-$DEFAULT_REPO}" >> "$REPOFILE"
-for repo in $EXTRAREPO; do
- echo "$repo" >> "$REPOFILE"
-done
-
-echo "Creating netboot image: $RELEASE/$ARCH/$FLAVOR"
-
-update-kernel \
- --arch "$ARCH" \
- --flavor "$FLAVOR" \
- --feature "$FEATURE" \
- --package "$PACKAGE" \
- --repositories-file "$REPOFILE" \
- "$OUTDIR"
-
-# older vanilla kernels do not have the flavor appended.
-for file in vmlinuz config System.map; do
- if [ -f "$OUTDIR"/$file ]; then
- mv "$OUTDIR"/$file "$OUTDIR"/$file-"$FLAVOR"
- fi
-done
-
-# arm64 kernel is not a std bzImage but intead gzip compressed image
-# iPXE efi mode (default for aarch64) does not support compressed kernel image
-if [ "$ARCH" = "aarch64" ] && gunzip -t "$OUTDIR"/vmlinuz-"$FLAVOR" 2> /dev/null; then
- TMP_KERNEL=$(mktemp)
- zcat "$OUTDIR"/vmlinuz-"$FLAVOR" > $TMP_KERNEL && mv $TMP_KERNEL \
- "$OUTDIR"/vmlinuz-"$FLAVOR"
- chmod 644 "$OUTDIR"/vmlinuz-"$FLAVOR"
-fi
-
-rm -f "$REPOFILE"
diff --git a/ncopa.asc b/ncopa.asc
new file mode 100644
index 0000000..b4b34a5
--- /dev/null
+++ b/ncopa.asc
@@ -0,0 +1,52 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+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
+Mkc=
+=FcYC
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/sign_images.sh b/sign_images.sh
new file mode 100755
index 0000000..3835c09
--- /dev/null
+++ b/sign_images.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+branch=$1
+arch=$2
+version=$3
+mirror=http://dl-cdn.alpinelinux.org/alpine
+sigs=/var/www/localhost/htdocs/sigs/$branch/$arch/$version
+tarball=alpine-netboot-$version-$arch.tar.gz
+
+# CA Settings
+CA_CRT="/etc/ssl/alpine-netboot-ca/ca.crt"
+SIGN_CRT="/etc/ssl/alpine-netboot-ca/codesign.crt"
+SIGN_KEY="/etc/ssl/alpine-netboot-ca/codesign.key"
+PASS_FILE="/etc/ssl/alpine-netboot-ca/passwd"
+
+sign_image() {
+ local in=$1 out=$2
+ echo "Signing image: $in"
+ openssl cms -sign -binary -noattr -in "$in" \
+ -signer "$SIGN_CRT" -inkey "$SIGN_KEY" \
+ -certfile "$CA_CRT" \
+ -outform DER -out "$out" \
+ -passin file:"$PASS_FILE"
+}
+
+fetch_and_verify() {
+ for file in "$tarball" "$tarball".asc; do
+ wget -q -P "$tmpdir" "$mirror"/$branch/releases/$arch/$file
+ done
+ gpg --verify "$tmpdir/$tarball".asc "$tmpdir/$tarball" &> /dev/null
+}
+
+tmpdir=$(mktemp -d)
+mkdir -p "$sigs" && rm -f "$sigs"/*
+
+if fetch_and_verify; then
+ tar -C "$tmpdir" -zxvf "$tmpdir"/"$tarball" | while read file; do
+ case $file in
+ *modloop*|*vmlinuz*|*initramfs*)
+ sign_image "$tmpdir/$file" "$sigs/${file##*/}.sig" ;;
+ esac
+ done
+else
+ echo "Failed to verify: $branch/$tarball"
+fi
+
+rm -rf "$tmpdir"
+
diff --git a/update-netboot.sh b/update-netboot.sh
deleted file mode 100755
index 99ff659..0000000
--- a/update-netboot.sh
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/bin/sh -e
-
-REPO="http://dl-cdn.alpinelinux.org/alpine"
-BRANCHES="edge latest-stable"
-ARCHS="x86 x86_64 aarch64"
-IMGDIR="/var/www/localhost/htdocs/images"
-
-# CA Settings
-CA_CRT="/etc/ssl/alpine-netboot-ca/ca.crt"
-SIGN_CRT="/etc/ssl/alpine-netboot-ca/codesign.crt"
-SIGN_KEY="/etc/ssl/alpine-netboot-ca/codesign.key"
-PASS_FILE="/etc/ssl/alpine-netboot-ca/passwd"
-
-if [ -f "/lib/libalpine.sh" ]; then
- . /lib/libalpine.sh
-else
- echo "Error: cannot find libalpine.sh" >&2
- exit 1
-fi
-
-CACHE_DIR="/var/cache/alpine-netboot"
-APK="apk --no-cache --repositories-file /dev/null"
-
-compare_files() {
- [ -f "$1" ] || return 1
- [ -f "$2" ] || return 1
- diff -q "$1" "$2" > /dev/null 2>&1
-}
-
-# list all runtime depencencies for alpine-base
-resolve_base() {
- local branch="$1"
- local arch="$2"
- ALPINE_BASE=$($APK --arch $arch -X $REPO/$branch/main fetch -R --simulate alpine-base 2> /dev/null)
- [ "$?" = "0" ] || die "Failed to get base dependency tree"
- echo "$ALPINE_BASE" | grep -v '^fetch' | cut -d' ' -f2
-}
-
-# find the latest kernel and firmware.
-# kernel/firmware deps are not interesting so we do not resolve the tree.
-get_latest_kernel() {
- local branch="$1"
- local arch="$2"
- KERNEL=$($APK --arch $arch -X $REPO/$branch/main search -x linux-vanilla linux-firmware)
- [ "$?" = "0" ] || die "Failed to get kernel version"
- echo "$KERNEL" | grep -v '^fetch'
-}
-
-sign_images() {
- local imgdir="$1"
- local img
- for img in vmlinuz initramfs; do
- local file=$(realpath $imgdir/*${img}*)
- echo "Signing image: $file"
- openssl cms -sign -binary -noattr -in "$file" \
- -signer "$SIGN_CRT" -inkey "$SIGN_KEY" \
- -certfile "$CA_CRT" \
- -outform DER -out "$file".sig \
- -passin file:"$PASS_FILE"
- done
-}
-
-
-#############
-# M a i n #
-#############
-
-mkdir -p "$CACHE_DIR"
-tmpfile=$(mktemp)
-tmpdir=$(mktemp -d)
-
-for branch in $BRANCHES; do
- mkdir -p "$IMGDIR"/$branch
- for arch in $ARCHS; do
- echo "Checking: $branch/$arch"
- for i in $(resolve_base $branch $arch && get_latest_kernel $branch $arch); do
- echo "$i" >> $tmpfile
- done
- sort $tmpfile -o $tmpfile
- if ! compare_files $tmpfile "$CACHE_DIR"/$branch-$arch.lst; then
- echo "Dependencies updated for: $branch/$arch"
- ./mknetboot.sh --release "$branch" --arch "$arch" --outdir "$tmpdir"
- (cd "$tmpdir" && sha512sum * > alpine-netboot-$branch-$arch.sha512 || true)
- sign_images "$tmpdir"
- rm -rf "$IMGDIR"/$branch/$arch
- mv "$tmpdir" "$IMGDIR"/$branch/$arch
- mv "$tmpfile" "$CACHE_DIR"/$branch-$arch.lst
- else
- printf "No update found\n"
- rm -f $tmpfile
- fi
- done
-done