diff --git a/.dockerignore b/.dockerignore index ca99cd20e..04f90c210 100644 --- a/.dockerignore +++ b/.dockerignore @@ -35,6 +35,10 @@ compose.*.yaml *.override.yaml *.tmp.yml *.tmp.yaml +*.tmp +*.img +*.img.xz +*.img.gz # Automatically generated files, e.g. by editors and operating systems .DS_Store diff --git a/.gitignore b/.gitignore index 6eb8dff74..a4b6675c4 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,10 @@ *.dll *.so *.dylib +*.tmp +*.img +*.img.xz +*.img.gz /*.zip /coverage.* __pycache__ diff --git a/Makefile b/Makefile index ec442b654..187f419ff 100644 --- a/Makefile +++ b/Makefile @@ -323,6 +323,9 @@ docker-tensorflow-arm64: terminal-tensorflow-arm64: mkdir -p ./build docker run --rm --pull missing -ti --platform=arm64 -v "./build:/build" -e BUILD_ARCH=arm64 -e SYSTEM_ARCH=arm64 photoprism/tensorflow:arm64 bash +build-setup: build-setup-nas-raspberry-pi +build-setup-nas-raspberry-pi: + ./scripts/setup/nas/raspberry-pi/build.sh watch-js: (cd frontend && env BUILD_ENV=development NODE_ENV=production npm run watch) test-js: diff --git a/scripts/dist/build-libheif.sh b/scripts/dist/build-libheif.sh index 63296df9d..08d017878 100755 --- a/scripts/dist/build-libheif.sh +++ b/scripts/dist/build-libheif.sh @@ -56,11 +56,11 @@ mkdir -p "$DESTDIR" ARCHIVE="${CURRENT_DIR}/build/$BUILD.tar.gz" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "VERSION: $LIBHEIF_VERSION" echo "LATEST : $LATEST" echo "ARCHIVE: $ARCHIVE" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "Installing build dependencies..." diff --git a/scripts/dist/install-ffmpeg.sh b/scripts/dist/install-ffmpeg.sh index 3d50818c1..01ba29c68 100755 --- a/scripts/dist/install-ffmpeg.sh +++ b/scripts/dist/install-ffmpeg.sh @@ -64,11 +64,11 @@ else DESTDIR="${DESTDIR}/bin" fi -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "VERSION: $FFMPEG_VERSION" echo "ARCHIVE: $ARCHIVE" echo "DESTDIR: $DESTDIR" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "Extracting \"$URL\" to \"$DESTDIR\"." sudo mkdir -p "${DESTDIR}" diff --git a/scripts/dist/install-jxl.sh b/scripts/dist/install-jxl.sh index e6c57a0af..10470722e 100755 --- a/scripts/dist/install-jxl.sh +++ b/scripts/dist/install-jxl.sh @@ -34,10 +34,10 @@ case $DESTARCH in URL="https://github.com/libjxl/libjxl/releases/download/${LIB_VERSION}/${ARCHIVE}" TMPDIR="/tmp/jpegxl" - echo "------------------------------------------------" + echo "--------------------------------------------------------------------------------" echo "VERSION: $LIB_VERSION" echo "ARCHIVE: $ARCHIVE" - echo "------------------------------------------------" + echo "--------------------------------------------------------------------------------" echo "Installing JPEG XL for ${DESTARCH^^}..." diff --git a/scripts/dist/install-libheif.sh b/scripts/dist/install-libheif.sh index 4183b789e..294395270 100755 --- a/scripts/dist/install-libheif.sh +++ b/scripts/dist/install-libheif.sh @@ -67,11 +67,11 @@ echo "Installing libheif..." ARCHIVE="libheif-${VERSION_CODENAME}-${DESTARCH}-${LIBHEIF_VERSION}.tar.gz" URL="https://dl.photoprism.app/dist/libheif/${ARCHIVE}" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "VERSION: $LIBHEIF_VERSION" echo "ARCHIVE: $ARCHIVE" echo "DESTDIR: $DESTDIR" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" if curl -fsSL "$URL" | tar --overwrite --mode=755 -xz -C "$DESTDIR" 2> /dev/null; then echo "✅ Extracted \"$URL\" to \"$DESTDIR\"" diff --git a/scripts/dist/install-nats.sh b/scripts/dist/install-nats.sh index b1d45e240..8ce0085ff 100755 --- a/scripts/dist/install-nats.sh +++ b/scripts/dist/install-nats.sh @@ -58,12 +58,12 @@ VERSION=${2:-$GITHUB_LATEST} ARCHIVE="nats-server-${VERSION}-linux-${DESTARCH}.tar.gz" GITHUB_URL="https://github.com/nats-io/nats-server/releases/download/${VERSION}/${ARCHIVE}" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "VERSION : ${VERSION}" echo "LATEST : ${GITHUB_LATEST}" echo "DOWNLOAD: ${GITHUB_URL}" echo "DESTDIR : ${DESTDIR}" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" # Adjust the installation path because the archive does not contain a bin directory. DESTDIR="${DESTDIR}/bin" diff --git a/scripts/dist/install-qdrant.sh b/scripts/dist/install-qdrant.sh index 6fd05dec0..e28c5e3d6 100755 --- a/scripts/dist/install-qdrant.sh +++ b/scripts/dist/install-qdrant.sh @@ -54,12 +54,12 @@ VERSION=${2:-$GITHUB_LATEST} ARCHIVE="qdrant-${DESTARCH}-unknown-linux-musl.tar.gz" GITHUB_URL="https://github.com/qdrant/qdrant/releases/download/${VERSION}/${ARCHIVE}" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "VERSION : ${VERSION}" echo "LATEST : ${GITHUB_LATEST}" echo "DOWNLOAD: ${GITHUB_URL}" echo "DESTDIR : ${DESTDIR}" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" # Adjust the installation path because the archive does not contain a bin directory. DESTDIR="${DESTDIR}/bin" diff --git a/scripts/dist/install-s6.sh b/scripts/dist/install-s6.sh index 262f5fdad..05ee9a87d 100755 --- a/scripts/dist/install-s6.sh +++ b/scripts/dist/install-s6.sh @@ -65,13 +65,13 @@ S6_BINARY_URL="https://github.com/just-containers/s6-overlay/releases/download/$ echo "Installing S6 Overlay for ${S6_OVERLAY_ARCH^^}..." -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "VERSION: ${S6_OVERLAY_VERSION}" echo "LATEST : ${S6_OVERLAY_LATEST}" echo "NOARCH : ${ARCHIVE_NOARCH}" echo "BINARY : ${ARCHIVE_BINARY}" echo "DESTDIR: ${S6_OVERLAY_DESTDIR}" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" # Create the destination directory if it does not already exist. mkdir -p "${S6_OVERLAY_DESTDIR}" diff --git a/scripts/dist/install-yt-dlp.sh b/scripts/dist/install-yt-dlp.sh index 641a0080a..4bea6c10a 100755 --- a/scripts/dist/install-yt-dlp.sh +++ b/scripts/dist/install-yt-dlp.sh @@ -64,13 +64,13 @@ fi GITHUB_URL="https://github.com/yt-dlp/yt-dlp/releases/download/${VERSION}/${BINARY}" DESTBIN="${DESTDIR}/bin/yt-dlp" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "VERSION : ${VERSION}" echo "LATEST : ${GITHUB_LATEST}" echo "DOWNLOAD: ${GITHUB_URL}" echo "DESTDIR : ${DESTDIR}" echo "DESTBIN : ${DESTBIN}" -echo "------------------------------------------------" +echo "--------------------------------------------------------------------------------" echo "Downloading the yt-dlp binary to \"${DESTBIN}\"..." mkdir -p "${DESTDIR}" diff --git a/scripts/setup/nas/raspberry-pi/build.sh b/scripts/setup/nas/raspberry-pi/build.sh new file mode 100755 index 000000000..dd5cdd69e --- /dev/null +++ b/scripts/setup/nas/raspberry-pi/build.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +# Builds a PhotoPrismPi SD card image for use with Raspberry Pi 4 and 5. + +# Stop the script if an error occurs. +set -e + +echo "Building PhotoPrismPi SD card image..." + +# Build directory: +DESTDIR=$(realpath "${1:-./setup/nas/raspberry-pi}") + +# Ubuntu Server version and download URL: +UBUNTU_VERSION="${2:-24.04.2}" +UBUNTU_URL="https://cdimage.ubuntu.com/releases/${UBUNTU_VERSION}/release/ubuntu-${UBUNTU_VERSION}-preinstalled-server-arm64+raspi.img.xz" + +# SD card image file name and path: +IMAGE_NAME="photoprismpi-ubuntu-${UBUNTU_VERSION}.img" +IMAGE_PATH="${DESTDIR}/${IMAGE_NAME}" + +# Cloud init config path: +CONFIG_PATH="${DESTDIR}/cloud-init" + +# Boot partition mount path: +MOUNT_DEV="/dev/nbd0" +MOUNT_PATH="${DESTDIR}/boot" + +# Show image and build details. +echo "--------------------------------------------------------------------------------" +echo "VERSION: Ubuntu Server ${UBUNTU_VERSION} for Raspberry Pi" +echo "CDIMAGE: ${UBUNTU_URL}" +echo "DESTDIR: ${DESTDIR}" +echo "SDIMAGE: ${IMAGE_PATH}.xz" +echo "--------------------------------------------------------------------------------" + +# Install build dependencies. +sudo apt update +sudo apt install -y qemu-utils xz-utils cloud-init + +# Remove existing Ubuntu Server image, if any. +rm -f "${IMAGE_PATH}" "${IMAGE_PATH}.xz" + +# Download latest Ubuntu Server image. +echo "Downloading Ubuntu Server image..." +curl -o "${IMAGE_PATH}.xz" -fsSL "${UBUNTU_URL}" +echo "Done." + +# Unpack Ubuntu Server image. +echo "Unpacking ${IMAGE_NAME}.xz..." +(cd "${DESTDIR}" && unxz "${IMAGE_NAME}.xz") +echo "Done." + +# Mount the boot partition to customize it. +echo "Mounting boot partition to ${MOUNT_PATH}..." +mkdir -p "${MOUNT_PATH}" +sudo umount -q "${MOUNT_PATH}" || true + +if [[ -e "${MOUNT_DEV}p1" ]]; then + sudo qemu-nbd --disconnect "${MOUNT_DEV}" || true +fi + +sleep 1 +sudo modprobe nbd max_part=8 +sudo qemu-nbd --connect="${MOUNT_DEV}" --format=raw "${IMAGE_PATH}" +sleep 3 +sudo mount "${MOUNT_DEV}p1" "${MOUNT_PATH}" +echo "Done." + +# Copy cloud-init files to the boot partition. +echo "Copying files to boot partition..." +sudo cp "${CONFIG_PATH}/meta-data" "${CONFIG_PATH}/network-config" "${CONFIG_PATH}/user-data" "${MOUNT_PATH}" +echo "Done." + +# Unmount boot partition. +echo "Unmounting boot partition..." +sudo umount "${MOUNT_PATH}" +sleep 1 +if [[ -e "${MOUNT_DEV}p1" ]]; then + sudo qemu-nbd --disconnect "${MOUNT_DEV}" +fi +sleep 1 +rmdir "${MOUNT_PATH}" +echo "Done." + +# Create the final SD card image. +echo "Creating ${IMAGE_PATH}.xz..." +xz -T0 -z -q -9 "${IMAGE_PATH}" +echo "Done." \ No newline at end of file