diff --git a/.github/workflows/build-action.yml b/.github/workflows/build-action.yml index 3c56f53f8..4f87b54b1 100644 --- a/.github/workflows/build-action.yml +++ b/.github/workflows/build-action.yml @@ -1,4 +1,4 @@ -name: Build Image +name: Build openHABian images # Trigger the workflow on push or pull request on: @@ -6,10 +6,12 @@ on: paths: - 'build.bash' - 'build-image/openhabian-installer.service' + - 'includes/offline-image-modifications.bash' pull_request: paths: - 'build.bash' - 'build-image/openhabian-installer.service' + - 'includes/offline-image-modifications.bash' workflow_dispatch: inputs: comments: @@ -27,31 +29,29 @@ jobs: with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.ref }} - - name: Environment variables - run: sudo -E bash -c set - - name: Install required packages - run: sudo apt-get install git curl unzip libarchive-zip-perl dos2unix xz-utils kpartx - - name: getimagename - id: getimagename + - name: Setup environment + id: setup run: | + sudo -E bash -c set + sudo apt-get update + sudo apt-get install --yes libarchive-zip-perl dos2unix systemd-container qemu-user-static qemu-utils echo "::set-output name=image::$(basename "$(curl "https://downloads.raspberrypi.org/raspios_lite_armhf_latest" -s -L -I -o /dev/null -w '%{url_effective}')")" - name: Cache Raspberry Pi OS image uses: actions/cache@v2 with: - path: ${{ steps.getimagename.outputs.image }} - key: ${{ steps.getimagename.outputs.image }} - - name: Run build.bash rpi + path: ${{ steps.setup.outputs.image }} + key: ${{ steps.setup.outputs.image }} + - name: Build openHABian 32bit image + id: build run: | sudo -E ./ci-setup.bash github pi-raspios32 sudo -E ./build.bash rpi - - name: getfilename - id: getfilename - run: echo "::set-output name=file::$(ls openhabian-*.img.xz)" - - name: Archive + echo "::set-output name=file::$(ls openhabian-*.img.xz)" + - name: Archive openHABian 32bit image uses: actions/upload-artifact@v2 with: - name: ${{ steps.getfilename.outputs.file }} - path: ${{ steps.getfilename.outputs.file }} + name: ${{ steps.build.outputs.file }} + path: ${{ steps.build.outputs.file }} build64experimental: # Using latest Ubuntu (not the GitHub Actions default) to get latest tool versions in GitHub Actions environment runs-on: ubuntu-20.04 @@ -62,28 +62,26 @@ jobs: with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.ref }} - - name: Environment variables - run: sudo -E bash -c set - - name: Install required packages - run: sudo apt-get install git curl unzip libarchive-zip-perl dos2unix xz-utils kpartx - - name: getimagename - id: getimagename + - name: Setup environment + id: setup run: | + sudo -E bash -c set + sudo apt-get update + sudo apt-get install --yes libarchive-zip-perl dos2unix systemd-container qemu-user-static qemu-utils echo "::set-output name=image::$(basename "$(curl "https://downloads.raspberrypi.org/raspios_lite_arm64_latest" -s -L -I -o /dev/null -w '%{url_effective}')")" - name: Cache Raspberry Pi OS image uses: actions/cache@v2 with: - path: ${{ steps.getimagename.outputs.image }} - key: ${{ steps.getimagename.outputs.image }} - - name: Run build.bash rpi64 + path: ${{ steps.setup.outputs.image }} + key: ${{ steps.setup.outputs.image }} + - name: Build openHABian 64bit image + id: build run: | sudo -E ./ci-setup.bash github pi-raspios64beta sudo -E ./build.bash rpi64 - - name: getfilename - id: getfilename - run: echo "::set-output name=file::$(ls openhabian-*.img.xz)" - - name: Archive + echo "::set-output name=file::$(ls openhabian-*.img.xz)" + - name: Archive openHABian 64bit image uses: actions/upload-artifact@v2 with: - name: ${{ steps.getfilename.outputs.file }} - path: ${{ steps.getfilename.outputs.file }} + name: ${{ steps.build.outputs.file }} + path: ${{ steps.build.outputs.file }} diff --git a/.github/workflows/shellcheck-action.yml b/.github/workflows/shellcheck-action.yml index 31d15c9f4..a63eb70e5 100644 --- a/.github/workflows/shellcheck-action.yml +++ b/.github/workflows/shellcheck-action.yml @@ -21,10 +21,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 - - name: Environment variables + - name: Setup environment run: sudo -E bash -c set - - name: Install required packages - run: sudo apt-get install shellcheck - name: "ShellCheck openhabian-setup.sh" run: | echo "ShellCheck openhabian-setup.sh..." diff --git a/build-image/first-boot.bash b/build-image/first-boot.bash index 40da3e853..de1144708 100755 --- a/build-image/first-boot.bash +++ b/build-image/first-boot.bash @@ -173,9 +173,9 @@ fi if [[ -x $(command -v python3) ]]; then bash /boot/webserver.bash "reinsure_running"; fi -if ! dpkg -s 'git' &> /dev/null; then +if ! [[ -x $(command -v git) ]]; then echo -n "$(timestamp) [openHABian] Installing git package... " - if apt-get install --yes git &> /dev/null; then echo "OK"; else echo "FAILED"; fi + if apt-get install --yes git; then echo "OK"; else echo "FAILED"; fi fi # shellcheck disable=SC2154 @@ -184,6 +184,7 @@ type openhabian_update &> /dev/null && if ! openhabian_update &> /dev/null; then echo "FAILED" echo "$(timestamp) [openHABian] The git repository on the public internet is not reachable." echo "$(timestamp) [openHABian] We will continue trying to get your system installed, but this is not guaranteed to work." + export OFFLINE="1" else echo "OK" fi diff --git a/build-image/openhabian.conf b/build-image/openhabian.conf index 1e4dc1ed4..00bf10e3a 100644 --- a/build-image/openhabian.conf +++ b/build-image/openhabian.conf @@ -77,5 +77,5 @@ java_opt=Zulu8-64 #relaypass=secret #smarthost=smtp.gmail.com #smartport=587 -# + # vim: filetype=sh diff --git a/build-image/openhabian.pi-raspios64beta.conf b/build-image/openhabian.pi-raspios64beta.conf index cb28a9d2d..7de73099a 100644 --- a/build-image/openhabian.pi-raspios64beta.conf +++ b/build-image/openhabian.pi-raspios64beta.conf @@ -78,5 +78,5 @@ java_opt=Zulu11-64 #relaypass=secret #smarthost=smtp.gmail.com #smartport=587 -# + # vim: filetype=sh diff --git a/build.bash b/build.bash index f410f7581..5a6de6393 100755 --- a/build.bash +++ b/build.bash @@ -11,14 +11,14 @@ usage() { } cleanup_build() { - if [[ -z "$buildfolder" ]]; then exit 1; fi + if [[ -z "$buildFolder" ]]; then exit 1; fi - umount "$buildfolder/boot" &> /dev/null || true - umount "$buildfolder/root" &> /dev/null || true - guestunmount --no-retry "$buildfolder/boot" &> /dev/null || true - guestunmount --no-retry "$buildfolder/root" &> /dev/null || true + umount "${buildFolder}/boot" &> /dev/null || true + umount "${buildFolder}/root" &> /dev/null || true + guestunmount --no-retry "${buildFolder}/boot" &> /dev/null || true + guestunmount --no-retry "${buildFolder}/root" &> /dev/null || true - rm -rf "$buildfolder" + rm -rf "$buildFolder" } ########################## @@ -26,6 +26,12 @@ cleanup_build() { ########################## # shellcheck source=functions/helpers.bash source "$(dirname "$0")"/functions/helpers.bash +# shellcheck source=functions/java-jre.bash +source "$(dirname "$0")"/functions/java-jre.bash +# shellcheck source=functions/zram.bash +source "$(dirname "$0")"/functions/zram.bash +# shellcheck source=functions/packages.bash +source "$(dirname "$0")"/functions/packages.bash ## This function formats log messages ## @@ -37,45 +43,45 @@ echo_process() { ## Function for identify and returning current active git repository and branch ## -## Returns global variable $clone_string +## Returns global variable $cloneString ## ## get_git_repo() ## get_git_repo() { - local repo_url repo_branch user_name repo_name + local repoURL repoBranch userName repoName - repo_url="$(git remote get-url origin)" - repo_branch="$(git rev-parse --abbrev-ref HEAD)" + repoURL="$(git remote get-url origin)" + repoBranch="$(git rev-parse --abbrev-ref HEAD)" - if ! [[ $repo_url == "https"* ]]; then + if ! [[ $repoURL == "https"* ]]; then # Convert URL from SSH to HTTPS - user_name="$(echo "$repo_url" | sed -Ene's#git@github.com:([^/]*)/(.*).git#\1#p')" - if [[ -z $user_name ]]; then + userName="$(echo "$repoURL" | sed -Ene's#git@github.com:([^/]*)/(.*).git#\1#p')" + if [[ -z $userName ]]; then echo_process "Could not identify git user while converting to SSH URL. Exiting." exit 1 fi - repo_name="$(echo "$repo_url" | sed -Ene's#git@github.com:([^/]*)/(.*).git#\2#p')" - if [[ -z $repo_name ]]; then + repoName="$(echo "$repoURL" | sed -Ene's#git@github.com:([^/]*)/(.*).git#\2#p')" + if [[ -z $repoName ]]; then echo_process "Could not identify git repo while converting to SSH URL. Exiting." exit 1 fi - repo_url="https://github.com/${user_name}/${repo_name}.git" + repoURL="https://github.com/${userName}/${repoName}.git" fi - clone_string="${repo_branch} ${repo_url}" + cloneString="${repoBranch} ${repoURL}" } ## Function for injecting custom development branch when building images. ## This function will also watermark the image as a test build. ## ## The first parameter shall be the temporary first-boot.bash file used when building the image. -## The global varible $clone_string must be set prior running this function. +## The global varible $cloneString must be set prior running this function. ## ## inject_build_repo(String path) ## inject_build_repo() { - if [[ -z "${clone_string+x}" ]]; then - echo_process "inject_build_repo() invoked without clone_string variable set, exiting...." + if [[ -z "${cloneString+x}" ]]; then + echo_process "inject_build_repo() invoked without cloneString variable set, exiting...." exit 1 fi sed -i '$a /usr/bin/apt-get install --yes figlet &>/dev/null' "$1" @@ -109,78 +115,115 @@ check_command_availability_and_exit() { done } -# mount rpi image using userspace tools, in docker use privileged mount via kpartx -mount_image_file_boot() { # imagefile buildfolder +## Mount RPi Image with userspace tools, for docker we use kpartx +## +## mount_image_file_boot(String imageFile, String buildFolder) +## +mount_image_file_boot() { + local imageFile="$1" + local buildFolder="$2" + local loopPrefix + if ! running_in_docker && ! running_on_github && ! is_pi; then - guestmount --format=raw -o uid=$EUID -a "$1" -m /dev/sda1 "$2/boot" + guestmount --format=raw -o uid="$EUID" -a "$imageFile" -m /dev/sda1 "${2}/boot" else - loop_prefix=$(kpartx -asv "$1" | grep -oE "loop([0-9]+)" | head -n 1) - mount -o rw -t vfat "/dev/mapper/${loop_prefix}p1" "$buildfolder/boot" + loopPrefix="$(kpartx -asv "$imageFile" | grep -oE "loop([0-9]+)" | head -n 1)" + mount -o rw -t vfat "/dev/mapper/${loopPrefix}p1" "${buildFolder}/boot" fi - df -h "$buildfolder/boot" + df -h "${buildFolder}/boot" } -mount_image_file_root() { # imagefile buildfolder +## Unmount RPi Image with userspace tools, for docker we use kpartx +## +## umount_image_file_boot(String imageFile, String buildFolder) +## +umount_image_file_boot() { + local imageFile="$1" + local buildFolder="$2" + if ! running_in_docker && ! running_on_github && ! is_pi; then - guestmount --format=raw -o uid=$EUID -a "$1" -m /dev/sda2 "$2/root" + guestunmount "${buildFolder}/boot" else - loop_prefix=$(kpartx -asv "$1" | grep -oE "loop([0-9]+)" | head -n 1) - e2fsck -y -f "/dev/mapper/${loop_prefix}p2" &> /dev/null - resize2fs "/dev/mapper/${loop_prefix}p2" &> /dev/null - mount -o rw -t ext4 "/dev/mapper/${loop_prefix}p2" "$buildfolder/root" + umount "${buildFolder}/boot" + kpartx -d "$imageFile" fi - df -h "$buildfolder/root" } +## Mount RPi Image with userspace tools, for docker we use kpartx +## +## mount_image_file_root(String imageFile, String buildFolder) +## +mount_image_file_root() { + local imageFile="$1" + local buildFolder="$2" + local loopPrefix -# umount rpi image -umount_image_file_boot() { # imagefile buildfolder if ! running_in_docker && ! running_on_github && ! is_pi; then - guestunmount "$2/boot" + guestmount --format=raw -o uid="$EUID" -a "$imageFile" -m /dev/sda2 "${buildFolder}/root" else - umount "$2/boot" - kpartx -d "$1" + loopPrefix="$(kpartx -asv "$imageFile" | grep -oE "loop([0-9]+)" | head -n 1)" + e2fsck -y -f "/dev/mapper/${loopPrefix}p2" &> /dev/null + resize2fs "/dev/mapper/${loopPrefix}p2" &> /dev/null + mount -o rw -t ext4 "/dev/mapper/${loopPrefix}p2" "${buildFolder}/root" fi + df -h "${buildFolder}/root" } -# umount rpi image -umount_image_file_root() { # imagefile buildfolder +## Unmount RPi Image with userspace tools, for docker we use kpartx +## +## umount_image_file_root(String imageFile, String buildFolder) +## +umount_image_file_root() { + local imageFile="$1" + local buildFolder="$2" + if ! running_in_docker && ! running_on_github && ! is_pi; then - guestunmount "$2/root" + guestunmount "${buildFolder}/root" else - umount "$2/root" - kpartx -d "$1" + umount "${buildFolder}/root" + kpartx -d "$imageFile" + fi +} + +## Make offline install modifications to code using systemd-nspawn +## +## offline_install_modifications(String imageFile, String mountFolder) +## +offline_install_modifications() { + local imageFile="$1" + local mountFolder="$2" + local loopPrefix + + if running_on_github; then + echo_process "Cacheing packages for offline install..." + loopPrefix="$(kpartx -asv "$imageFile" | grep -oE "loop([0-9]+)" | head -n 1)" + mount -o rw -t ext4 "/dev/mapper/${loopPrefix}p2" "$mountFolder" + mount -o rw -t vfat "/dev/mapper/${loopPrefix}p1" "${mountFolder}/boot" + systemd-nspawn --directory="$2" /opt/openhabian/includes/offline-install-modifications.bash &> /dev/null + sync + df -h "$mountFolder" + df -h "${mountFolder}/boot" + umount "${mountFolder}/boot" + umount "$mountFolder" + e2fsck -y -f "/dev/mapper/${loopPrefix}p2" &> /dev/null + zerofree "/dev/mapper/${loopPrefix}p2" &> /dev/null + sleep 30 + kpartx -d "$imageFile" fi } -## Grow root partition and file system of a downloaded Raspi OS image +## Grow root partition and file system of a downloaded RaspiOS image +## Root partition if #2 and sector size is 512 bytes for RaspiOS image ## Arguments: $1 = filename of image ## $2 = number of MBs to grow image by ## ## grow_image(String image, int extraSize) ## grow_image() { - local partStart - local partition - - # root partition is #2 and sector size is 512 byte for the Raspi OS image - partition=2 - - dd if=/dev/zero bs=1M count="$2" oflag=append conv=notrunc of="$1" &> /dev/null - partStart=$(echo p|/sbin/fdisk "$1" | grep "$1"2 | awk '{print $2}') - - /sbin/fdisk "$1" &> /dev/null < /dev/null + echo ", +" | sfdisk -N "$partition" "$1" &> /dev/null } @@ -188,17 +231,17 @@ EOF #### Build script start #### ############################ -timestamp=$(date +%Y%m%d%H%M) -file_tag="" # marking output file for special builds +timestamp="$(date +%Y%m%d%H%M)" +fileTag="" # marking output file for special builds echo_process "This script will build the openHABian image file." # Identify hardware platform if [ "$1" == "rpi" ]; then - hw_platform="pi-raspios32" + hwPlatform="pi-raspios32" echo_process "Hardware platform: Raspberry Pi (rpi)" elif [ "$1" == "rpi64" ]; then - hw_platform="pi-raspios64beta" + hwPlatform="pi-raspios64beta" echo_process "Hardware platform: Raspberry Pi (rpi64) - BETA -" elif [ "$1" == "local-test" ]; then @@ -225,18 +268,17 @@ fi # Check if a specific repository should be included if [ "$2" == "dev-git" ]; then # Use current git repo and branch as a development image - file_tag="custom" + fileTag="custom" get_git_repo echo_process "Injecting current branch and git repo when building this image, make sure to push local content to:" - echo_process "$clone_string" - + echo_process "$cloneString" elif [ "$2" == "dev-url" ]; then # Use custom git server as a development image - file_tag="custom" - clone_string="$3 $4" + fileTag="custom" + cloneString="$3 $4" clonebranch="$3" repositoryurl="$4" echo_process "Injecting given git repo when building this image, make sure to push local content to:" - echo_process "$clone_string" + echo_process "$cloneString" elif [ -n "$2" ]; then usage exit 1 @@ -248,32 +290,32 @@ trap cleanup_build EXIT ERR cd "$(dirname "$0")" || (echo "$(dirname "$0") cannot be accessed."; exit 1) # Log everything to a file -exec &> >(tee -a "openhabian-build-$timestamp.log") +exec &> >(tee -a "openhabian-build-${timestamp}.log") # Load config, create temporary build folder, cleanup -sourcefolder="build-image" +sourceFolder="build-image" # shellcheck disable=SC1090 -source "${sourcefolder}/openhabian.${hw_platform}.conf" -buildfolder="$(mktemp -d "${TMPDIR:-/tmp}"/openhabian-build-${hw_platform}-image.XXXXX)" -imagefile="${buildfolder}/${hw_platform}.img" -extrasize="300" # grow image root by this number of MB +source "${sourceFolder}/openhabian.${hwPlatform}.conf" +buildFolder="$(mktemp -d "${TMPDIR:-/tmp}"/openhabian-build-${hwPlatform}-image.XXXXX)" +imageFile="${buildFolder}/${hwPlatform}.img" +extraSize="1000" # grow image root by this number of MB # Build Raspberry Pi image -if [[ $hw_platform == "pi-raspios32" ]] || [[ $hw_platform == "pi-raspios64beta" ]]; then - if [ "$hw_platform" == "pi-raspios64beta" ]; then - baseurl="https://downloads.raspberrypi.org/raspios_lite_arm64_latest" +if [[ $hwPlatform == "pi-raspios32" ]] || [[ $hwPlatform == "pi-raspios64beta" ]]; then + if [ "$hwPlatform" == "pi-raspios64beta" ]; then + baseURL="https://downloads.raspberrypi.org/raspios_lite_arm64_latest" bits="64" else - baseurl="https://downloads.raspberrypi.org/raspios_lite_armhf_latest" + baseURL="https://downloads.raspberrypi.org/raspios_lite_armhf_latest" bits="32" fi - zipurl="$(curl "$baseurl" -s -L -I -o /dev/null -w '%{url_effective}')" - zipfile="$(basename "$zipurl")" + zipURL="$(curl "$baseURL" -s -L -I -o /dev/null -w '%{url_effective}')" + zipFile="$(basename "$zipURL")" # Prerequisites echo_process "Checking prerequisites... " - REQ_COMMANDS="git curl unzip crc32 dos2unix xz" - REQ_PACKAGES="git curl unzip libarchive-zip-perl dos2unix xz-utils" + requiredCommands="git curl wget unzip crc32 dos2unix xz qemu-img" + requiredPackages="git curl wget unzip libarchive-zip-perl dos2unix xz-utils qemu-utils" if running_in_docker || running_on_github || is_pi; then # in docker guestfstools are not used; do not install it and all of its prerequisites # -> must be run as root @@ -281,106 +323,134 @@ if [[ $hw_platform == "pi-raspios32" ]] || [[ $hw_platform == "pi-raspios64beta" echo_process "For use with Docker or on RPi, this script must be run as root" 1>&2 exit 1 fi - REQ_COMMANDS+=" kpartx" - REQ_PACKAGES+=" kpartx" + requiredCommands+=" kpartx" + requiredPackages+=" kpartx" else # if not running in Docker not on a RPi, use userspace tools - REQ_COMMANDS+=" guestmount" - REQ_PACKAGES+=" libguestfs-tools" + requiredCommands+=" guestmount" + requiredPackages+=" libguestfs-tools" fi - check_command_availability_and_exit "$REQ_COMMANDS" "$REQ_PACKAGES" + check_command_availability_and_exit "$requiredCommands" "$requiredPackages" - - if [[ -f $zipfile ]]; then - echo_process "Using local copy of Raspberry Pi OS ($bits-bit) image... " - cp "$zipfile" "$buildfolder/$zipfile" + if [[ -f $zipFile ]]; then + echo_process "Using local copy of Raspberry Pi OS (${bits}-bit) image... " + cp "$zipFile" "${buildFolder}/${zipFile}" else - echo_process "Downloading latest Raspberry Pi OS ($bits-bit) image (no local copy found)... " - curl -L "$baseurl" -o "$zipfile" - cp "$zipfile" "$buildfolder/$zipfile" + echo_process "Downloading latest Raspberry Pi OS (${bits}-bit) image (no local copy found)... " + curl -L "$baseURL" -o "$zipFile" + cp "$zipFile" "${buildFolder}/${zipFile}" fi echo_process "Verifying signature of downloaded image... " - curl -s "$zipurl".sig -o "$buildfolder"/"$zipfile".sig + curl -s "$zipURL".sig -o "$buildFolder"/"$zipFile".sig if ! gpg -q --keyserver keyserver.ubuntu.com --recv-key 0x8738CD6B956F460C; then echo "FAILED (download public key)"; exit 1; fi - if gpg -q --trust-model always --verify "$buildfolder/$zipfile".sig "$buildfolder/$zipfile"; then echo "OK"; else echo "FAILED (signature)"; exit 1; fi + if gpg -q --trust-model always --verify "${buildFolder}/${zipFile}".sig "${buildFolder}/${zipFile}"; then echo "OK"; else echo "FAILED (signature)"; exit 1; fi echo_process "Unpacking image... " - unzip -q "$buildfolder/$zipfile" -d "$buildfolder" - mv "$buildfolder"/*-raspios-*.img "$imagefile" || true - - if [[ $extrasize -gt 0 ]]; then - echo_process "Growing root partition of the image by $extrasize MB... " - # shellcheck disable=SC2012 - SIZEBEFORE=$(ls -sh "$imagefile"|awk '{print $1}') - grow_image "$imagefile" "$extrasize" - # shellcheck disable=SC2012 - SIZEAFTER=$(ls -sh "$imagefile"|awk '{print $1}') - echo_process "Growing image form $SIZEBEFORE to $SIZEAFTER completed." + unzip -q "${buildFolder}/${zipFile}" -d "$buildFolder" + mv "$buildFolder"/*-raspios-*.img "$imageFile" || true + + if [[ $extraSize -gt 0 ]]; then + echo_process "Growing root partition of the image by ${extraSize} MB... " + sizeBefore="$(( $(stat --format=%s "$imageFile") / 1024 / 1024 ))" + grow_image "$imageFile" "$extraSize" + sizeAfter="$(( $(stat --format=%s "$imageFile") / 1024 / 1024 ))" + echo_process "Growing image from ${sizeBefore} MB to ${sizeAfter} MB completed." fi echo_process "Mounting the image for modifications... " - mkdir -p "$buildfolder"/boot "$buildfolder"/root - mount_image_file_root "$imagefile" "$buildfolder" + mkdir -p "$buildFolder"/boot "$buildFolder"/root "$buildFolder"/mnt + mount_image_file_root "$imageFile" "$buildFolder" echo_process "Setting hostname... " # shellcheck disable=SC2154 - sed -i "s/127.0.1.1.*/127.0.1.1 $hostname/" "$buildfolder"/root/etc/hosts - echo "$hostname" > "$buildfolder"/root/etc/hostname + sed -i "s/127.0.1.1.*/127.0.1.1 $hostname/" "$buildFolder"/root/etc/hosts + echo "$hostname" > "$buildFolder"/root/etc/hostname echo_process "Injecting 'openhabian-installer.service', 'first-boot.bash' and 'openhabian.conf'... " - cp "$sourcefolder"/openhabian-installer.service "$buildfolder"/root/etc/systemd/system/ - ln -s "$buildfolder"/root/etc/systemd/system/openhabian-installer.service "$buildfolder"/root/etc/systemd/system/multi-user.target.wants/openhabian-installer.service + cp "$sourceFolder"/openhabian-installer.service "$buildFolder"/root/etc/systemd/system/ + ln -s "$buildFolder"/root/etc/systemd/system/openhabian-installer.service "$buildFolder"/root/etc/systemd/system/multi-user.target.wants/openhabian-installer.service - # Open subshell to make sure we don't hurt the host system if for some reason $buildfolder is not properly set + # Open subshell to make sure we don't hurt the host system if for some reason $buildFolder is not properly set echo_process "Setting default runlevel multiuser.target and disabling autologin... " ( - cd "$buildfolder"/root/etc/systemd/system/ || exit 1 + cd "$buildFolder"/root/etc/systemd/system/ || exit 1 rm -rf default.target ln -s ../../../lib/systemd/system/multi-user.target default.target rm -f getty@tty1.service.d/autologin.conf ) echo_process "Cloning myself from ${repositoryurl:-https://github.com/openhab/openhabian.git}, ${clonebranch:-stable} branch... " - if ! [[ -d $buildfolder/root/opt/openhabian ]]; then - git clone "${repositoryurl:-https://github.com/openhab/openhabian.git}" "$buildfolder"/root/opt/openhabian &> /dev/null - git -C "$buildfolder"/root/opt/openhabian checkout "${clonebranch:-stable}" &> /dev/null + if ! [[ -d ${buildFolder}/root/opt/openhabian ]]; then + git clone "${repositoryurl:-https://github.com/openhab/openhabian.git}" "$buildFolder"/root/opt/openhabian &> /dev/null + git -C "$buildFolder"/root/opt/openhabian checkout "${clonebranch:-stable}" &> /dev/null fi - touch "$buildfolder"/root/opt/openHABian-install-inprogress - umount_image_file_root "$imagefile" "$buildfolder" + touch "$buildFolder"/root/opt/openHABian-install-inprogress + + # Cache zram for offline install. + ( + echo_process "Downloading zram..." + install_zram_code "${buildFolder}/root/opt/zram" &> /dev/null + ) + + # Cache Java for offline install. + ( + # Source config to set Java option correctly, this cache currently only works for Zulu. + # shellcheck disable=SC1090 + source "${sourceFolder}/openhabian.${hwPlatform}.conf" + + echo_process "Downloading Java..." + # Using variable hw intended for CI only to force use of arm packages. + # java_zulu_fetch takes version/bits as parameter, but internally uses is_arm + # to decide if x86/64 or arm packages are downloaded. Parameter works for 32 and 64bit. + hwarch="armv7l" java_zulu_fetch "${java_opt:-Zulu8-32}" "$buildFolder"/root &> /dev/null + java_zulu_install_crypto_extension "$(find "$buildFolder"/root/opt/jdk/*/lib -type d -print -quit)/security" &> /dev/null + ) + + # Cache FireMotD for offline install. + ( + echo_process "Downloading FireMotD..." + firemotd_download "${buildFolder}/root/opt" &> /dev/null + ) + + sync + umount_image_file_root "$imageFile" "$buildFolder" + + mount_image_file_boot "$imageFile" "$buildFolder" echo_process "Reactivating SSH... " - mount_image_file_boot "$imagefile" "$buildfolder" - touch "$buildfolder"/boot/ssh - cp "$sourcefolder"/first-boot.bash "$buildfolder"/boot/first-boot.bash - touch "$buildfolder"/boot/first-boot.log - unix2dos -q -n "$sourcefolder"/openhabian.${hw_platform}.conf "$buildfolder"/boot/openhabian.conf - cp "$sourcefolder"/webserver.bash "$buildfolder"/boot/webserver.bash - - # Injecting development git repo if clone_string is set and watermark build - if [[ -n "${clone_string+x}" ]]; then - inject_build_repo "$buildfolder"/boot/first-boot.bash + touch "$buildFolder"/boot/ssh + cp "$sourceFolder"/first-boot.bash "$buildFolder"/boot/first-boot.bash + touch "$buildFolder"/boot/first-boot.log + unix2dos -q -n "$sourceFolder"/openhabian.${hwPlatform}.conf "$buildFolder"/boot/openhabian.conf + cp "$sourceFolder"/webserver.bash "$buildFolder"/boot/webserver.bash + + # Injecting development git repo if cloneString is set and watermark build + if [[ -n "${cloneString+x}" ]]; then + inject_build_repo "$buildFolder"/boot/first-boot.bash fi echo_process "Closing up image file... " sync - umount_image_file_boot "$imagefile" "$buildfolder" + umount_image_file_boot "$imageFile" "$buildFolder" + + offline_install_modifications "$imageFile" "${buildFolder}/mnt" fi echo_process "Moving image and cleaning up... " shorthash="$(git log --pretty=format:'%h' -n 1)" -crc32checksum=$(crc32 "$imagefile") -destination="openhabian-${hw_platform}-${timestamp}-git${file_tag}${shorthash}-crc${crc32checksum}.img" -mv -v "$imagefile" "$destination" -rm -rf "$buildfolder" +crc32checksum="$(crc32 "$imageFile")" +destination="openhabian-${hwPlatform}-${timestamp}-git${fileTag}${shorthash}-crc${crc32checksum}.img" +mv -v "$imageFile" "$destination" +rm -rf "$buildFolder" echo_process "Compressing image... " # speedup compression, T0 will use all cores and should be supported by reasonably new versions of xz -xz --verbose --compress --keep -T0 "$destination" -crc32checksum="$(crc32 "$destination.xz")" -mv "${destination}.xz" "openhabian-${hw_platform}-${timestamp}-git${file_tag}${shorthash}-crc${crc32checksum}.img.xz" +xz --verbose --compress --keep -9 -T0 "$destination" +crc32checksum="$(crc32 "${destination}.xz")" +mv "${destination}.xz" "openhabian-${hwPlatform}-${timestamp}-git${fileTag}${shorthash}-crc${crc32checksum}.img.xz" echo_process "Finished! The results:" -ls -alh "openhabian-$hw_platform-$timestamp"* +ls -alh "openhabian-${hwPlatform}-${timestamp}"* # vim: filetype=sh diff --git a/functions/backup.bash b/functions/backup.bash index 409e69954..78717a79d 100644 --- a/functions/backup.bash +++ b/functions/backup.bash @@ -432,6 +432,11 @@ mirror_SD() { ## setup_mirror_SD() ## setup_mirror_SD() { + if [[ -n "$UNATTENDED" ]] && [[ -z "$backupdrive" ]]; then + echo "$(timestamp) [openHABian] Setting up automated SD mirroring and backup... CANCELED (no configuration provided)" + return 0 + fi + local dest local srcSize local destSize @@ -440,16 +445,17 @@ setup_mirror_SD() { local storageDir="${storagedir:-/storage}" local sizeError="your destination SD card device does not have enough space, it needs to have at least twice as much as the source" local infoText1="DANGEROUS OPERATION, USE WITH PRECAUTION!\\n\\nThis will *copy* your system root from your SD card to a USB attached card writer device. Are you sure" - local infoText2="is an SD card writer device equipped with a dispensible SD card ? Are you this will destroy all data on that card and you want to proceed writing to this device ?" - + local infoText2="is an SD card writer device equipped with a dispensible SD card? Are you sure, this will destroy all data on that card and you want to proceed writing to this device?" echo -n "$(timestamp) [openHABian] Setting up automated SD mirroring and backup... " + if [[ "$1" == "remove" ]]; then cond_redirect systemctl disable sdrsync.service sdrawcopy.service sdrsync.timer sdrawcopy.timer rm -f ${serviceTargetDir}/sdr*.{service,timer} cond_redirect systemctl -q daemon-reload &> /dev/null return 0 fi + if [[ "$1" != "install" ]]; then echo "FAILED"; return 1; fi if ! is_pi; then @@ -461,11 +467,8 @@ setup_mirror_SD() { mkdir -p "${storageDir}" if cond_redirect apt-get install --yes gdisk; then echo "OK"; else echo "FAILED (install gdisk)"; return 1; fi - - # shellcheck disable=SC2154 - if [[ -n "$UNATTENDED" ]] && [[ -z "$backupdrive" ]]; then return 0; fi - if ! cond_redirect install -m 755 "${BASEDIR:-/opt/openhabian}"/includes/set-partuuid /usr/local/sbin; then echo "FAILED (install set-partuuid)"; return 1; fi + if [[ -n "$INTERACTIVE" ]]; then select_blkdev "^sd" "Setup SD mirroring" "Select USB device to copy the internal SD card data to" if [[ -z "$retval" ]]; then return 0; fi diff --git a/functions/helpers.bash b/functions/helpers.bash index dac9f6c28..40e9b3417 100644 --- a/functions/helpers.bash +++ b/functions/helpers.bash @@ -439,6 +439,6 @@ select_blkdev() { else ((count=${#array[@]} + 8)) # shellcheck disable=SC2034 - retval="$(whiptail --title "$2" --cancel-button Cancel --ok-button Select --menu "\n${3}" ${count} 76 0 "${array[@]}" 3>&1 1>&2 2>&3)" + retval="$(whiptail --title "$2" --cancel-button Cancel --ok-button Select --menu "\n${3}" "${count}" 76 0 "${array[@]}" 3>&1 1>&2 2>&3)" fi } diff --git a/functions/java-jre.bash b/functions/java-jre.bash index 14fc42915..7d0987dd3 100644 --- a/functions/java-jre.bash +++ b/functions/java-jre.bash @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2119,SC2120 ## Install appropriate Java version based on current choice. ## Valid arguments: "Adopt11", "Zulu8-32", "Zulu8-64", "Zulu11-32", or "Zulu11-64" @@ -116,7 +117,12 @@ java_zulu_prerequisite() { if is_aarch64 && [[ $(getconf LONG_BIT) == 64 ]]; then if dpkg -s 'libc6:arm64' 'libstdc++6:arm64' 'zlib1g:arm64' &> /dev/null; then echo "OK"; return 0; fi dpkg --add-architecture arm64 - if ! cond_redirect apt-get update; then echo "FAILED (update apt lists)"; return 1; fi + if ! cond_redirect apt-get update; then + echo "FAILED (update apt lists)" + if [[ -z $OFFLINE ]]; then + return 1 + fi + fi if cond_redirect apt-get install --yes libc6:arm64 libstdc++6:arm64 zlib1g:arm64; then echo "OK"; else echo "FAILED"; return 1; fi elif is_x86_64 && [[ $(getconf LONG_BIT) == 64 ]]; then if dpkg -s 'libc6:amd64' 'libstdc++6:amd64' 'zlib1g:amd64' &> /dev/null; then echo "OK"; return 0; fi @@ -128,7 +134,12 @@ java_zulu_prerequisite() { if is_arm; then if dpkg -s 'libc6:armhf' 'libstdc++6:armhf' 'zlib1g:armhf' &> /dev/null; then echo "OK"; return 0; fi dpkg --add-architecture armhf - if ! cond_redirect apt-get update; then echo "FAILED (update apt lists)"; return 1; fi + if ! cond_redirect apt-get update; then + echo "FAILED (update apt lists)" + if [[ -z $OFFLINE ]]; then + return 1 + fi + fi if cond_redirect apt-get install --yes libc6:armhf libstdc++6:armhf zlib1g:armhf; then echo "OK"; else echo "FAILED"; return 1; fi else if dpkg -s 'libc6:i386' 'libstdc++6:i386' 'zlib1g:i386' &> /dev/null; then echo "OK"; return 0; fi @@ -233,14 +244,14 @@ java_zulu_install() { ## Fetch Java Zulu 8 directly from Azul API v1 ## Valid arguments: "Zulu8-32", "Zulu8-64", "Zulu11-32", or "Zulu11-64" ## -## java_zulu_fetch(String type) +## java_zulu_fetch(String type, String prefix) ## java_zulu_fetch() { local downloadLink local jdkInstallLocation local link - jdkInstallLocation="/opt/jdk" + jdkInstallLocation="${2}/opt/jdk" link="https://api.azul.com/zulu/download/community/v1.0/bundles/latest/binary/?os=linux&ext=tar.gz&javafx=false" if [[ $1 == "Zulu8-32" ]]; then @@ -274,7 +285,7 @@ java_zulu_fetch() { fi if [[ -z $downloadLink ]]; then echo "FAILED (download link)"; return 1; fi - if ! mkdir -p $jdkInstallLocation; then echo "FAILED (create directory)"; return 1; fi + if ! mkdir -p "$jdkInstallLocation"; then echo "FAILED (create directory)"; return 1; fi if ! rm -rf "${jdkInstallLocation:?}"/*; then echo "FAILED (clean directory)"; return 1; fi if ! cond_redirect wget -O "$jdkInstallLocation"/zulu.tar.gz "$downloadLink"; then echo "FAILED (download)"; rm -rf "${jdkInstallLocation:?}"/*; return 1; fi if ! cond_redirect tar -xpzf "$jdkInstallLocation"/zulu.tar.gz -C "$jdkInstallLocation"; then echo "FAILED (extract)"; rm -rf "${jdkInstallLocation:?}"/*; return 1; fi @@ -387,13 +398,18 @@ java_zulu_enterprise_apt() { ## Install Zulu Cryptography Extension Kit to enable cryptos using more then 128 bits ## -## java_zulu_install_crypto_extension() +## java_zulu_install_crypto_extension(String path) ## java_zulu_install_crypto_extension() { + if [[ -n $OFFLINE ]]; then + echo "$(timestamp) [openHABian] Using cached Java Zulu CEK to enable unlimited cipher strength... OK" + return 0 + fi + local jdkSecurity local policyTempLocation - jdkSecurity="$(realpath /usr/bin/java | sed 's|/java||')/../lib/security" + jdkSecurity="${1:-"$(realpath /usr/bin/java | sed 's|/java||')/../lib/security"}" policyTempLocation="$(mktemp -d "${TMPDIR:-/tmp}"/openhabian.XXXXX)" echo -n "$(timestamp) [openHABian] Installing Java Zulu CEK to enable unlimited cipher strength... " diff --git a/functions/nodejs-apps.bash b/functions/nodejs-apps.bash index 1ff03438f..96d59ee41 100644 --- a/functions/nodejs-apps.bash +++ b/functions/nodejs-apps.bash @@ -20,21 +20,31 @@ nodejs_setup() { myDistro="$(lsb_release -sc)" temp="$(mktemp "${TMPDIR:-/tmp}"/openhabian.XXXXX)" - if is_armv6l; then + if [[ -z $PREOFFLINE ]] && is_armv6l; then echo -n "$(timestamp) [openHABian] Installing NodeJS... " if ! cond_redirect wget -qO "$temp" "$link"; then echo "FAILED (download)"; rm -f "$temp"; return 1; fi if ! cond_redirect tar -Jxf "$temp" --strip-components=1 -C /usr; then echo "FAILED (extract)"; rm -f "$temp"; return 1; fi if cond_redirect rm -f "$temp"; then echo "OK"; else echo "FAILED (cleanup)"; return 1; fi else - if ! add_keys "https://deb.nodesource.com/gpgkey/nodesource.gpg.key"; then return 1; fi - - echo -n "$(timestamp) [openHABian] Adding NodeSource repository to apt... " - echo "deb https://deb.nodesource.com/node_12.x $myDistro main" > /etc/apt/sources.list.d/nodesource.list - echo "deb-src https://deb.nodesource.com/node_12.x $myDistro main" >> /etc/apt/sources.list.d/nodesource.list - if cond_redirect apt-get update; then echo "OK"; else echo "FAILED (update apt lists)"; return 1; fi + if [[ -z $OFFLINE ]]; then + if ! add_keys "https://deb.nodesource.com/gpgkey/nodesource.gpg.key"; then return 1; fi + + echo -n "$(timestamp) [openHABian] Adding NodeSource repository to apt... " + echo "deb https://deb.nodesource.com/node_12.x $myDistro main" > /etc/apt/sources.list.d/nodesource.list + echo "deb-src https://deb.nodesource.com/node_12.x $myDistro main" >> /etc/apt/sources.list.d/nodesource.list + if [[ -n $PREOFFLINE ]]; then + if cond_redirect apt-get --quiet update; then echo "OK"; else echo "FAILED (update apt lists)"; return 1; fi + else + if cond_redirect apt-get update; then echo "OK"; else echo "FAILED (update apt lists)"; return 1; fi + fi + fi echo -n "$(timestamp) [openHABian] Installing NodeJS... " - if cond_redirect apt-get install --yes nodejs; then echo "OK"; else echo "FAILED"; return 1; fi + if [[ -n $PREOFFLINE ]]; then + if cond_redirect apt-get --quiet install --download-only --yes nodejs; then echo "OK"; else echo "FAILED"; return 1; fi + else + if cond_redirect apt-get install --yes nodejs; then echo "OK"; else echo "FAILED"; return 1; fi + fi fi } @@ -44,7 +54,7 @@ nodejs_setup() { ## frontail_setup() { local frontailBase - local frontailUser=frontail + local frontailUser="frontail" if ! [[ -x $(command -v npm) ]] || [[ $(node --version) != "v12"* ]] || is_armv6l; then echo -n "$(timestamp) [openHABian] Installing Frontail prerequsites (NodeJS)... " diff --git a/functions/openhab.bash b/functions/openhab.bash index c15a17ad9..23f741ae8 100644 --- a/functions/openhab.bash +++ b/functions/openhab.bash @@ -76,14 +76,19 @@ openhab2_setup() { echo "OK" fi - if ! add_keys "https://bintray.com/user/downloadSubjectPublicKey?username=openhab"; then return 1; fi + if [[ -z $OFFLINE ]]; then + if ! add_keys "https://bintray.com/user/downloadSubjectPublicKey?username=openhab"; then return 1; fi - echo "$repo" > /etc/apt/sources.list.d/openhab2.list + echo "$repo" > /etc/apt/sources.list.d/openhab2.list - echo -n "$(timestamp) [openHABian] Installing selected openHAB version... " - if ! cond_redirect apt-get update; then echo "FAILED (update apt lists)"; return 1; fi - openhabVersion="$(apt-cache madison openhab2 | head -n 1 | cut -d'|' -f2 | xargs)" - if cond_redirect apt-get install --allow-downgrades --yes "openhab2=${openhabVersion}" "openhab2-addons=${openhabVersion}"; then echo "OK"; else echo "FAILED"; return 1; fi + echo -n "$(timestamp) [openHABian] Installing selected openHAB version... " + if ! cond_redirect apt-get update; then echo "FAILED (update apt lists)"; return 1; fi + openhabVersion="$(apt-cache madison openhab2 | head -n 1 | cut -d'|' -f2 | xargs)" + if cond_redirect apt-get install --allow-downgrades --yes "openhab2=${openhabVersion}" "openhab2-addons=${openhabVersion}"; then echo "OK"; else echo "FAILED"; return 1; fi + else + echo -n "$(timestamp) [openHABian] Installing cached openHAB version... " + if cond_redirect apt-get install --yes openhab2 openhab2-addons; then echo "OK"; else echo "FAILED"; return 1; fi + fi echo -n "$(timestamp) [openHABian] Setting up openHAB service... " if ! cond_redirect systemctl -q daemon-reload &> /dev/null; then echo "FAILED (daemon-reload)"; return 1; fi diff --git a/functions/openhabian.bash b/functions/openhabian.bash index 9f143d48b..ac1b886e1 100644 --- a/functions/openhabian.bash +++ b/functions/openhabian.bash @@ -25,6 +25,7 @@ get_git_revision() { install_cleanup() { echo -n "$(timestamp) [openHABian] Cleaning up... " if ! cond_redirect systemctl -q daemon-reload &> /dev/null; then echo "FAILED (daemon-reload)"; return 1; fi + if ! cond_redirect apt-get clean; then echo "FAILED (apt-get clean)"; return 1; fi if cond_redirect apt-get autoremove --yes; then echo "OK"; else echo "FAILED"; return 1; fi } diff --git a/functions/packages.bash b/functions/packages.bash index 3d065c56c..50ee789ba 100644 --- a/functions/packages.bash +++ b/functions/packages.bash @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2120 ## Function for installing samba for remote access of folders. ## This function can be invoked either INTERACTIVE with userinterface or UNATTENDED. @@ -29,50 +30,63 @@ samba_setup() { if cond_redirect systemctl enable --now smbd.service &> /dev/null; then echo "OK"; else echo "FAILED (enable service)"; return 1; fi } +## Function for downloading FireMotD to current system +## +## firemotd_download(String prefix) +## +firemotd_download() { + echo -n "$(timestamp) [openHABian] Downloading FireMotD... " + if ! [[ -d "${1}/FireMotD" ]]; then + cond_echo "\\nFresh Installation... " + if cond_redirect git clone https://github.com/OutsideIT/FireMotD.git "${1}/FireMotD"; then echo "OK"; else echo "FAILED (git clone)"; return 1; fi + else + cond_echo "\\nUpdate... " + if cond_redirect update_git_repo "${1}/FireMotD" "master"; then echo "OK"; else echo "FAILED (update git repo)"; return 1; fi + fi +} + ## Function for installing FireMotD which displays the system overview on login. ## This function can be invoked either INTERACTIVE with userinterface or UNATTENDED. ## ## firemotd_setup() ## firemotd_setup() { - local temp - local targetDir="/etc/systemd/system/" + if running_in_docker || running_on_github; then return 0; fi - temp="$(mktemp "${TMPDIR:-/tmp}"/openhabian.XXXXX)" + local firemotdDir="/opt/FireMotD" + local targetDir="/etc/systemd/system/" - if ! dpkg -s 'bc' 'sysstat' 'jq' 'moreutils' &> /dev/null; then + if ! dpkg -s 'bc' 'sysstat' 'jq' 'moreutils' 'make' &> /dev/null; then echo -n "$(timestamp) [openHABian] Installing FireMotD required packages (bc, sysstat, jq, moreutils)... " - if cond_redirect apt-get install --yes bc sysstat jq moreutils; then echo "OK"; else echo "FAILED"; return 1; fi + if cond_redirect apt-get install --yes bc sysstat jq moreutils make; then echo "OK"; else echo "FAILED"; return 1; fi fi - echo -n "$(timestamp) [openHABian] Downloading FireMotD... " - if cond_redirect wget -O "$temp" https://raw.githubusercontent.com/OutsideIT/FireMotD/master/FireMotD; then - echo "OK" - else - echo "FAILED" - rm -f "$temp" - return 1 + if ! firemotd_download /opt; then + if [[ -z $OFFLINE ]]; then + return 1 + fi fi - echo -n "$(timestamp) [openHABian] Setting up FireMotD... " - chmod 755 "$temp" - if cond_redirect "$temp" -I; then echo "OK"; rm -f "$temp"; else echo "FAILED"; rm -f "$temp"; return 1; fi + echo -n "$(timestamp) [openHABian] Installing FireMotD... " + if ! cond_redirect make --always-make --directory="$firemotdDir" install; then echo "FAILED (install FireMotD)"; return 1; fi + if cond_redirect make --always-make --directory="$firemotdDir" bash_completion; then echo "OK"; else echo "FAILED (install FireMotD bash completion)"; return 1; fi echo -n "$(timestamp) [openHABian] Generating FireMotD theme... " + if ! cond_redirect FireMotD -S -D all; then echo "FAILED (generate FireMotD)"; return 1; fi if cond_redirect FireMotD -G Gray; then echo "OK"; else echo "FAILED"; return 1; fi - if ! grep -q "FireMotD" /home/"${username:-openhabian}"/.bash_profile; then + if ! grep -qs "FireMotD" /home/"${username:-openhabian}"/.bash_profile; then echo -n "$(timestamp) [openHABian] Make FireMotD display on login... " if echo -e "\\necho\\nFireMotD --theme Gray \\necho" >> /home/"${username:-openhabian}"/.bash_profile; then echo "OK"; else echo "FAILED"; return 1; fi fi echo -n "$(timestamp) [openHABian] Setting up FireMotD apt updates count service... " cond_echo "\\nMake FireMotD check for new updates every night... " - if cond_redirect cp "${BASEDIR}"/includes/firemotd.* "$targetDir"/; then echo "OK"; else echo "FAILED"; return 1; fi + if cond_redirect cp "${BASEDIR}"/includes/firemotd.* "$targetDir"; then echo "OK"; else echo "FAILED"; return 1; fi if ! cond_redirect systemctl -q daemon-reload &> /dev/null; then echo "FAILED (daemon-reload)"; return 1; fi if ! cond_redirect systemctl enable firemotd.service &> /dev/null; then echo "FAILED (service enable)"; return 1; fi cond_echo "\\nMake FireMotD check for new updates after using apt... " - echo "DPkg::Post-Invoke { \"if [ -x /usr/local/bin/FireMotD ]; then echo -n 'Updating FireMotD available updates count ... '; /bin/bash /usr/local/bin/FireMotD --skiprepoupdate -S; echo ''; fi\"; };" > /etc/apt/apt.conf.d/15firemotd + if ! cond_redirect install -m 644 "${BASEDIR:-/opt/openhabian}"/includes/15firemotd /etc/apt/apt.conf.d/; then echo "FAILED (apt configuration)"; return 1; fi cond_echo "\\nInitial FireMotD updates check" if cond_redirect FireMotD -S; then echo "OK"; else echo "FAILED"; return 1; fi } @@ -83,6 +97,11 @@ firemotd_setup() { ## exim_setup() ## exim_setup() { + if [[ -n $UNATTENDED ]] && [[ -z $relayuser ]]; then + echo "$(timestamp) [openHABian] Beginning Mail Transfer Agent setup... CANCELED (no configuration provided)" + return 0 + fi + local updateEximTemplate="${BASEDIR:-/opt/openhabian}/includes/update-exim4.conf.conf-template" local eximConfig="/etc/exim4/update-exim4.conf.conf" local eximPasswd="/etc/exim4/passwd.client" diff --git a/functions/system.bash b/functions/system.bash index 0139907bf..b15445e0f 100644 --- a/functions/system.bash +++ b/functions/system.bash @@ -46,16 +46,16 @@ needed_packages() { local bluetoothPackages="bluez python3-dev libbluetooth-dev raspberrypi-sys-mods pi-bluetooth" # Install apt-transport-https - update packages through https repository - # Install bc + sysstat - needed for FireMotD + # Install bc/sysstat/jq/moreutils - needed for FireMotD # Install avahi-daemon - hostname based discovery on local networks # Install python3/python3-pip/python3-wheel/python3-setuptools - for python packages echo -n "$(timestamp) [openHABian] Installing additional needed packages... " - if cond_redirect apt-get install --yes apt-transport-https bc sysstat \ - avahi-daemon python3 python3-pip python3-wheel python3-setuptools \ + if cond_redirect apt-get install --yes apt-transport-https bc sysstat jq \ + moreutils avahi-daemon python3 python3-pip python3-wheel python3-setuptools \ avahi-autoipd fontconfig; \ then echo "OK"; else echo "FAILED"; return 1; fi - if is_pizerow || is_pithree || is_pithreeplus || is_pifour; then + if is_pizerow || is_pithree || is_pithreeplus || is_pifour && [[ -z $PREOFFLINE ]]; then echo -n "$(timestamp) [openHABian] Installing additional bluetooth packages... " # phython3-bluez is not available in stretch so only add it if we are runnning on buster or later if ! is_stretch; then diff --git a/includes/15firemotd b/includes/15firemotd new file mode 100644 index 000000000..8bb5ee98c --- /dev/null +++ b/includes/15firemotd @@ -0,0 +1,3 @@ +DPkg::Post-Invoke { + "if [ -x /usr/local/bin/FireMotD ]; then echo -n 'Updating FireMotD available updates count ... '; /usr/local/bin/FireMotD --skiprepoupdate -S; echo ''; fi"; +}; diff --git a/includes/firemotd.service b/includes/firemotd.service index 2d01c6ab8..532416a72 100644 --- a/includes/firemotd.service +++ b/includes/firemotd.service @@ -1,5 +1,5 @@ [Unit] -Description=periodic FireMotD stats regeneration +Description=Periodic FireMotD stats regeneration [Service] Type=oneshot diff --git a/includes/offline-install-modifications.bash b/includes/offline-install-modifications.bash new file mode 100755 index 000000000..cb52ca84a --- /dev/null +++ b/includes/offline-install-modifications.bash @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +export BASEDIR="/opt/openhabian" +export DEBIAN_FRONTEND="noninteractive" +export PREOFFLINE="1" + +source /opt/openhabian/functions/helpers.bash +add_keys "https://bintray.com/user/downloadSubjectPublicKey?username=openhab" +echo "deb https://dl.bintray.com/openhab/apt-repo2 stable main" > /etc/apt/sources.list.d/openhab2.list +apt-get --quiet update +apt-get --quiet upgrade --yes +apt-get --quiet install --download-only --yes libattr1-dev libc6 libstdc++6 \ + zlib1g make openhab2 openhab2-addons samba amanda-common amanda-server \ + amanda-client exim4 dnsutils mailutils gdisk screen vim nano mc vfu \ + bash-completion htop curl wget multitail git util-linux bzip2 zip unzip \ + xz-utils software-properties-common man-db whiptail acl usbutils dirmngr \ + arping apt-transport-https bc sysstat jq moreutils avahi-daemon python3 \ + python3-pip python3-wheel python3-setuptools avahi-autoipd fontconfig +source /opt/openhabian/functions/nodejs-apps.bash +nodejs_setup +apt-get --quiet autoremove --yes +exit diff --git a/openhabian-setup.sh b/openhabian-setup.sh index 533c1d10f..cb12edd1e 100755 --- a/openhabian-setup.sh +++ b/openhabian-setup.sh @@ -82,7 +82,7 @@ config_ipv6 if [[ -n "$UNATTENDED" ]]; then # apt/dpkg commands will not try interactive dialogs - export DEBIAN_FRONTEND=noninteractive + export DEBIAN_FRONTEND="noninteractive" wait_for_apt_to_finish_update load_create_config change_swapsize diff --git a/openhabian.conf.dist b/openhabian.conf.dist index d1ad8d0e8..00bf10e3a 100644 --- a/openhabian.conf.dist +++ b/openhabian.conf.dist @@ -25,6 +25,12 @@ system_default_locale="en_US.UTF-8" wifi_ssid="" wifi_psk="" +# Wi-Fi setting. Select a two-letter country code suitable for your location +# E.g. US (default), DE, AU, NZ... +# You may infringe on local legislature otherwise +# See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 or /usr/share/zoneinfo/zone.tab +wifi_country="" + # Eventually disable all IPv6 e.g. on installation problems # values: "enable", "disable" ipv6=enable @@ -71,6 +77,5 @@ java_opt=Zulu8-64 #relaypass=secret #smarthost=smtp.gmail.com #smartport=587 -# # vim: filetype=sh