mirror of
https://github.com/immich-app/retro.git
synced 2026-09-30 13:23:07 +08:00
wip
This commit is contained in:
+4
-3
@@ -1,3 +1,4 @@
|
||||
overlay/usr/app/images/*.tar
|
||||
immich.apkovl.tar.gz
|
||||
mkimage.sh
|
||||
overlay/var/lib/docker
|
||||
build/
|
||||
out/
|
||||
.overlay-build/
|
||||
@@ -1,32 +1,21 @@
|
||||
Steps to build:
|
||||
# Immich-retro
|
||||
|
||||
1. Fire up a local alpine image on Docker:
|
||||
## How to build
|
||||
|
||||
Run the following from the root of this repository
|
||||
|
||||
```bash
|
||||
docker run --rm -it -v "$(pwd)":/home alpine sh
|
||||
docker run --rm -it -v "$(pwd)":/home --privileged alpine sh ./home/build.sh
|
||||
```
|
||||
|
||||
2. Inside the container, run
|
||||
The built image will be placed in `out/`
|
||||
|
||||
```bash
|
||||
apk add alpine-sdk abuild
|
||||
```
|
||||
### A couple of notes:
|
||||
|
||||
3. Run
|
||||
|
||||
```bash
|
||||
tar --numeric-owner --owner=0 --group=0 -cf root-overlay.tar -C overlay .
|
||||
```
|
||||
|
||||
3. Run
|
||||
|
||||
```bash
|
||||
./mkimage.sh --tag immich \
|
||||
--outdir out \
|
||||
--arch x86_64 \
|
||||
--repository https://dl-cdn.alpinelinux.org/alpine/latest-stable/main \
|
||||
--profile immich
|
||||
|
||||
```
|
||||
|
||||
4.
|
||||
- The entirety of the operating system runs from RAM. No configuration, assets, or settings will be persisted on reboot of the machine. DO NOT use this as your main Immich instance.
|
||||
- All assets are stored in RAM so you may quickly run out of "storage" if your machine has less than 16GB of RAM.
|
||||
- If booting from the DVD, the boot process **will be slow**. You may see "0%" for a prolonged period of time during boot. _Be patient!_. This part of the boot process requires reading the entire DVD and loading it into RAM.
|
||||
- Minimum system requirements:
|
||||
- 2 core x86 processor
|
||||
- 8GB of RAM, 16GB recommended
|
||||
- No storage drive needed!
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
apk add alpine-sdk alpine-conf xorriso squashfs-tools grub grub-efi doas docker openrc fuse-overlayfs mtools dosfstools grub-efi
|
||||
|
||||
echo "permit persist root" > /etc/doas.d/doas.conf
|
||||
echo "permit nopass root" >> /etc/doas.d/doas.conf
|
||||
|
||||
addgroup build docker
|
||||
|
||||
# su - build -c "
|
||||
abuild-keygen -i -a -n
|
||||
apk update
|
||||
|
||||
cd /home
|
||||
./scripts/mkimage.sh --tag immich --outdir out --arch x86_64 --repository https://dl-cdn.alpinelinux.org/alpine/latest-stable/main --repository https://dl-cdn.alpinelinux.org/alpine/latest-stable/community --profile immich
|
||||
@@ -0,0 +1,6 @@
|
||||
docker run -d --privileged \
|
||||
--name dind-test \
|
||||
-v "$(pwd)":/home \
|
||||
-v "$(pwd)/overlay/var/lib/docker":/var/lib/docker \
|
||||
-e DOCKER_TLS_CERTDIR= \
|
||||
docker:dind
|
||||
@@ -0,0 +1,22 @@
|
||||
# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables
|
||||
|
||||
# The location where your uploaded files are stored
|
||||
UPLOAD_LOCATION=./library
|
||||
|
||||
# The location where your database files are stored. Network shares are not supported for the database
|
||||
DB_DATA_LOCATION=./postgres
|
||||
|
||||
# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
||||
# TZ=Etc/UTC
|
||||
|
||||
# The Immich version to use. You can pin this to a specific version like "v1.71.0"
|
||||
IMMICH_VERSION=release
|
||||
|
||||
# Connection secret for postgres. You should change it to a random password
|
||||
# Please use only the characters `A-Za-z0-9`, without special characters or spaces
|
||||
DB_PASSWORD=postgres
|
||||
|
||||
# The values below this line do not need to be changed
|
||||
###################################################################################
|
||||
DB_USERNAME=postgres
|
||||
DB_DATABASE_NAME=immich
|
||||
@@ -0,0 +1,74 @@
|
||||
#
|
||||
# WARNING: To install Immich, follow our guide: https://immich.app/docs/install/docker-compose
|
||||
#
|
||||
# Make sure to use the docker-compose.yml of the current release:
|
||||
#
|
||||
# https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
|
||||
#
|
||||
# The compose file on main may not be compatible with the latest release.
|
||||
|
||||
name: immich
|
||||
|
||||
services:
|
||||
immich-server:
|
||||
container_name: immich_server
|
||||
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
|
||||
# extends:
|
||||
# file: hwaccel.transcoding.yml
|
||||
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
|
||||
volumes:
|
||||
# Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file
|
||||
- ${UPLOAD_LOCATION}:/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "2283:2283"
|
||||
depends_on:
|
||||
- redis
|
||||
- database
|
||||
restart: always
|
||||
healthcheck:
|
||||
disable: false
|
||||
|
||||
immich-machine-learning:
|
||||
container_name: immich_machine_learning
|
||||
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
|
||||
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
||||
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
||||
# extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
|
||||
# file: hwaccel.ml.yml
|
||||
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
||||
volumes:
|
||||
- model-cache:/cache
|
||||
env_file:
|
||||
- .env
|
||||
restart: always
|
||||
healthcheck:
|
||||
disable: false
|
||||
|
||||
redis:
|
||||
container_name: immich_redis
|
||||
image: docker.io/valkey/valkey:8-bookworm@sha256:facc1d2c3462975c34e10fccb167bfa92b0e0dbd992fc282c29a61c3243afb11
|
||||
healthcheck:
|
||||
test: redis-cli ping || exit 1
|
||||
restart: always
|
||||
|
||||
database:
|
||||
container_name: immich_postgres
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
POSTGRES_USER: ${DB_USERNAME}
|
||||
POSTGRES_DB: ${DB_DATABASE_NAME}
|
||||
POSTGRES_INITDB_ARGS: "--data-checksums"
|
||||
# Uncomment the DB_STORAGE_TYPE: 'HDD' var if your database isn't stored on SSDs
|
||||
# DB_STORAGE_TYPE: 'HDD'
|
||||
volumes:
|
||||
# Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file
|
||||
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
||||
shm_size: 128mb
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
model-cache:
|
||||
@@ -0,0 +1,3 @@
|
||||
The following folder contains the contents of the `scripts/` folder from https://gitlab.alpinelinux.org/alpine/aports.git
|
||||
|
||||
`mkimage.immich.sh` defines the configuration for the Immich custom ISO
|
||||
Executable
+173
@@ -0,0 +1,173 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
abuild_opts="-r"
|
||||
if [ "$1" = "-k" ] || [ "$1" = "--keep" ]; then
|
||||
abuild_opts="$abuild_opts -k"
|
||||
shift
|
||||
fi
|
||||
|
||||
TARGET_ARCH="$1"
|
||||
SUDO_APK=abuild-apk
|
||||
|
||||
shift
|
||||
|
||||
# optional cross build packages
|
||||
#: ${KERNEL_PKG=linux-firmware linux-lts}
|
||||
#: ${COMPILER_PKG=libffi brotli libev c-ares cunit nghttp2 libidn2 libunistring libpsl curl libssh2 libxml2 llvm15 community/ghc llvm20 rust community/go}
|
||||
# FIXME: Maybe subdivide into ghc, rust, and go stuff
|
||||
: ${MKINITFS=libcap-ng ncurses readline sqlite util-linux libaio lvm2 popt xz json-c argon2 cryptsetup kmod lddtree mkinitfs pax-utils}
|
||||
#: ${OPENSSH=openssh}
|
||||
|
||||
if [ -z "$TARGET_ARCH" ]; then
|
||||
program=$(basename $0)
|
||||
cat <<EOF
|
||||
usage: $program TARGET_ARCH
|
||||
|
||||
This script creates a local cross-compiler, and uses it to
|
||||
cross-compile an Alpine Linux base system for new architecture.
|
||||
|
||||
Steps for introducing new architecture include:
|
||||
- adding the compiler triplet and arch type to abuild
|
||||
- adjusting build rules for packages that are arch aware:
|
||||
gcc, openssl, linux-headers, musl
|
||||
- create new kernel config for linux-lts
|
||||
- optionally reserve an architecture name in apk-tools
|
||||
|
||||
After these steps the initial cross-build can be completed
|
||||
by running this with the target arch as parameter, e.g.:
|
||||
./$program aarch64
|
||||
|
||||
The cross-compiler generated by this script is not intended
|
||||
nor supported for any use other than building the base system
|
||||
and other packages in the bootstrap path.
|
||||
|
||||
EOF
|
||||
return 1
|
||||
fi
|
||||
|
||||
# get abuild configurables
|
||||
sharedir=${ABUILD_SHAREDIR:-/usr/share/abuild}
|
||||
[ -e "$sharedir"/functions.sh ] || (echo "abuild not found" ; exit 1)
|
||||
CBUILDROOT="$(CTARGET=$TARGET_ARCH . "$sharedir"/functions.sh ; echo $CBUILDROOT)"
|
||||
. "$sharedir"/functions.sh
|
||||
[ -z "$CBUILD_ARCH" ] && die "abuild is too old (use 2.29.0 or later)"
|
||||
[ -z "$CBUILDROOT" ] && die "CBUILDROOT not set for $TARGET_ARCH"
|
||||
export CBUILD
|
||||
|
||||
# deduce aports directory
|
||||
[ -z "$APORTS" ] && APORTS=$(realpath $(dirname $0)/../)
|
||||
[ -e "$APORTS/main/build-base" ] || die "Unable to deduce aports base checkout"
|
||||
|
||||
apkbuildname() {
|
||||
local repo="${1%%/*}"
|
||||
local pkg="${1##*/}"
|
||||
[ "$repo" = "$1" ] && repo="main"
|
||||
echo $APORTS/$repo/$pkg/APKBUILD
|
||||
}
|
||||
|
||||
msg() {
|
||||
[ -n "$quiet" ] && return 0
|
||||
local prompt="$GREEN>>>${NORMAL}"
|
||||
local name="${BLUE}bootstrap-${TARGET_ARCH}${NORMAL}"
|
||||
printf "${prompt} ${name}: %s\n" "$1" >&2
|
||||
}
|
||||
|
||||
if [ ! -d "$CBUILDROOT" ]; then
|
||||
msg "Creating sysroot in $CBUILDROOT"
|
||||
mkdir -p "$CBUILDROOT/etc/apk/keys"
|
||||
# /etc/apk/keys and ~/.abuild/ can contain files with the same names.
|
||||
# if that is the case, cp will abort copying and fail. Then on the next
|
||||
# run of the bootstrap script, 1) the keys are not in the sysroot and
|
||||
# 2) the apk database is not initialized the sysroot
|
||||
# Thus it's unusable at that point and needs to be deleted manually.
|
||||
cp -a /etc/apk/keys/* "$CBUILDROOT/etc/apk/keys"
|
||||
cp -a ~/.abuild/*.pub "$CBUILDROOT/etc/apk/keys"
|
||||
${SUDO_APK} add --quiet --initdb --arch $TARGET_ARCH --root $CBUILDROOT
|
||||
fi
|
||||
|
||||
msg "Building cross-compiler"
|
||||
|
||||
# Build and install cross binutils (--with-sysroot)
|
||||
CTARGET=$TARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname binutils) abuild $abuild_opts
|
||||
|
||||
if ! CHOST=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild up2date 2>/dev/null; then
|
||||
# C-library headers for target
|
||||
CHOST=$TARGET_ARCH BOOTSTRAP=nocc APKBUILD=$(apkbuildname musl) abuild $abuild_opts
|
||||
|
||||
# Minimal cross GCC
|
||||
EXTRADEPENDS_HOST="musl-dev" \
|
||||
CTARGET=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname gcc) abuild $abuild_opts
|
||||
|
||||
# Cross build bootstrap C-library for the target
|
||||
EXTRADEPENDS_BUILD="gcc-pass2-$TARGET_ARCH" \
|
||||
CHOST=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild $abuild_opts
|
||||
fi
|
||||
|
||||
# Build libucontext without docs and pkgconfig file as a dependency for gcc-gdc
|
||||
EXTRADEPENDS_BUILD="gcc-pass2-$TARGET_ARCH" \
|
||||
EXTRADEPENDS_TARGET="musl musl-dev" \
|
||||
CHOST=$TARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname libucontext) abuild $abuild_opts
|
||||
|
||||
# Full cross GCC
|
||||
EXTRADEPENDS_TARGET="musl musl-dev libucontext-dev" \
|
||||
CTARGET=$TARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname gcc) abuild $abuild_opts
|
||||
|
||||
# Cross build-base
|
||||
CTARGET=$TARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname build-base) abuild $abuild_opts
|
||||
|
||||
msg "Cross building base system"
|
||||
|
||||
# Implicit dependencies for early targets
|
||||
EXTRADEPENDS_TARGET="libgcc libstdc++ musl-dev"
|
||||
|
||||
# On a few architectures like riscv64 we need to account for
|
||||
# gcc requiring -ltomic to be set explicitly if a C[++]11 program
|
||||
# uses atomics (e.g. #include <atomic>):
|
||||
# https://github.com/riscv/riscv-gnu-toolchain/issues/183#issuecomment-253721765
|
||||
# The reason gcc itself is needed is because .so is in that package,
|
||||
# not in libatomic.
|
||||
if [ "$TARGET_ARCH" = "riscv64" ]; then
|
||||
NEEDS_LIBATOMIC="yes"
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
set -- fortify-headers linux-headers musl pkgconf zlib \
|
||||
openssl ca-certificates libmd \
|
||||
gmp mpfr4 mpc1 isl26 libucontext zstd binutils gcc \
|
||||
bsd-compat-headers libbsd busybox make \
|
||||
apk-tools file \
|
||||
libcap openrc alpine-conf alpine-baselayout alpine-keys alpine-base patch build-base \
|
||||
attr acl fakeroot tar \
|
||||
lzip abuild \
|
||||
$OPENSSH \
|
||||
$MKINITFS \
|
||||
$COMPILER_PKG \
|
||||
$KERNEL_PKG
|
||||
fi
|
||||
|
||||
for PKG; do
|
||||
|
||||
if [ "$NEEDS_LIBATOMIC" = "yes" ]; then
|
||||
EXTRADEPENDS_BUILD="libatomic gcc-$TARGET_ARCH g++-$TARGET_ARCH"
|
||||
fi
|
||||
EXTRADEPENDS_TARGET="$EXTRADEPENDS_TARGET" EXTRADEPENDS_BUILD="$EXTRADEPENDS_BUILD" \
|
||||
CHOST=$TARGET_ARCH BOOTSTRAP=bootimage APKBUILD=$(apkbuildname $PKG) abuild $abuild_opts
|
||||
|
||||
case "$PKG" in
|
||||
fortify-headers)
|
||||
# Additional implicit dependencies once built
|
||||
EXTRADEPENDS_TARGET="$EXTRADEPENDS_TARGET $PKG"
|
||||
;;
|
||||
gcc)
|
||||
if [ "$NEEDS_LIBATOMIC" = "yes" ]; then
|
||||
EXTRADEPENDS_TARGET="libatomic gcc $EXTRADEPENDS_TARGET"
|
||||
fi
|
||||
;;
|
||||
build-base)
|
||||
# After build-base, that alone is sufficient dependency in the target
|
||||
EXTRADEPENDS_TARGET="busybox $PKG"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
HOSTNAME="$1"
|
||||
if [ -z "$HOSTNAME" ]; then
|
||||
echo "usage: $0 hostname"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
makefile() {
|
||||
OWNER="$1"
|
||||
PERMS="$2"
|
||||
FILENAME="$3"
|
||||
cat > "$FILENAME"
|
||||
chown "$OWNER" "$FILENAME"
|
||||
chmod "$PERMS" "$FILENAME"
|
||||
}
|
||||
|
||||
rc_add() {
|
||||
mkdir -p "$tmp"/etc/runlevels/"$2"
|
||||
ln -sf /etc/init.d/"$1" "$tmp"/etc/runlevels/"$2"/"$1"
|
||||
}
|
||||
|
||||
tmp="$(mktemp -d)"
|
||||
trap cleanup EXIT
|
||||
|
||||
mkdir -p "$tmp"/etc
|
||||
makefile root:root 0644 "$tmp"/etc/hostname <<EOF
|
||||
$HOSTNAME
|
||||
EOF
|
||||
|
||||
mkdir -p "$tmp"/etc/network
|
||||
makefile root:root 0644 "$tmp"/etc/network/interfaces <<EOF
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet dhcp
|
||||
EOF
|
||||
|
||||
mkdir -p "$tmp"/etc/apk
|
||||
makefile root:root 0644 "$tmp"/etc/apk/world <<EOF
|
||||
alpine-base
|
||||
EOF
|
||||
|
||||
rc_add devfs sysinit
|
||||
rc_add dmesg sysinit
|
||||
rc_add mdev sysinit
|
||||
rc_add hwdrivers sysinit
|
||||
rc_add modloop sysinit
|
||||
|
||||
rc_add hwclock boot
|
||||
rc_add modules boot
|
||||
rc_add sysctl boot
|
||||
rc_add hostname boot
|
||||
rc_add bootmisc boot
|
||||
rc_add syslog boot
|
||||
|
||||
rc_add mount-ro shutdown
|
||||
rc_add killprocs shutdown
|
||||
rc_add savecache shutdown
|
||||
|
||||
tar -c -C "$tmp" etc | gzip -9n > $HOSTNAME.apkovl.tar.gz
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
HOSTNAME="$1"
|
||||
if [ -z "$HOSTNAME" ]; then
|
||||
echo "usage: $0 hostname"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
makefile() {
|
||||
OWNER="$1"
|
||||
PERMS="$2"
|
||||
FILENAME="$3"
|
||||
cat > "$FILENAME"
|
||||
chown "$OWNER" "$FILENAME"
|
||||
chmod "$PERMS" "$FILENAME"
|
||||
}
|
||||
|
||||
rc_add() {
|
||||
mkdir -p "$tmp"/etc/runlevels/"$2"
|
||||
ln -sf /etc/init.d/"$1" "$tmp"/etc/runlevels/"$2"/"$1"
|
||||
}
|
||||
|
||||
tmp="$(mktemp -d)"
|
||||
trap cleanup EXIT
|
||||
|
||||
mkdir -p "$tmp"/etc
|
||||
makefile root:root 0644 "$tmp"/etc/hostname <<EOF
|
||||
$HOSTNAME
|
||||
EOF
|
||||
|
||||
makefile root:root 0644 "$tmp"/etc/modules <<EOF
|
||||
xen_netback
|
||||
xen_blkback
|
||||
xenfs
|
||||
xen-platform-pci
|
||||
xen_wdt
|
||||
tun
|
||||
EOF
|
||||
|
||||
mkdir -p "$tmp"/etc/network
|
||||
makefile root:root 0644 "$tmp"/etc/network/interfaces <<EOF
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
EOF
|
||||
|
||||
mkdir -p "$tmp"/etc/apk
|
||||
|
||||
makefile root:root 0644 "$tmp"/etc/apk/world <<EOF
|
||||
xen
|
||||
EOF
|
||||
|
||||
rc_add devfs sysinit
|
||||
rc_add dmesg sysinit
|
||||
rc_add udev sysinit
|
||||
|
||||
rc_add hwclock boot
|
||||
rc_add modules boot
|
||||
rc_add sysctl boot
|
||||
rc_add hostname boot
|
||||
rc_add bootmisc boot
|
||||
rc_add syslog boot
|
||||
|
||||
rc_add udev-postmount default
|
||||
rc_add xenstored default
|
||||
rc_add xenconsoled default
|
||||
|
||||
rc_add mount-ro shutdown
|
||||
rc_add killprocs shutdown
|
||||
rc_add savecache shutdown
|
||||
|
||||
tar -c -C "$tmp" etc | gzip -9n > $HOSTNAME.apkovl.tar.gz
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
tmp="$(mktemp -d)"
|
||||
trap cleanup EXIT
|
||||
chmod 0755 "$tmp"
|
||||
|
||||
arch="$(apk --print-arch)"
|
||||
repositories_file=/etc/apk/repositories
|
||||
keys_dir=/etc/apk/keys
|
||||
|
||||
while getopts "a:r:k:o:" opt; do
|
||||
case $opt in
|
||||
a) arch="$OPTARG";;
|
||||
r) repositories_file="$OPTARG";;
|
||||
k) keys_dir="$OPTARG";;
|
||||
o) outfile="$OPTARG";;
|
||||
esac
|
||||
done
|
||||
shift $(( $OPTIND - 1))
|
||||
|
||||
cat "$repositories_file"
|
||||
|
||||
if [ -z "$outfile" ]; then
|
||||
outfile=rootfs-$arch.tar.gz
|
||||
fi
|
||||
|
||||
${APK:-apk} add --keys-dir "$keys_dir" --no-cache \
|
||||
--repositories-file "$repositories_file" \
|
||||
--no-script --root "$tmp" --initdb --arch "$arch" \
|
||||
"$@"
|
||||
|
||||
rm -f "$tmp"/var/log/apk.log
|
||||
|
||||
for link in $("$tmp"/bin/busybox --list-full); do
|
||||
[ -e "$tmp"/$link ] || ln -s /bin/busybox "$tmp"/$link
|
||||
done
|
||||
|
||||
# disable password login but allow login with ssh keys for root
|
||||
sed -i -e 's/^root::/root:*:/' "$tmp"/etc/shadow
|
||||
# Set shadow group manually since we use --no-script above
|
||||
# Use gid since we use --numeric-owner below
|
||||
chgrp 42 "$tmp"/etc/shadow
|
||||
|
||||
branch=edge
|
||||
VERSION_ID=$(awk -F= '$1=="VERSION_ID" {print $2}' "$tmp"/etc/os-release)
|
||||
case $VERSION_ID in
|
||||
*_alpha*|*_beta*) branch=edge;;
|
||||
*.*.*) branch=v${VERSION_ID%.*};;
|
||||
esac
|
||||
|
||||
cat > "$tmp"/etc/apk/repositories <<EOF
|
||||
https://dl-cdn.alpinelinux.org/alpine/$branch/main
|
||||
https://dl-cdn.alpinelinux.org/alpine/$branch/community
|
||||
EOF
|
||||
|
||||
tar --numeric-owner --exclude='dev/*' -c -C "$tmp" . | gzip -9n > "$outfile"
|
||||
Executable
+93
@@ -0,0 +1,93 @@
|
||||
#!/bin/sh
|
||||
|
||||
progname=$(basename $0)
|
||||
|
||||
usage() {
|
||||
echo "usage: $progname --checksums <checksums> --arch <arch> FILE..."
|
||||
}
|
||||
|
||||
checksums="sha256 sha512"
|
||||
while [ $# -gt 0 ]; do
|
||||
opt="$1"
|
||||
shift
|
||||
case "$opt" in
|
||||
--checksums) checksums="$1"; shift ;;
|
||||
--arch) arch="$1"; shift ;;
|
||||
--branch) branch="$1"; shift;;
|
||||
--release) release="$1"; shift;;
|
||||
--flavor) flavor="$1"; shift;;
|
||||
--title) title="$1"; shift;;
|
||||
--desc) desc="$1"; shift;;
|
||||
--) break ;;
|
||||
-*) usage; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
set -- $opt "$@"
|
||||
|
||||
if [ -z "$branch" ]; then
|
||||
case "$release" in
|
||||
*.*.*_alpha*|*.*.*_beta*) branch=edge;;
|
||||
*.*.*) branch=${release%.*}; branch="v${branch#v}";;
|
||||
*)
|
||||
git_branch="$(git rev-parse --abbrev-ref HEAD)"
|
||||
case "$git_branch" in
|
||||
*-stable) branch=${git_branch%-stable};;
|
||||
*) branch=edge;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
releasedir="$branch/releases/$arch"
|
||||
|
||||
[ -n "$arch" ] || arch=$(apk --print-arch)
|
||||
|
||||
# size_and_sum [file] [prefix]
|
||||
size_and_sum() {
|
||||
echo " ${2}size: $(stat -c "%s" "$1")"
|
||||
for hash in ${checksums}; do
|
||||
# generate checksums if missing
|
||||
if ! [ -f "$1.$hash" ]; then
|
||||
${hash}sum "$1" | sed 's: .*/: :' > "$1.$hash"
|
||||
fi
|
||||
echo " $2$hash: $(cut -d' ' -f1 $1.$hash)"
|
||||
done
|
||||
}
|
||||
|
||||
for image; do
|
||||
filepath="$releasedir/${image##*/}"
|
||||
datetime="$(stat -c "%y" $image)"
|
||||
size="$(stat -c "%s" $image)"
|
||||
date=${datetime%% *}
|
||||
time=${datetime#* }
|
||||
time=${time%.*}
|
||||
file=${filepath##*/}
|
||||
flavor=${file%-${release}-${arch}.*}
|
||||
desc=$(echo "$desc" | sed -E 's/^\s*/ /')
|
||||
|
||||
cat <<-EOF
|
||||
-
|
||||
title: "$title"
|
||||
desc: |
|
||||
$desc
|
||||
branch: $branch
|
||||
arch: $arch
|
||||
version: $release
|
||||
flavor: $flavor
|
||||
file: $file
|
||||
iso: $file
|
||||
date: $date
|
||||
time: $time
|
||||
EOF
|
||||
size_and_sum "$image"
|
||||
|
||||
case "$file" in
|
||||
*.img.gz)
|
||||
extracted=${image%.gz}
|
||||
if ! [ -f "$extracted" ]; then
|
||||
zcat < "$image" > "$extracted"
|
||||
fi
|
||||
size_and_sum "$extracted" extracted_
|
||||
;;
|
||||
esac
|
||||
done
|
||||
Executable
+332
@@ -0,0 +1,332 @@
|
||||
#!/bin/sh
|
||||
|
||||
# apk add \
|
||||
# abuild apk-tools alpine-conf busybox fakeroot syslinux xorriso cmd:mksquashfs
|
||||
# (for efi:) mtools grub
|
||||
# (for s390x:) s390-tools
|
||||
# (for ppc64le:) grub
|
||||
|
||||
# FIXME: clean workdir out of unneeded sections
|
||||
# FIXME: --release: cp/mv images to REPODIR/$ARCH/releases/
|
||||
# FIXME: --update-latest: rewrite latest-releases.yaml with this build
|
||||
|
||||
set -e
|
||||
|
||||
# get abuild configurables
|
||||
. "${ABUILD_SHAREDIR:-/usr/share/abuild}"/functions.sh
|
||||
|
||||
scriptdir="$(dirname "$0")"
|
||||
git=$(command -v git) || git=true
|
||||
|
||||
# echo '-dirty' if git is not clean
|
||||
git_dirty() {
|
||||
[ $($git status -s -- "$scriptdir" | wc -l) -ne 0 ] && echo "-dirty"
|
||||
}
|
||||
|
||||
# echo last commit hash id
|
||||
git_last_commit() {
|
||||
$git log --format=oneline -n 1 -- "$scriptdir" | awk '{print $1}'
|
||||
}
|
||||
|
||||
# date of last commit
|
||||
git_last_commit_epoch() {
|
||||
$git log -1 --format=%cd --date=unix "$1" -- "$scriptdir"
|
||||
}
|
||||
|
||||
set_source_date() {
|
||||
# dont error out if we're not in git
|
||||
if ! $git rev-parse --show-toplevel >/dev/null 2>&1; then
|
||||
git=true
|
||||
fi
|
||||
# set time stamp for reproducible builds
|
||||
if [ -z "$ABUILD_LAST_COMMIT" ]; then
|
||||
export ABUILD_LAST_COMMIT="$(git_last_commit)$(git_dirty)"
|
||||
fi
|
||||
if [ -z "$SOURCE_DATE_EPOCH" ] && [ "${ABUILD_LAST_COMMIT%-dirty}" = "$ABUILD_LAST_COMMIT" ]; then
|
||||
SOURCE_DATE_EPOCH=$(git_last_commit_epoch "$ABUILD_LAST_COMMIT")
|
||||
fi
|
||||
if [ -z "$SOURCE_DATE_EPOCH" ]; then
|
||||
SOURCE_DATE_EPOCH=$(date -u "+%s")
|
||||
fi
|
||||
export SOURCE_DATE_EPOCH
|
||||
}
|
||||
|
||||
set_source_date
|
||||
|
||||
#
|
||||
all_sections=""
|
||||
all_profiles=""
|
||||
all_checksums="sha256 sha512"
|
||||
all_dirs=""
|
||||
build_date="$(date -u +%y%m%d -d "@$SOURCE_DATE_EPOCH")"
|
||||
default_arch="$(apk --print-arch)"
|
||||
_hostkeys=""
|
||||
_simulate=""
|
||||
_checksum=""
|
||||
|
||||
OUTDIR="$PWD"
|
||||
RELEASE="${build_date}"
|
||||
|
||||
|
||||
msg() {
|
||||
if [ -n "$quiet" ]; then return 0; fi
|
||||
local prompt="$GREEN>>>${NORMAL}"
|
||||
local name="${BLUE}mkimage${ARCH+-$ARCH}${NORMAL}"
|
||||
printf "${prompt} ${name}: %s\n" "$1" >&2
|
||||
}
|
||||
|
||||
list_has() {
|
||||
local needle="$1"
|
||||
local i
|
||||
shift
|
||||
for i in $@; do
|
||||
[ "$needle" != "$i" ] || return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
|
||||
$0 [--tag RELEASE] [--outdir OUTDIR] [--workdir WORKDIR]
|
||||
[--arch ARCH] [--profile PROFILE] [--hostkeys] [--simulate]
|
||||
[--repository REPO [--repository REPO]]
|
||||
[--repositories-file REPO_FILE] [--yaml FILE]
|
||||
$0 --help
|
||||
|
||||
options:
|
||||
--arch Specify which architecture images to build
|
||||
(default: $default_arch)
|
||||
--hostkeys Copy system apk signing keys to created images
|
||||
--outdir Specify directory for the created images
|
||||
--profile Specify which profiles to build
|
||||
--repositories-file List of repositories to use for the image create
|
||||
--repository Package repository to use for the image create
|
||||
--simulate Don't execute commands
|
||||
--tag Build images for tag RELEASE
|
||||
--workdir Specify temporary working directory (cache)
|
||||
--yaml
|
||||
|
||||
known profiles: $(echo $all_profiles | sort -u)
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# helpers
|
||||
load_plugins() {
|
||||
local f
|
||||
[ -e "$1" ] || return 0
|
||||
for f in "$1"/mkimg.*.sh; do
|
||||
[ -e "$f" ] || return 0
|
||||
break
|
||||
done
|
||||
all_profiles="$all_profiles $(sed -n -e 's/^profile_\(.*\)() {$/\1/p' $1/mkimg.*.sh)"
|
||||
all_sections="$all_sections $(sed -n -e 's/^section_\(.*\)() {$/\1/p' $1/mkimg.*.sh)"
|
||||
for f in "$1"/mkimg.*.sh; do
|
||||
. $f
|
||||
done
|
||||
}
|
||||
|
||||
checksum() {
|
||||
sha1sum | cut -f 1 -d ' '
|
||||
}
|
||||
|
||||
build_section() {
|
||||
local section="$1"
|
||||
local args="$@"
|
||||
local _dir="${args//[^a-zA-Z0-9]/_}"
|
||||
shift
|
||||
local args="$@"
|
||||
|
||||
if [ -z "$_dir" ]; then
|
||||
_fail="yes"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -e "$WORKDIR/${_dir}" ]; then
|
||||
DESTDIR="$WORKDIR/${_dir}.work"
|
||||
msg "--> $section $args"
|
||||
if [ -z "$_simulate" ]; then
|
||||
rm -rf "$DESTDIR"
|
||||
mkdir -p "$DESTDIR"
|
||||
if build_${section} "$@"; then
|
||||
mv "$DESTDIR" "$WORKDIR/${_dir}"
|
||||
_dirty="yes"
|
||||
else
|
||||
rm -rf "$DESTDIR"
|
||||
_fail="yes"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
unset DESTDIR
|
||||
all_dirs="$all_dirs $_dir"
|
||||
_my_sections="$_my_sections $_dir"
|
||||
}
|
||||
|
||||
build_profile() {
|
||||
local _id _dir _spec
|
||||
_my_sections=""
|
||||
_dirty="no"
|
||||
_fail="no"
|
||||
|
||||
profile_$PROFILE
|
||||
list_has $ARCH $arch || return 0
|
||||
|
||||
msg "Building $PROFILE"
|
||||
|
||||
# Collect list of needed sections, and make sure they are built
|
||||
for SECTION in $all_sections; do
|
||||
section_$SECTION || return 1
|
||||
done
|
||||
[ "$_fail" = "no" ] || return 1
|
||||
|
||||
# Defaults
|
||||
[ -n "$image_name" ] || image_name="alpine-${PROFILE}"
|
||||
[ -n "$output_filename" ] || output_filename="${image_name}-${RELEASE}-${ARCH}.${image_ext}"
|
||||
local output_file="${OUTDIR:-.}/$output_filename"
|
||||
|
||||
# Construct final image
|
||||
local _imgid=$(echo -n $_my_sections | sort | checksum)
|
||||
DESTDIR=$WORKDIR/image-$_imgid-$ARCH-$PROFILE
|
||||
if [ "$_dirty" = "yes" -o ! -e "$DESTDIR" ]; then
|
||||
msg "Creating $output_filename"
|
||||
if [ -z "$_simulate" ]; then
|
||||
# Merge sections
|
||||
rm -rf "$DESTDIR"
|
||||
mkdir -p "$DESTDIR"
|
||||
for _dir in $_my_sections; do
|
||||
for _fn in $WORKDIR/$_dir/*; do
|
||||
[ ! -e "$_fn" ] || cp -Lrs $_fn $DESTDIR/
|
||||
done
|
||||
done
|
||||
echo "${image_name}-${RELEASE} ${build_date}" > "$DESTDIR"/.alpine-release
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$_dirty" = "yes" -o ! -e "$output_file" ]; then
|
||||
# Create image
|
||||
[ -n "$output_format" ] || output_format="${image_ext//[:\.]/}"
|
||||
create_image_${output_format} || { _fail="yes"; return 1; }
|
||||
|
||||
if [ "$_checksum" = "yes" ]; then
|
||||
for _c in $all_checksums; do
|
||||
echo "$(${_c}sum "$output_file" | cut -d' ' -f1) ${output_filename}" > "${output_file}.${_c}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if [ -n "$_yaml_out" ]; then
|
||||
$mkimage_yaml --release $RELEASE \
|
||||
--title "$title" \
|
||||
--desc "$desc" \
|
||||
"$output_file" >> "$_yaml_out"
|
||||
fi
|
||||
}
|
||||
|
||||
# load plugins
|
||||
load_plugins "$scriptdir"
|
||||
[ -z "$HOME" ] || load_plugins "$HOME/.mkimage"
|
||||
|
||||
mkimage_yaml="$(dirname $0)"/mkimage-yaml.sh
|
||||
|
||||
# parse parameters
|
||||
while [ $# -gt 0 ]; do
|
||||
opt="$1"
|
||||
shift
|
||||
case "$opt" in
|
||||
--repositories-file) REPOS_FILE="$1"; shift ;;
|
||||
--repository)
|
||||
if [ -z "$REPOS" ]; then
|
||||
REPOS="$1"
|
||||
else
|
||||
REPOS=$(printf '%s\n%s' "$REPOS" "$1");
|
||||
fi
|
||||
shift ;;
|
||||
--extra-repository)
|
||||
warning "--extra-repository is deprecated. Use multiple --repository"
|
||||
EXTRAREPOS="$EXTRAREPOS $1"
|
||||
shift ;;
|
||||
--workdir) WORKDIR="$1"; shift ;;
|
||||
--outdir) OUTDIR="$1"; shift ;;
|
||||
--tag) RELEASE="$1"; shift ;;
|
||||
--arch) req_arch="$1"; shift ;;
|
||||
--profile) req_profiles="$1"; shift ;;
|
||||
--hostkeys) _hostkeys="--hostkeys";;
|
||||
--simulate) _simulate="yes";;
|
||||
--checksum) _checksum="yes";;
|
||||
--yaml) _yaml="yes";;
|
||||
--help) usage; exit 0;;
|
||||
--) break ;;
|
||||
-*) usage; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$RELEASE" ]; then
|
||||
if git describe --exact-match >/dev/null 2>&1; then
|
||||
RELEASE=$(git describe --always)
|
||||
RELEASE=${RELEASE#v}
|
||||
else
|
||||
RELEASE="${build_date}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$REPOS" ]; then
|
||||
echo "Must provide --repository"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# setup defaults
|
||||
if [ -z "$WORKDIR" ]; then
|
||||
WORKDIR="$(mktemp -d -t mkimage.XXXXXX)"
|
||||
trap 'rm -rf $WORKDIR' INT EXIT
|
||||
fi
|
||||
req_profiles=${req_profiles:-${all_profiles}}
|
||||
req_arch=${req_arch:-${default_arch}}
|
||||
[ "$req_arch" != "all" ] || req_arch="${all_arch}"
|
||||
[ "$req_profiles" != "all" ] || req_profiles="${all_profiles}"
|
||||
|
||||
mkdir -p "$OUTDIR"
|
||||
|
||||
# get abuild pubkey used to sign the apkindex
|
||||
# we need inject this to the initramfs or we will not be able to use the
|
||||
# boot repository
|
||||
if [ -z "$_hostkeys" ]; then
|
||||
_pub=${PACKAGER_PRIVKEY:+${PACKAGER_PRIVKEY}.pub}
|
||||
_abuild_pubkey="${PACKAGER_PUBKEY:-$_pub}"
|
||||
fi
|
||||
|
||||
# create images
|
||||
for ARCH in $req_arch; do
|
||||
APKROOT="$WORKDIR/apkroot-$ARCH"
|
||||
if [ ! -e "$APKROOT" ]; then
|
||||
# create root for caching packages
|
||||
mkdir -p "$APKROOT/etc/apk/cache" "$APKROOT"/etc/apk/keys
|
||||
[ -d /usr/share/apk/keys/"$ARCH" ] &&
|
||||
cp /usr/share/apk/keys/"$ARCH"/* "$APKROOT"/etc/apk/keys
|
||||
if [ -n "$_hostkeys" ]; then
|
||||
cp /etc/apk/keys/* "$APKROOT"/etc/apk/keys
|
||||
else
|
||||
cp "$_abuild_pubkey" "$APKROOT"/etc/apk/keys
|
||||
fi
|
||||
apk --arch "$ARCH" --root "$APKROOT" add --initdb --no-chown
|
||||
|
||||
_repositories="$APKROOT/etc/apk/repositories"
|
||||
if [ -n "$REPOS_FILE" ]; then
|
||||
cat "$REPOS_FILE" > "$_repositories"
|
||||
fi
|
||||
echo "$REPOS" >> "$_repositories"
|
||||
for repo in $EXTRAREPOS; do
|
||||
echo "$repo" >> "$_repositories"
|
||||
done
|
||||
fi
|
||||
apk update --root "$APKROOT"
|
||||
|
||||
if [ "$_yaml" = "yes" ]; then
|
||||
_yaml_out=${OUTDIR:-.}/latest-releases.yaml
|
||||
echo "---" > "$_yaml_out"
|
||||
fi
|
||||
for PROFILE in $req_profiles; do
|
||||
(set -eo pipefail; build_profile) || exit 1
|
||||
done
|
||||
done
|
||||
echo "Images generated in $OUTDIR"
|
||||
@@ -0,0 +1,71 @@
|
||||
build_rpi_blobs() {
|
||||
for i in raspberrypi-bootloader-common raspberrypi-bootloader; do
|
||||
apk fetch --root "$APKROOT" --quiet --stdout "$i" | tar -C "${DESTDIR}" -zx --strip=1 boot/ || return 1
|
||||
done
|
||||
}
|
||||
|
||||
rpi_gen_cmdline() {
|
||||
echo "modules=loop,squashfs,sd-mod,usb-storage quiet ${kernel_cmdline}"
|
||||
}
|
||||
|
||||
rpi_gen_config() {
|
||||
local arm_64bit=0
|
||||
case "$ARCH" in
|
||||
aarch64) arm_64bit=1;;
|
||||
esac
|
||||
cat <<-EOF
|
||||
# do not modify this file as it will be overwritten on upgrade.
|
||||
# create and/or modify usercfg.txt instead.
|
||||
# https://www.raspberrypi.com/documentation/computers/config_txt.html
|
||||
|
||||
kernel=boot/vmlinuz-rpi
|
||||
initramfs boot/initramfs-rpi
|
||||
arm_64bit=$arm_64bit
|
||||
include usercfg.txt
|
||||
EOF
|
||||
}
|
||||
|
||||
build_rpi_config() {
|
||||
rpi_gen_cmdline > "${DESTDIR}"/cmdline.txt
|
||||
rpi_gen_config > "${DESTDIR}"/config.txt
|
||||
}
|
||||
|
||||
section_rpi_config() {
|
||||
[ "$hostname" = "rpi" ] || return 0
|
||||
build_section rpi_config $( (rpi_gen_cmdline ; rpi_gen_config) | checksum )
|
||||
build_section rpi_blobs
|
||||
}
|
||||
|
||||
profile_rpi() {
|
||||
profile_base
|
||||
title="Raspberry Pi"
|
||||
desc="First generation Pis including Zero/W (armhf).
|
||||
Pi 2 to Pi 3+ generations (armv7).
|
||||
Pi 3 to Pi 5 generations (aarch64)."
|
||||
image_ext="tar.gz"
|
||||
arch="aarch64 armhf armv7"
|
||||
kernel_flavors="rpi"
|
||||
kernel_cmdline="console=tty1"
|
||||
initfs_features="base squashfs mmc usb kms dhcp https"
|
||||
hostname="rpi"
|
||||
grub_mod=
|
||||
}
|
||||
|
||||
create_image_imggz() {
|
||||
sync "$DESTDIR"
|
||||
local image_size=$(du -L -k -s "$DESTDIR" | awk '{print $1 + 8192}' )
|
||||
local imgfile="${OUTDIR}/${output_filename%.gz}"
|
||||
dd if=/dev/zero of="$imgfile" bs=1M count=$(( image_size / 1024 ))
|
||||
mformat -i "$imgfile" -N 0 ::
|
||||
mcopy -s -i "$imgfile" "$DESTDIR"/* "$DESTDIR"/.alpine-release ::
|
||||
echo "Compressing $imgfile..."
|
||||
pigz -v -f -9 "$imgfile" || gzip -f -9 "$imgfile"
|
||||
}
|
||||
|
||||
profile_rpiimg() {
|
||||
profile_rpi
|
||||
title="Raspberry Pi Disk Image"
|
||||
image_name="alpine-rpi"
|
||||
image_ext="img.gz"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
build_kernel() {
|
||||
local _flavor="$2" _modloopsign= _add
|
||||
shift 3
|
||||
local _pkgs="$@"
|
||||
[ "$modloop_sign" = "yes" ] && _modloopsign="--modloopsign"
|
||||
update-kernel \
|
||||
$_hostkeys \
|
||||
${_abuild_pubkey:+--apk-pubkey $_abuild_pubkey} \
|
||||
$_modloopsign \
|
||||
--media \
|
||||
--cache-dir "$APKROOT/etc/apk/cache" \
|
||||
--keys-dir "$APKROOT/etc/apk/keys" \
|
||||
--flavor "$_flavor" \
|
||||
--arch "$ARCH" \
|
||||
--package "$_pkgs" \
|
||||
--feature "$initfs_features" \
|
||||
--modloopfw "$modloopfw" \
|
||||
--repositories-file "$APKROOT/etc/apk/repositories" \
|
||||
"$DESTDIR" \
|
||||
|| return 1
|
||||
for _add in $boot_addons; do
|
||||
apk fetch --root "$APKROOT" --quiet --stdout $_add | tar -C "${DESTDIR}" -zx boot/
|
||||
done
|
||||
}
|
||||
|
||||
section_kernels() {
|
||||
local _f _a _pkgs
|
||||
for _f in $kernel_flavors; do
|
||||
_pkgs="linux-$_f linux-firmware wireless-regdb $modloop_addons"
|
||||
for _a in $kernel_addons; do
|
||||
_pkgs="$_pkgs $_a-$_f"
|
||||
done
|
||||
local id=$( (echo "$initfs_features::$_hostkeys" ; apk fetch --root "$APKROOT" --simulate alpine-base $_pkgs | sort) | checksum)
|
||||
build_section kernel $ARCH $_f $id $_pkgs
|
||||
done
|
||||
}
|
||||
|
||||
build_apks() {
|
||||
local _apksdir="$DESTDIR/apks"
|
||||
local _archdir="$_apksdir/$ARCH"
|
||||
mkdir -p "$_archdir"
|
||||
|
||||
apk fetch --root "$APKROOT" --link --recursive --output "$_archdir" $apks
|
||||
if ! ls "$_archdir"/*.apk >& /dev/null; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
apk index \
|
||||
--root "$APKROOT" \
|
||||
--description "$RELEASE" \
|
||||
--rewrite-arch "$ARCH" \
|
||||
--index "$_archdir"/APKINDEX.tar.gz \
|
||||
--output "$_archdir"/APKINDEX.tar.gz \
|
||||
"$_archdir"/*.apk
|
||||
abuild-sign "$_archdir"/APKINDEX.tar.gz
|
||||
touch "$_apksdir/.boot_repository"
|
||||
}
|
||||
|
||||
section_apks() {
|
||||
[ -n "$apks" ] || return 0
|
||||
build_section apks $ARCH $(apk fetch --root "$APKROOT" --simulate --recursive $apks | sort | checksum)
|
||||
}
|
||||
|
||||
build_apkovl() {
|
||||
local _host="$1" _script=
|
||||
msg "Generating $_host.apkovl.tar.gz"
|
||||
for _script in "$PWD"/"$apkovl" $HOME/.mkimage/$apkovl \
|
||||
$(readlink -f "$scriptdir/$apkovl"); do
|
||||
|
||||
if [ -f "$_script" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
[ -n "$_script" ] || die "could not find $apkovl"
|
||||
(cd "$DESTDIR"; fakeroot "$_script" "$_host")
|
||||
}
|
||||
|
||||
section_apkovl() {
|
||||
[ -n "$apkovl" -a -n "$hostname" ] || return 0
|
||||
build_section apkovl $hostname $(checksum < "$apkovl")
|
||||
}
|
||||
|
||||
build_syslinux() {
|
||||
local _fn
|
||||
mkdir -p "$DESTDIR"/boot/syslinux
|
||||
apk fetch --root "$APKROOT" --stdout syslinux | tar -C "$DESTDIR" -xz usr/share/syslinux
|
||||
for _fn in isohdpfx.bin isolinux.bin ldlinux.c32 libutil.c32 libcom32.c32 mboot.c32; do
|
||||
mv "$DESTDIR"/usr/share/syslinux/$_fn "$DESTDIR"/boot/syslinux/$_fn || return 1
|
||||
done
|
||||
rm -rf "$DESTDIR"/usr
|
||||
}
|
||||
|
||||
section_syslinux() {
|
||||
[ "$ARCH" = x86 -o "$ARCH" = x86_64 ] || return 0
|
||||
[ "$output_format" = "iso" ] || return 0
|
||||
build_section syslinux $(apk fetch --root "$APKROOT" --simulate syslinux | sort | checksum)
|
||||
}
|
||||
|
||||
syslinux_gen_config() {
|
||||
[ -z "$syslinux_serial" ] || echo "SERIAL $syslinux_serial"
|
||||
echo "TIMEOUT ${syslinux_timeout:-10}"
|
||||
echo "PROMPT ${syslinux_prompt:-1}"
|
||||
echo "DEFAULT ${kernel_flavors%% *}"
|
||||
|
||||
local _f _p _initrd
|
||||
for _f in $kernel_flavors; do
|
||||
if [ -z "${xen_params+set}" ]; then
|
||||
_initrd="/boot/initramfs-$_f"
|
||||
for _p in $initrd_ucode; do
|
||||
_initrd="$_p,$_initrd"
|
||||
done
|
||||
|
||||
cat <<- EOF
|
||||
|
||||
LABEL $_f
|
||||
MENU LABEL Linux $_f
|
||||
KERNEL /boot/vmlinuz-$_f
|
||||
INITRD $_initrd
|
||||
FDTDIR /boot/dtbs-$_f
|
||||
APPEND $initfs_cmdline $kernel_cmdline
|
||||
EOF
|
||||
else
|
||||
cat <<- EOF
|
||||
|
||||
LABEL $_f
|
||||
MENU LABEL Xen/Linux $_f
|
||||
KERNEL /boot/syslinux/mboot.c32
|
||||
APPEND /boot/xen.gz ${xen_params} --- /boot/vmlinuz-$_f $initfs_cmdline $kernel_cmdline --- /boot/initramfs-$_f
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
grub_gen_config() {
|
||||
local _f _p _initrd
|
||||
echo "set timeout=1"
|
||||
for _f in $kernel_flavors; do
|
||||
if [ -z "${xen_params+set}" ]; then
|
||||
_initrd="/boot/initramfs-$_f"
|
||||
for _p in $initrd_ucode; do
|
||||
_initrd="$_p $_initrd"
|
||||
done
|
||||
|
||||
cat <<- EOF
|
||||
|
||||
menuentry "Linux $_f" {
|
||||
linux /boot/vmlinuz-$_f $initfs_cmdline $kernel_cmdline
|
||||
initrd $_initrd
|
||||
}
|
||||
EOF
|
||||
else
|
||||
cat <<- EOF
|
||||
|
||||
menuentry "Xen/Linux $_f" {
|
||||
multiboot2 /boot/xen.gz ${xen_params}
|
||||
module2 /boot/vmlinuz-$_f $initfs_cmdline $kernel_cmdline
|
||||
module2 /boot/initramfs-$_f
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
build_syslinux_cfg() {
|
||||
local syslinux_cfg="$1"
|
||||
mkdir -p "${DESTDIR}/$(dirname $syslinux_cfg)"
|
||||
syslinux_gen_config > "${DESTDIR}"/$syslinux_cfg
|
||||
}
|
||||
|
||||
section_syslinux_cfg() {
|
||||
syslinux_cfg=""
|
||||
if [ "$ARCH" = x86 -o "$ARCH" = x86_64 ]; then
|
||||
[ ! "$output_format" = "iso" ] || syslinux_cfg="boot/syslinux/syslinux.cfg"
|
||||
fi
|
||||
[ ! -n "$uboot_install" ] || syslinux_cfg="extlinux/extlinux.conf"
|
||||
[ -n "$syslinux_cfg" ] || return 0
|
||||
build_section syslinux_cfg $syslinux_cfg $(syslinux_gen_config | checksum)
|
||||
}
|
||||
|
||||
build_grub_cfg() {
|
||||
local grub_cfg="$1"
|
||||
mkdir -p "${DESTDIR}/$(dirname $grub_cfg)"
|
||||
grub_gen_config > "${DESTDIR}"/$grub_cfg
|
||||
}
|
||||
|
||||
gen_volid() {
|
||||
printf "%s" "alpine-${profile_abbrev:-$PROFILE} ${RELEASE%_rc*} $ARCH" | cut -c1-32
|
||||
}
|
||||
|
||||
grub_gen_earlyconf() {
|
||||
cat <<- EOF
|
||||
search --no-floppy --set=root --label "$(gen_volid)"
|
||||
set prefix=(\$root)/boot/grub
|
||||
EOF
|
||||
}
|
||||
|
||||
build_grub_efi() {
|
||||
local _format="$1"
|
||||
local _efi="$2"
|
||||
|
||||
apk fetch --root "$APKROOT" --quiet --stdout grub-efi | tar -C "$WORKDIR" -zx usr/lib/grub
|
||||
|
||||
# Prepare grub-efi bootloader
|
||||
mkdir -p "$DESTDIR/efi/boot"
|
||||
grub_gen_earlyconf > "$WORKDIR/grub_early.$3.cfg"
|
||||
grub-mkimage \
|
||||
--config="$WORKDIR/grub_early.$3.cfg" \
|
||||
--directory="$WORKDIR"/usr/lib/grub/"$_format" \
|
||||
--prefix="/boot/grub" \
|
||||
--output="$DESTDIR/efi/boot/$_efi" \
|
||||
--format="$_format" \
|
||||
--compression="xz" \
|
||||
$grub_mod
|
||||
}
|
||||
|
||||
section_grubieee1275() {
|
||||
[ "$ARCH" = ppc64le ] || return 0
|
||||
[ "$output_format" = "iso" ] || return 0
|
||||
kernel_cmdline="$kernel_cmdline console=hvc0"
|
||||
|
||||
build_section grub_cfg boot/grub/grub.cfg $(grub_gen_config | checksum)
|
||||
}
|
||||
|
||||
section_grub_efi() {
|
||||
[ -n "$grub_mod" ] || return 0
|
||||
local _format _efi
|
||||
case "$ARCH" in
|
||||
aarch64)_format="arm64-efi"; _efi="bootaa64.efi" ;;
|
||||
arm*) _format="arm-efi"; _efi="bootarm.efi" ;;
|
||||
x86) _format="i386-efi"; _efi="bootia32.efi" ;;
|
||||
x86_64) _format="x86_64-efi"; _efi="bootx64.efi" ;;
|
||||
riscv64) _format="riscv64-efi"; _efi="bootriscv64.efi" ;;
|
||||
loongarch64) _format="loongarch64-efi"; _efi="bootloongarch64.efi" ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
|
||||
build_section grub_cfg boot/grub/grub.cfg $(grub_gen_config | checksum)
|
||||
build_section grub_efi $_format $_efi $(grub_gen_earlyconf | checksum)
|
||||
}
|
||||
|
||||
create_image_iso() {
|
||||
local ISO="${OUTDIR}/${output_filename}"
|
||||
local _isolinux
|
||||
local _efiboot
|
||||
|
||||
if [ -e "${DESTDIR}/boot/syslinux/isolinux.bin" ]; then
|
||||
# isolinux enabled
|
||||
_isolinux="
|
||||
-isohybrid-mbr ${DESTDIR}/boot/syslinux/isohdpfx.bin
|
||||
-eltorito-boot boot/syslinux/isolinux.bin
|
||||
-eltorito-catalog boot/syslinux/boot.cat
|
||||
-no-emul-boot
|
||||
-boot-load-size 4
|
||||
-boot-info-table
|
||||
"
|
||||
fi
|
||||
if [ -e "${DESTDIR}/efi" -a -e "${DESTDIR}/boot/grub" ]; then
|
||||
# Create the EFI boot partition image
|
||||
mformat -i ${DESTDIR}/boot/grub/efi.img -C -f 1440 -N 0 ::
|
||||
mcopy -i ${DESTDIR}/boot/grub/efi.img -s ${DESTDIR}/efi ::
|
||||
touch -md "@${SOURCE_DATE_EPOCH}" ${DESTDIR}/boot/grub/efi.img
|
||||
|
||||
# Enable EFI boot
|
||||
if [ -z "$_isolinux" ]; then
|
||||
# efi boot only
|
||||
_efiboot="
|
||||
-efi-boot-part
|
||||
--efi-boot-image
|
||||
-e boot/grub/efi.img
|
||||
-no-emul-boot
|
||||
"
|
||||
else
|
||||
# hybrid isolinux+efi boot
|
||||
_efiboot="
|
||||
-eltorito-alt-boot
|
||||
-e boot/grub/efi.img
|
||||
-no-emul-boot
|
||||
-isohybrid-gpt-basdat
|
||||
"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$ARCH" = ppc64le ]; then
|
||||
apk fetch --root "$APKROOT" --quiet --stdout grub-ieee1275 | tar -C "$WORKDIR" -zx usr/lib/grub
|
||||
grub-mkrescue --output ${ISO} ${DESTDIR} -follow-links \
|
||||
--directory="$WORKDIR"/usr/lib/grub/powerpc-ieee1275 \
|
||||
-sysid LINUX \
|
||||
-volid "$(gen_volid)"
|
||||
else
|
||||
if [ "$ARCH" = s390x ]; then
|
||||
printf %s "$initfs_cmdline $kernel_cmdline " > ${WORKDIR}/parmfile
|
||||
for _f in $kernel_flavors; do
|
||||
mk-s390-cdboot -p ${WORKDIR}/parmfile \
|
||||
-i ${DESTDIR}/boot/vmlinuz-$_f \
|
||||
-r ${DESTDIR}/boot/initramfs-$_f \
|
||||
-o ${DESTDIR}/boot/merged.img
|
||||
done
|
||||
iso_opts="$iso_opts -no-emul-boot -eltorito-boot boot/merged.img"
|
||||
fi
|
||||
xorrisofs \
|
||||
-quiet \
|
||||
-output ${ISO} \
|
||||
-full-iso9660-filenames \
|
||||
-joliet \
|
||||
-rational-rock \
|
||||
-sysid LINUX \
|
||||
-volid "$(gen_volid)" \
|
||||
$_isolinux \
|
||||
$_efiboot \
|
||||
-follow-links \
|
||||
${iso_opts} \
|
||||
${DESTDIR}
|
||||
fi
|
||||
}
|
||||
|
||||
create_image_targz() {
|
||||
tar -C "${DESTDIR}" \
|
||||
--mtime="@${SOURCE_DATE_EPOCH}" \
|
||||
--owner=0 --group=0 --numeric-owner \
|
||||
-chzf "${OUTDIR}/${output_filename}" .
|
||||
}
|
||||
|
||||
profile_base() {
|
||||
kernel_flavors="lts"
|
||||
initfs_cmdline="modules=loop,squashfs,sd-mod,usb-storage quiet"
|
||||
initfs_features="ata base bootchart cdrom ext4 mmc nvme raid scsi squashfs usb virtio"
|
||||
modloop_sign=yes
|
||||
grub_mod="all_video disk part_gpt part_msdos linux normal configfile search search_label efi_gop fat iso9660 cat echo ls test true help gzio"
|
||||
case "$ARCH" in
|
||||
x86*) grub_mod="$grub_mod multiboot2 efi_uga";;
|
||||
esac
|
||||
case "$ARCH" in
|
||||
x86_64) initfs_features="$initfs_features nfit";;
|
||||
arm*|aarch64) initfs_features="$initfs_features phy";;
|
||||
esac
|
||||
apks="alpine-base apk-cron busybox chrony dhcpcd doas e2fsprogs
|
||||
kbd-bkeymaps network-extras openntpd openssl openssh
|
||||
tzdata wget tiny-cloud-alpine"
|
||||
apkovl=
|
||||
hostname="alpine"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
profile_immich() {
|
||||
profile_standard
|
||||
apks="$apks docker docker-compose"
|
||||
apkovl="immich.apkovl.tar.gz"
|
||||
apkovl="scripts/genapkovl-dhcp.sh"
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
section_minirootfs() {
|
||||
return 0
|
||||
}
|
||||
|
||||
create_image_rootfs() {
|
||||
local _script=$(readlink -f "$scriptdir/genrootfs.sh")
|
||||
local output_file="$(readlink -f ${OUTDIR:-.})/$output_filename"
|
||||
|
||||
(cd "$OUTDIR"; fakeroot "$_script" -k "$APKROOT"/etc/apk/keys \
|
||||
-r "$APKROOT"/etc/apk/repositories \
|
||||
-o "$output_file" \
|
||||
-a $ARCH \
|
||||
$rootfs_apks)
|
||||
}
|
||||
|
||||
profile_minirootfs() {
|
||||
title="Mini root filesystem"
|
||||
desc="Minimal root filesystem.
|
||||
For use in containers
|
||||
and minimal chroots."
|
||||
image_ext=tar.gz
|
||||
output_format=rootfs
|
||||
arch="$ARCH" # allow any arch
|
||||
rootfs_apks="busybox alpine-baselayout alpine-keys alpine-release apk-tools libc-utils"
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
create_image_netboot() {
|
||||
rm -rf "${OUTDIR}"/netboot-$RELEASE "${OUTDIR}"/netboot
|
||||
cp -aL "${DESTDIR}"/boot "${OUTDIR}"/netboot-$RELEASE
|
||||
ln -s netboot-$RELEASE "${OUTDIR}"/netboot
|
||||
# let webserver read initramfs
|
||||
chmod a+r "${OUTDIR}"/netboot-$RELEASE/*
|
||||
tar -C "${DESTDIR}" -chzf ${OUTDIR}/${output_filename} boot/
|
||||
}
|
||||
|
||||
profile_netboot() {
|
||||
title="Netboot"
|
||||
desc="Kernel, initramfs and modloop for
|
||||
netboot.
|
||||
"
|
||||
arch="aarch64 armhf armv7 ppc64le x86 x86_64 s390x"
|
||||
case "$ARCH" in
|
||||
armhf) kernel_flavors="rpi";;
|
||||
armv7) kernel_flavors="lts rpi";;
|
||||
aarch64) kernel_flavors="lts virt rpi";;
|
||||
x86_64) kernel_flavors="lts virt";;
|
||||
*) kernel_flavors="lts";;
|
||||
esac
|
||||
case "$ARCH" in
|
||||
s390x) initfs_features="base network squashfs usb dasd_mod qeth zfcp";;
|
||||
*) initfs_features="base network squashfs usb virtio"
|
||||
esac
|
||||
modloop_sign=yes
|
||||
apks=""
|
||||
output_format="netboot"
|
||||
image_ext="tar.gz"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
profile_standard() {
|
||||
title="Standard"
|
||||
desc="Alpine as it was intended.
|
||||
Just enough to get you started.
|
||||
Network connection is required."
|
||||
profile_base
|
||||
profile_abbrev="std"
|
||||
image_ext="iso"
|
||||
arch="aarch64 armv7 x86 x86_64 ppc64le s390x loongarch64"
|
||||
output_format="iso"
|
||||
kernel_addons="xtables-addons"
|
||||
case "$ARCH" in
|
||||
s390x)
|
||||
apks="$apks s390-tools"
|
||||
initfs_features="$initfs_features dasd_mod qeth zfcp"
|
||||
initfs_cmdline="modules=loop,squashfs,dasd_mod,qeth,zfcp quiet"
|
||||
;;
|
||||
ppc64le)
|
||||
initfs_cmdline="modules=loop,squashfs,sd-mod,usb-storage,ibmvscsi quiet"
|
||||
;;
|
||||
esac
|
||||
apks="$apks iw wpa_supplicant"
|
||||
}
|
||||
|
||||
profile_extended() {
|
||||
profile_standard
|
||||
profile_abbrev="ext"
|
||||
title="Extended"
|
||||
desc="Most common used packages included.
|
||||
Suitable for routers and servers.
|
||||
Runs from RAM.
|
||||
Includes AMD and Intel microcode updates."
|
||||
arch="x86 x86_64"
|
||||
kernel_addons="xtables-addons zfs"
|
||||
boot_addons="amd-ucode intel-ucode"
|
||||
initrd_ucode="/boot/amd-ucode.img /boot/intel-ucode.img"
|
||||
apks="$apks
|
||||
coreutils ethtool hwids doas
|
||||
logrotate lsof lm_sensors lxc lxc-templates nano
|
||||
pciutils strace tmux
|
||||
usbutils v86d vim xtables-addons curl
|
||||
|
||||
acct arpon arpwatch awall bridge-utils bwm-ng
|
||||
ca-certificates conntrack-tools cutter cyrus-sasl
|
||||
dhcpcd dnsmasq fping fprobe htop
|
||||
igmpproxy ip6tables iproute2 iproute2-qos
|
||||
iptables iputils nftables iw kea ldns-tools links
|
||||
ncurses-terminfo net-snmp net-snmp-tools nrpe nsd
|
||||
opennhrp openvpn pingu ppp quagga
|
||||
quagga-nhrp rng-tools sntpc socat ssmtp strongswan
|
||||
sysklogd tcpdump tinyproxy unbound
|
||||
wireguard-tools wireless-tools wpa_supplicant zonenotify
|
||||
|
||||
btrfs-progs cksfv dosfstools cryptsetup
|
||||
e2fsprogs e2fsprogs-extra efibootmgr f2fs-tools
|
||||
grub-bios grub-efi lvm2 lz4 mdadm mkinitfs mtools nfs-utils
|
||||
parted rsync sfdisk syslinux util-linux xfsprogs zstd zfs
|
||||
"
|
||||
|
||||
local _k _a
|
||||
for _k in $kernel_flavors; do
|
||||
apks="$apks linux-$_k"
|
||||
for _a in $kernel_addons; do
|
||||
apks="$apks $_a-$_k"
|
||||
done
|
||||
done
|
||||
apks="$apks linux-firmware linux-firmware-none"
|
||||
}
|
||||
|
||||
profile_virt() {
|
||||
profile_standard
|
||||
profile_abbrev="virt"
|
||||
title="Virtual"
|
||||
desc="Similar to standard.
|
||||
Slimmed down kernel.
|
||||
Optimized for virtual systems."
|
||||
arch="aarch64 armv7 x86 x86_64"
|
||||
kernel_addons=
|
||||
kernel_flavors="virt"
|
||||
case "$ARCH" in
|
||||
arm*|aarch64)
|
||||
kernel_cmdline="console=tty0 console=ttyAMA0"
|
||||
;;
|
||||
esac
|
||||
syslinux_serial="0 115200"
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
build_uboot() {
|
||||
# FIXME: Fix apk-tools to extract packages directly
|
||||
local pkg pkgs="$(apk fetch --simulate --root "$APKROOT" --recursive u-boot-all | sed -ne "s/^Downloading \(.*\)\-[0-9].*$/\1/p")"
|
||||
for pkg in $pkgs; do
|
||||
[ "$pkg" = "u-boot-all" ] || apk fetch --root "$APKROOT" --stdout $pkg | tar -C "$DESTDIR" -xz usr
|
||||
done
|
||||
mkdir -p "$DESTDIR"/u-boot
|
||||
mv "$DESTDIR"/usr/sbin/update-u-boot "$DESTDIR"/usr/share/u-boot/* "$DESTDIR"/u-boot
|
||||
rm -rf "$DESTDIR"/usr
|
||||
}
|
||||
|
||||
section_uboot() {
|
||||
[ -n "$uboot_install" ] || return 0
|
||||
build_section uboot $ARCH $(apk fetch --root "$APKROOT" --simulate --recursive u-boot-all | sort | checksum)
|
||||
}
|
||||
|
||||
profile_uboot() {
|
||||
profile_base
|
||||
title="Generic U-Boot"
|
||||
desc="Has default LTS kernel.
|
||||
Includes the U-Boot bootloader.
|
||||
Tarball.
|
||||
"
|
||||
image_ext="tar.gz"
|
||||
arch="aarch64 armv7 riscv64"
|
||||
kernel_flavors="lts"
|
||||
case "$ARCH" in
|
||||
aarch64|armv7) kernel_addons="xtables-addons";;
|
||||
esac
|
||||
initfs_features="base ext4 kms mmc nvme phy raid scsi squashfs usb"
|
||||
uboot_install="yes"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
build_xen() {
|
||||
apk fetch --root "$APKROOT" --stdout xen-hypervisor | tar -C "$DESTDIR" -xz boot
|
||||
}
|
||||
|
||||
section_xen() {
|
||||
[ -n "${xen_params+set}" ] || return 0
|
||||
build_section xen $ARCH $(apk fetch --root "$APKROOT" --simulate xen-hypervisor | checksum)
|
||||
}
|
||||
|
||||
profile_xen() {
|
||||
profile_standard
|
||||
profile_abbrev="xen"
|
||||
title="Xen"
|
||||
desc="Built-in support for Xen Hypervisor.
|
||||
Includes packages targetted at Xen usage.
|
||||
Use for Xen Dom0."
|
||||
arch="x86_64"
|
||||
kernel_addons="zfs"
|
||||
xen_params=""
|
||||
apks="$apks ethtool lvm2 mdadm multipath-tools rng-tools sfdisk xen xen-bridge xen-qemu syslinux zfs"
|
||||
|
||||
local _k _a
|
||||
for _k in $kernel_flavors; do
|
||||
apks="$apks linux-$_k"
|
||||
for _a in $kernel_addons; do
|
||||
apks="$apks $_a-$_k"
|
||||
done
|
||||
done
|
||||
}
|
||||
+17
-2
@@ -1,5 +1,7 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# modified from https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/scripts/genapkovl-dhcp.sh?ref_type=heads
|
||||
|
||||
HOSTNAME="$1"
|
||||
if [ -z "$HOSTNAME" ]; then
|
||||
echo "usage: $0 hostname"
|
||||
@@ -68,6 +70,19 @@ rc_add killprocs shutdown
|
||||
rc_add savecache shutdown
|
||||
|
||||
# copy all directories from overlay/ into $tmp and merge
|
||||
cp -a overlay/. "$tmp"/
|
||||
cp -a /home/overlay/. "$tmp"/
|
||||
|
||||
tar -c -C "$tmp" etc usr | gzip -9n > $HOSTNAME.apkovl.tar.gz
|
||||
# run docker and docker pull the images
|
||||
mkdir -p "$tmp"/var/lib/docker
|
||||
dockerd --data-root "$tmp"/var/lib/docker/ &
|
||||
|
||||
sleep 5
|
||||
|
||||
docker pull ghcr.io/immich-app/immich-server:release
|
||||
docker pull ghcr.io/immich-app/immich-machine-learning:release
|
||||
docker pull docker.io/valkey/valkey:8-bookworm
|
||||
docker pull ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
|
||||
|
||||
pkill docker || true
|
||||
|
||||
tar -c -C "$tmp" etc usr var | gzip -9n > $HOSTNAME.apkovl.tar.gz
|
||||
Reference in New Issue
Block a user