Commit 35de699e authored by Carlo Landmeter's avatar Carlo Landmeter
Browse files

use images from offical mirror

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
parent 0995c816
......@@ -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
......
......@@ -2,10 +2,14 @@
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
iseq ${alpine_loader} true && set img_verify enabled || set img_verify disabled
set console tty0 ||
set cmdline_extra none ||
set release latest-stable ||
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
......@@ -30,10 +34,13 @@ 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} ]
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_extra ${space} Additional cmdline [ ${cmdline_extra} ]
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
......@@ -41,19 +48,30 @@ 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
: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} [ ${arch} ]
item tty0 Console on tty0
item ttyS0 Console on ttyS0
item ttyS1 Console on ttyS1
item ttyAMA0 Console on ttyAMA0 (aarch64)
menu ${os} ${provider} [ ${arch} ]
{{#consoles}}
item {{{.}}} Console on {{{.}}}
{{/consoles}}
item custom Enter custom console
choose console || goto menu
iseq ${console} custom && goto custom_console ||
......@@ -70,26 +88,35 @@ shell
goto menu
:img_verify
iseq ${img_verify} true && set img_verify false || set img_verify true
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
:cmdline_extra
clear cmdline_extra
echo -n Enter extra cmdline options: && read cmdline_extra
: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
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
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-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
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-vanilla ${img-url}/vmlinuz-vanilla.sig
imgverify initramfs-vanilla ${img-url}/initramfs-vanilla.sig
imgverify vmlinuz-${flavor} ${sig-url}/vmlinuz-${flavor}.sig
imgverify initramfs-${flavor} ${sig-url}/initramfs-${flavor}.sig
:no_img_verify
boot
goto alpine_exit
......
#!/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))
---
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
#!/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"
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
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
Mkc=
=FcYC
-----END PGP PUBLIC KEY BLOCK-----
#!/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"
#!/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
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment