From fa919cb681747c95a31ceed508282a4e8475d0bf Mon Sep 17 00:00:00 2001 From: Carlo Landmeter Date: Mon, 5 Mar 2018 22:39:42 +0000 Subject: Initial commit --- LICENSE | 21 ++ README.md | 68 +++++ boot.ipxe | 27 ++ html/alpinelinux-logo.svg | 167 +++++++++++ html/favicon.ico | Bin 0 -> 4286 bytes html/page.theme | 31 ++ html/style.css | 66 +++++ html/theme.css | 709 ++++++++++++++++++++++++++++++++++++++++++++++ mkindex.sh | 15 + mknetboot.sh | 76 +++++ update-netboot.sh | 93 ++++++ 11 files changed, 1273 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 boot.ipxe create mode 100644 html/alpinelinux-logo.svg create mode 100644 html/favicon.ico create mode 100644 html/page.theme create mode 100644 html/style.css create mode 100644 html/theme.css create mode 100755 mkindex.sh create mode 100755 mknetboot.sh create mode 100755 update-netboot.sh diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e45ac6b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Carlo Landmeter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2335bf0 --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ +# Alpine Linux netboot + +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). + +## Boot script + +The default bootscript for alpine-ipxe is +**[https://boot.alpinelinux.org/boot.ipxe](boot.ipxe)** which will automatically +be fetched by alpine-ipxe. If you like to change this behaviour you will need to +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). +Don't load the boot.ipxe script directly as image verifications will fail. + +## 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) +* **latest-stable** + * [x86](images/latest-stable/x86) + * [x86_64](images/latest-stable/x86_64) + +## 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 not trust our +signatures and will result in failed boot. + +## Boot options + +### BIOS + +* [pxe.lkrn](alpine-ipxe/ipxe.lkrn) - Linux kernel image that can be used by a bootloader/qemu +* [pxe.pxe](alpine-ipxe/ipxe.pxe) - PXE image for chainloading from a PXE environment +* [undionly.kpxe](alpine-ipxe/undionly.kpxe) - PXE image with UNDI support +* [ipxe.iso](alpine-ipxe/ipxe.iso) - ISO image to boot from any regular system + +### UEFI + +* [ipxe.efi](alpine-ipxe/ipxe.efi) x86_64 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. + +## Testing netboot + +The easiest way to test is by using Qemu directly with the ipxe kernel image. + +`apk add qemu-system-x86_64 alpine-ipxe` + +`qemu-system-x86_64 -m 512M -enable-kvm -kernel /usr/share/alpine-ipxe/ipxe.lkrn -curses` + +**NOTE**: you need a minimum of 256M of memory to boot alpine in network mode +due to the size of our initramfs and modloop (kernel modules). diff --git a/boot.ipxe b/boot.ipxe new file mode 100644 index 0000000..57127e4 --- /dev/null +++ b/boot.ipxe @@ -0,0 +1,27 @@ +#!ipxe + +set os Alpine Linux +cpuid --ext 29 && set arch x86_64 || set arch x86 + +imgtrust --permanent + +menu ${os} [ ${arch} ] +item latest-stable Latest stable +item edge Edge (development) +choose version || goto alpine_exit +goto boot + +:boot +set img-url http://boot.alpinelinux.org/images/${version}/${arch} +set repo-url http://dl-cdn.alpinelinux.org/alpine/${version}/main +imgfree +kernel ${img-url}/vmlinuz-vanilla alpine_repo=${repo-url} modules=loop,squashfs modloop=${img-url}/modloop-vanilla quiet nomodeset +imgverify vmlinuz-vanilla ${img-url}/vmlinuz-vanilla.sig +initrd ${img-url}/initramfs-vanilla +imgverify initramfs-vanilla ${img-url}/initramfs-vanilla.sig +boot +goto alpine_exit + +:alpine_exit +clear menu +exit 0 diff --git a/html/alpinelinux-logo.svg b/html/alpinelinux-logo.svg new file mode 100644 index 0000000..70f2f60 --- /dev/null +++ b/html/alpinelinux-logo.svg @@ -0,0 +1,167 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/html/favicon.ico b/html/favicon.ico new file mode 100644 index 0000000..471bba3 Binary files /dev/null and b/html/favicon.ico differ diff --git a/html/page.theme b/html/page.theme new file mode 100644 index 0000000..664ae04 --- /dev/null +++ b/html/page.theme @@ -0,0 +1,31 @@ + + + + + + + Alpine Linux netboot + + + + + +
+
+
+ +
+
+
+
+
+ +
+ +
+ + diff --git a/html/style.css b/html/style.css new file mode 100644 index 0000000..5a736ad --- /dev/null +++ b/html/style.css @@ -0,0 +1,66 @@ +html, body { + margin: 0; + padding: 0; + height: 100%; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, + sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + color: #526066; +} + +div#wrapper { + min-height: 100%; + position: relative; +} + +header { + border-bottom: 1px solid #eaecef; +} + +div.logo { + padding: 1em; +} + +.img-block { + max-width: 100%; + height: auto; + display: block; +} + +div.markdown-body { + box-sizing: border-box; + min-width: 200px; + max-width: 980px; + margin: 0 auto; + padding: 30px; + padding-bottom: 50px; +} + +div.g-4-24 { + width: 16.6667%; +} + +div.g-20-24 { + width: 83.3333%; +} + +footer { + background: #111; + color: #888; + text-align: center; + position: absolute; + bottom: 0; + width: 100%; + padding-top: 0.6em; + padding-bottom: 0.6em; + font-size: 0.6em; +} + +.pointer { + cursor: pointer; +} + +@media (max-width: 63.999em) { + .logo img { + max-width: 16em; + } +} diff --git a/html/theme.css b/html/theme.css new file mode 100644 index 0000000..e197e59 --- /dev/null +++ b/html/theme.css @@ -0,0 +1,709 @@ +@font-face { + font-family: octicons-link; + src: url(data:font/woff;charset=utf-8;base64,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) format('woff'); +} + +.markdown-body { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + line-height: 1.5; + color: #24292e; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 16px; + line-height: 1.5; + word-wrap: break-word; +} + +.markdown-body .pl-c { + color: #6a737d; +} + +.markdown-body .pl-c1, +.markdown-body .pl-s .pl-v { + color: #005cc5; +} + +.markdown-body .pl-e, +.markdown-body .pl-en { + color: #6f42c1; +} + +.markdown-body .pl-smi, +.markdown-body .pl-s .pl-s1 { + color: #24292e; +} + +.markdown-body .pl-ent { + color: #22863a; +} + +.markdown-body .pl-k { + color: #d73a49; +} + +.markdown-body .pl-s, +.markdown-body .pl-pds, +.markdown-body .pl-s .pl-pse .pl-s1, +.markdown-body .pl-sr, +.markdown-body .pl-sr .pl-cce, +.markdown-body .pl-sr .pl-sre, +.markdown-body .pl-sr .pl-sra { + color: #032f62; +} + +.markdown-body .pl-v, +.markdown-body .pl-smw { + color: #e36209; +} + +.markdown-body .pl-bu { + color: #b31d28; +} + +.markdown-body .pl-ii { + color: #fafbfc; + background-color: #b31d28; +} + +.markdown-body .pl-c2 { + color: #fafbfc; + background-color: #d73a49; +} + +.markdown-body .pl-c2::before { + content: "^M"; +} + +.markdown-body .pl-sr .pl-cce { + font-weight: bold; + color: #22863a; +} + +.markdown-body .pl-ml { + color: #735c0f; +} + +.markdown-body .pl-mh, +.markdown-body .pl-mh .pl-en, +.markdown-body .pl-ms { + font-weight: bold; + color: #005cc5; +} + +.markdown-body .pl-mi { + font-style: italic; + color: #24292e; +} + +.markdown-body .pl-mb { + font-weight: bold; + color: #24292e; +} + +.markdown-body .pl-md { + color: #b31d28; + background-color: #ffeef0; +} + +.markdown-body .pl-mi1 { + color: #22863a; + background-color: #f0fff4; +} + +.markdown-body .pl-mc { + color: #e36209; + background-color: #ffebda; +} + +.markdown-body .pl-mi2 { + color: #f6f8fa; + background-color: #005cc5; +} + +.markdown-body .pl-mdr { + font-weight: bold; + color: #6f42c1; +} + +.markdown-body .pl-ba { + color: #586069; +} + +.markdown-body .pl-sg { + color: #959da5; +} + +.markdown-body .pl-corl { + text-decoration: underline; + color: #032f62; +} + +.markdown-body .octicon { + display: inline-block; + vertical-align: text-top; + fill: currentColor; +} + +.markdown-body a { + background-color: transparent; + -webkit-text-decoration-skip: objects; +} + +.markdown-body a:active, +.markdown-body a:hover { + outline-width: 0; +} + +.markdown-body strong { + font-weight: inherit; +} + +.markdown-body strong { + font-weight: bolder; +} + +.markdown-body h1 { + font-size: 2em; + margin: 0.67em 0; +} + +.markdown-body img { + border-style: none; +} + +.markdown-body svg:not(:root) { + overflow: hidden; +} + +.markdown-body code, +.markdown-body kbd, +.markdown-body pre { + font-family: monospace, monospace; + font-size: 1em; +} + +.markdown-body hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +.markdown-body input { + font: inherit; + margin: 0; +} + +.markdown-body input { + overflow: visible; +} + +.markdown-body [type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +.markdown-body * { + box-sizing: border-box; +} + +.markdown-body input { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +.markdown-body a { + color: #0366d6; + text-decoration: none; +} + +.markdown-body a:hover { + text-decoration: underline; +} + +.markdown-body strong { + font-weight: 600; +} + +.markdown-body hr { + height: 0; + margin: 15px 0; + overflow: hidden; + background: transparent; + border: 0; + border-bottom: 1px solid #dfe2e5; +} + +.markdown-body hr::before { + display: table; + content: ""; +} + +.markdown-body hr::after { + display: table; + clear: both; + content: ""; +} + +.markdown-body table { + border-spacing: 0; + border-collapse: collapse; +} + +.markdown-body td, +.markdown-body th { + padding: 0; +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body h1 { + font-size: 32px; + font-weight: 600; +} + +.markdown-body h2 { + font-size: 24px; + font-weight: 600; +} + +.markdown-body h3 { + font-size: 20px; + font-weight: 600; +} + +.markdown-body h4 { + font-size: 16px; + font-weight: 600; +} + +.markdown-body h5 { + font-size: 14px; + font-weight: 600; +} + +.markdown-body h6 { + font-size: 12px; + font-weight: 600; +} + +.markdown-body p { + margin-top: 0; + margin-bottom: 10px; +} + +.markdown-body blockquote { + margin: 0; +} + +.markdown-body ul, +.markdown-body ol { + padding-left: 0; + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body ol ol, +.markdown-body ul ol { + list-style-type: lower-roman; +} + +.markdown-body ul ul ol, +.markdown-body ul ol ol, +.markdown-body ol ul ol, +.markdown-body ol ol ol { + list-style-type: lower-alpha; +} + +.markdown-body dd { + margin-left: 0; +} + +.markdown-body code { + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 12px; +} + +.markdown-body pre { + margin-top: 0; + margin-bottom: 0; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 12px; +} + +.markdown-body .octicon { + vertical-align: text-bottom; +} + +.markdown-body .pl-0 { + padding-left: 0 !important; +} + +.markdown-body .pl-1 { + padding-left: 4px !important; +} + +.markdown-body .pl-2 { + padding-left: 8px !important; +} + +.markdown-body .pl-3 { + padding-left: 16px !important; +} + +.markdown-body .pl-4 { + padding-left: 24px !important; +} + +.markdown-body .pl-5 { + padding-left: 32px !important; +} + +.markdown-body .pl-6 { + padding-left: 40px !important; +} + +.markdown-body::before { + display: table; + content: ""; +} + +.markdown-body::after { + display: table; + clear: both; + content: ""; +} + +.markdown-body>*:first-child { + margin-top: 0 !important; +} + +.markdown-body>*:last-child { + margin-bottom: 0 !important; +} + +.markdown-body a:not([href]) { + color: inherit; + text-decoration: none; +} + +.markdown-body .anchor { + float: left; + padding-right: 4px; + margin-left: -20px; + line-height: 1; +} + +.markdown-body .anchor:focus { + outline: none; +} + +.markdown-body p, +.markdown-body blockquote, +.markdown-body ul, +.markdown-body ol, +.markdown-body dl, +.markdown-body table, +.markdown-body pre { + margin-top: 0; + margin-bottom: 16px; +} + +.markdown-body hr { + height: 0.25em; + padding: 0; + margin: 24px 0; + background-color: #e1e4e8; + border: 0; +} + +.markdown-body blockquote { + padding: 0 1em; + color: #6a737d; + border-left: 0.25em solid #dfe2e5; +} + +.markdown-body blockquote>:first-child { + margin-top: 0; +} + +.markdown-body blockquote>:last-child { + margin-bottom: 0; +} + +.markdown-body kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: solid 1px #c6cbd1; + border-bottom-color: #959da5; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #959da5; +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + margin-top: 24px; + margin-bottom: 16px; + font-weight: 600; + line-height: 1.25; +} + +.markdown-body h1 .octicon-link, +.markdown-body h2 .octicon-link, +.markdown-body h3 .octicon-link, +.markdown-body h4 .octicon-link, +.markdown-body h5 .octicon-link, +.markdown-body h6 .octicon-link { + color: #1b1f23; + vertical-align: middle; + visibility: hidden; +} + +.markdown-body h1:hover .anchor, +.markdown-body h2:hover .anchor, +.markdown-body h3:hover .anchor, +.markdown-body h4:hover .anchor, +.markdown-body h5:hover .anchor, +.markdown-body h6:hover .anchor { + text-decoration: none; +} + +.markdown-body h1:hover .anchor .octicon-link, +.markdown-body h2:hover .anchor .octicon-link, +.markdown-body h3:hover .anchor .octicon-link, +.markdown-body h4:hover .anchor .octicon-link, +.markdown-body h5:hover .anchor .octicon-link, +.markdown-body h6:hover .anchor .octicon-link { + visibility: visible; +} + +.markdown-body h1 { + padding-bottom: 0.3em; + font-size: 2em; + border-bottom: 1px solid #eaecef; +} + +.markdown-body h2 { + padding-bottom: 0.3em; + font-size: 1.5em; + border-bottom: 1px solid #eaecef; +} + +.markdown-body h3 { + font-size: 1.25em; +} + +.markdown-body h4 { + font-size: 1em; +} + +.markdown-body h5 { + font-size: 0.875em; +} + +.markdown-body h6 { + font-size: 0.85em; + color: #6a737d; +} + +.markdown-body ul, +.markdown-body ol { + padding-left: 2em; +} + +.markdown-body ul ul, +.markdown-body ul ol, +.markdown-body ol ol, +.markdown-body ol ul { + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body li>p { + margin-top: 16px; +} + +.markdown-body li+li { + margin-top: 0.25em; +} + +.markdown-body dl { + padding: 0; +} + +.markdown-body dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: 600; +} + +.markdown-body dl dd { + padding: 0 16px; + margin-bottom: 16px; +} + +.markdown-body table { + display: block; + width: 100%; + overflow: auto; +} + +.markdown-body table th { + font-weight: 600; +} + +.markdown-body table th, +.markdown-body table td { + padding: 6px 13px; + border: 1px solid #dfe2e5; +} + +.markdown-body table tr { + background-color: #fff; + border-top: 1px solid #c6cbd1; +} + +.markdown-body table tr:nth-child(2n) { + background-color: #f6f8fa; +} + +.markdown-body img { + max-width: 100%; + box-sizing: content-box; + background-color: #fff; +} + +.markdown-body img[align=right] { + padding-left: 20px; +} + +.markdown-body img[align=left] { + padding-right: 20px; +} + +.markdown-body code { + padding: 0; + padding-top: 0.2em; + padding-bottom: 0.2em; + margin: 0; + font-size: 85%; + background-color: rgba(27,31,35,0.05); + border-radius: 3px; +} + +.markdown-body code::before, +.markdown-body code::after { + letter-spacing: -0.2em; + content: "\00a0"; +} + +.markdown-body pre { + word-wrap: normal; +} + +.markdown-body pre>code { + padding: 0; + margin: 0; + font-size: 100%; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} + +.markdown-body .highlight { + margin-bottom: 16px; +} + +.markdown-body .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.markdown-body .highlight pre, +.markdown-body pre { + padding: 16px; + overflow: auto; + font-size: 85%; + line-height: 1.45; + background-color: #f6f8fa; + border-radius: 3px; +} + +.markdown-body pre code { + display: inline; + max-width: auto; + padding: 0; + margin: 0; + overflow: visible; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; +} + +.markdown-body pre code::before, +.markdown-body pre code::after { + content: normal; +} + +.markdown-body .full-commit .btn-outline:not(:disabled):hover { + color: #005cc5; + border-color: #005cc5; +} + +.markdown-body kbd { + display: inline-block; + padding: 3px 5px; + font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: solid 1px #d1d5da; + border-bottom-color: #c6cbd1; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #c6cbd1; +} + +.markdown-body :checked+.radio-label { + position: relative; + z-index: 1; + border-color: #0366d6; +} + +.markdown-body .task-list-item { + list-style-type: none; +} + +.markdown-body .task-list-item+.task-list-item { + margin-top: 3px; +} + +.markdown-body .task-list-item input { + margin: 0 0.2em 0.25em -1.6em; + vertical-align: middle; +} + +.markdown-body hr { + border-bottom-color: #eee; +} diff --git a/mkindex.sh b/mkindex.sh new file mode 100755 index 0000000..c6dbb74 --- /dev/null +++ b/mkindex.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +htmldir="/var/www/localhost/htdocs" + +if ! command -v discount-theme >/dev/null 2>&1; then + echo "Cannot find discount-theme please install discount" + exit 1 +fi + +for i in html boot.ipxe; do + [ -L "$htmldir/$i" ] || ln -s "$(realpath $i)" "$htmldir" +done + +discount-theme -t html/page.theme \ + -o "$htmldir"/index.html README.md diff --git a/mknetboot.sh b/mknetboot.sh new file mode 100755 index 0000000..91087de --- /dev/null +++ b/mknetboot.sh @@ -0,0 +1,76 @@ +#!/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 + +rm -f "$REPOFILE" diff --git a/update-netboot.sh b/update-netboot.sh new file mode 100755 index 0000000..a23677a --- /dev/null +++ b/update-netboot.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +REPO="http://dl-cdn.alpinelinux.org/alpine" +BRANCHES="edge latest-stable" +ARCHS="x86 x86_64" +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) + 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\n" + rm -f $tmpfile + fi + done +done -- cgit v1.2.3