From cc0e1ac55a1a2c874c1a5a7346bfea314fd61ded Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 13 Jan 2024 10:29:10 +0100 Subject: [PATCH 01/18] feat!: use rugpi repositories and layers feature --- .github/workflows/bake-image.yml | 42 +- .gitignore | 8 +- README.md | 135 ++-- env.template | 9 + images/pi01.toml | 5 - images/pi023.toml | 3 - images/pi4.toml | 4 - images/pi45.toml | 4 - justfile | 139 ++-- layers/containers.toml | 7 + layers/default.toml | 6 + profiles/armhf.toml | 26 - profiles/default.toml | 18 - profiles/wifi.toml | 26 - recipes/build-info/files/.gitignore | 0 recipes/build-info/recipe.toml | 2 - recipes/build-info/steps/00-install.sh | 10 - .../health-check/files/health.d/00-time-sync | 46 -- .../files/health.d/10-tedge-health | 19 - recipes/health-check/files/healthcheck.sh | 57 -- recipes/health-check/recipe.toml | 2 - recipes/health-check/steps/00-install.sh | 8 - recipes/mosquitto/recipe.toml | 2 - recipes/mosquitto/steps/00-install.sh | 11 - recipes/persist-data/files/data.toml | 2 - recipes/persist-data/recipe.toml | 2 - recipes/persist-data/steps/00-install.sh | 7 - .../files/network-manager-config.toml | 2 - recipes/persist-network-manager/recipe.toml | 2 - .../steps/00-install.sh | 3 - recipes/persist-overlay/files/ctrl.toml | 1 - recipes/persist-overlay/recipe.toml | 2 - recipes/persist-overlay/steps/00-install.sh | 3 - recipes/sbom/recipe.toml | 2 - recipes/sbom/steps/00-install.sh | 8 - recipes/set-wifi/recipe.toml | 7 - recipes/set-wifi/steps/00-install.sh | 29 - recipes/tedge-bootstrap/files/hostname.toml | 2 - recipes/tedge-bootstrap/files/tedge-bootstrap | 128 ---- .../files/tedge-bootstrap.service | 13 - recipes/tedge-bootstrap/files/tedge-identity | 101 --- recipes/tedge-bootstrap/recipe.toml | 1 - recipes/tedge-bootstrap/steps/00-install.sh | 8 - .../files/firmware-auto-rollback | 15 - .../files/firmware-auto-rollback.service | 9 - .../files/firmware-auto-rollback.timer | 8 - .../files/firmware-version | 26 - .../files/firmware_update.rugpi.toml | 67 -- .../files/rugpi_workflow.sh | 313 --------- .../tedge-firmware-update/files/system.toml | 2 - .../files/tedge-firmware | 1 - recipes/tedge-firmware-update/recipe.toml | 7 - .../tedge-firmware-update/steps/00-install.sh | 19 - recipes/thin-edge.io/files/custom.conf | 1 - recipes/thin-edge.io/files/tedge-config.toml | 12 - .../files/tedge-configuration-plugin.toml | 14 - .../thin-edge.io/files/tedge-log-plugin.toml | 11 - recipes/thin-edge.io/files/thin-edge.io.sh | 655 ------------------ recipes/thin-edge.io/recipe.toml | 2 - recipes/thin-edge.io/steps/00-install.sh | 58 -- recipes/x-avahi-daemon/files/tedge.service | 19 - recipes/x-avahi-daemon/recipe.toml | 1 - recipes/x-avahi-daemon/steps/00-packages | 2 - recipes/x-avahi-daemon/steps/01-install.sh | 12 - rugpi-bakery.toml | 25 + run-bakery | 2 +- 66 files changed, 265 insertions(+), 1928 deletions(-) create mode 100644 env.template delete mode 100644 images/pi01.toml delete mode 100644 images/pi023.toml delete mode 100644 images/pi4.toml delete mode 100644 images/pi45.toml create mode 100644 layers/containers.toml create mode 100644 layers/default.toml delete mode 100644 profiles/armhf.toml delete mode 100644 profiles/default.toml delete mode 100644 profiles/wifi.toml delete mode 100644 recipes/build-info/files/.gitignore delete mode 100644 recipes/build-info/recipe.toml delete mode 100755 recipes/build-info/steps/00-install.sh delete mode 100755 recipes/health-check/files/health.d/00-time-sync delete mode 100755 recipes/health-check/files/health.d/10-tedge-health delete mode 100755 recipes/health-check/files/healthcheck.sh delete mode 100644 recipes/health-check/recipe.toml delete mode 100755 recipes/health-check/steps/00-install.sh delete mode 100644 recipes/mosquitto/recipe.toml delete mode 100755 recipes/mosquitto/steps/00-install.sh delete mode 100644 recipes/persist-data/files/data.toml delete mode 100644 recipes/persist-data/recipe.toml delete mode 100755 recipes/persist-data/steps/00-install.sh delete mode 100644 recipes/persist-network-manager/files/network-manager-config.toml delete mode 100644 recipes/persist-network-manager/recipe.toml delete mode 100755 recipes/persist-network-manager/steps/00-install.sh delete mode 100644 recipes/persist-overlay/files/ctrl.toml delete mode 100644 recipes/persist-overlay/recipe.toml delete mode 100755 recipes/persist-overlay/steps/00-install.sh delete mode 100644 recipes/sbom/recipe.toml delete mode 100755 recipes/sbom/steps/00-install.sh delete mode 100644 recipes/set-wifi/recipe.toml delete mode 100755 recipes/set-wifi/steps/00-install.sh delete mode 100644 recipes/tedge-bootstrap/files/hostname.toml delete mode 100755 recipes/tedge-bootstrap/files/tedge-bootstrap delete mode 100644 recipes/tedge-bootstrap/files/tedge-bootstrap.service delete mode 100755 recipes/tedge-bootstrap/files/tedge-identity delete mode 100644 recipes/tedge-bootstrap/recipe.toml delete mode 100755 recipes/tedge-bootstrap/steps/00-install.sh delete mode 100755 recipes/tedge-firmware-update/files/firmware-auto-rollback delete mode 100644 recipes/tedge-firmware-update/files/firmware-auto-rollback.service delete mode 100644 recipes/tedge-firmware-update/files/firmware-auto-rollback.timer delete mode 100755 recipes/tedge-firmware-update/files/firmware-version delete mode 100644 recipes/tedge-firmware-update/files/firmware_update.rugpi.toml delete mode 100755 recipes/tedge-firmware-update/files/rugpi_workflow.sh delete mode 100644 recipes/tedge-firmware-update/files/system.toml delete mode 100644 recipes/tedge-firmware-update/files/tedge-firmware delete mode 100644 recipes/tedge-firmware-update/recipe.toml delete mode 100755 recipes/tedge-firmware-update/steps/00-install.sh delete mode 100644 recipes/thin-edge.io/files/custom.conf delete mode 100644 recipes/thin-edge.io/files/tedge-config.toml delete mode 100644 recipes/thin-edge.io/files/tedge-configuration-plugin.toml delete mode 100644 recipes/thin-edge.io/files/tedge-log-plugin.toml delete mode 100755 recipes/thin-edge.io/files/thin-edge.io.sh delete mode 100644 recipes/thin-edge.io/recipe.toml delete mode 100755 recipes/thin-edge.io/steps/00-install.sh delete mode 100644 recipes/x-avahi-daemon/files/tedge.service delete mode 100644 recipes/x-avahi-daemon/recipe.toml delete mode 100644 recipes/x-avahi-daemon/steps/00-packages delete mode 100755 recipes/x-avahi-daemon/steps/01-install.sh create mode 100644 rugpi-bakery.toml diff --git a/.github/workflows/bake-image.yml b/.github/workflows/bake-image.yml index 813144c..914dc7b 100644 --- a/.github/workflows/bake-image.yml +++ b/.github/workflows/bake-image.yml @@ -12,14 +12,14 @@ jobs: name: Build information runs-on: ubuntu-latest outputs: - version: ${{ steps.step1.outputs.version }} + version: ${{ steps.info.outputs.version }} steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - uses: extractions/setup-just@v1 - - id: step1 + - id: info name: Get Version run: | case "${GITHUB_REF}" in @@ -35,37 +35,53 @@ jobs: echo "version=$version" >> "$GITHUB_OUTPUT" bake-image: - name: Bake Image ${{ matrix.job.arch }} - ${{ matrix.job.profile }} - ${{ matrix.job.variant }} + name: Bake Image ${{ matrix.job.image }} runs-on: ubuntu-latest needs: info strategy: fail-fast: false matrix: job: - - { arch: armhf, profile: armhf, variant: pi01 } - - { arch: arm64, profile: default, variant: pi023 } - - { arch: arm64, profile: default, variant: pi4 } - - { arch: arm64, profile: default, variant: pi45 } + - { image: pi4 } + - { image: tryboot } + - { image: u-boot } + - { image: u-boot-armhf } steps: - uses: actions/checkout@v3 with: submodules: recursive - uses: extractions/setup-just@v1 + - name: Install dependencies + run: just setup + - id: info + env: + VERSION: ${{needs.info.outputs.version}} + run: | + source <(just show) + echo "PREFIX=$PREFIX" >> "$GITHUB_OUTPUT" + - name: Configure .env + env: + IMAGE_CONFIG: ${{secrets.IMAGE_CONFIG || ''}} + run: | + echo "IMAGE_NAME=${{ steps.info.outputs.PREFIX }}${{ matrix.job.image }}_${{ needs.info.outputs.version }}" > ".env" + if [ -n "$IMAGE_CONFIG" ]; then + echo "Adding custom IMAGE_CONFIG settings to .env" + echo "$IMAGE_CONFIG" >> ".env" + fi + - name: Build image env: VERSION: ${{needs.info.outputs.version}} run: | - mkdir build - just IMAGE_ARCH=${{ matrix.job.arch }} PROFILE=${{ matrix.job.profile }} VARIANT=${{ matrix.job.variant }} build-all - mv recipes/sbom/debian-packages.list build/tedge_rugpi_${{matrix.job.profile}}_${{matrix.job.variant}}_${{needs.info.outputs.version}}.sbom.txt + just IMAGE=${{ matrix.job.image }} build - name: Upload Image uses: actions/upload-artifact@v3 with: - name: tedge_rugpi_${{matrix.job.profile}}_${{matrix.job.variant}}_${{needs.info.outputs.version}} + name: ${{ steps.info.outputs.PREFIX }}${{ matrix.job.image }}_${{ needs.info.outputs.version }} path: | - build/tedge_rugpi_${{matrix.job.profile}}_${{matrix.job.variant}}_${{needs.info.outputs.version}}*.xz - build/tedge_rugpi_${{matrix.job.profile}}_${{matrix.job.variant}}_${{needs.info.outputs.version}}.sbom.txt + build/ + *.sbom.txt release: name: Release diff --git a/.gitignore b/.gitignore index 5c34264..c4f71ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /.rugpi /build -recipes/build-info/files/.build_info -**/debian-packages.list -rugpi-bakery.toml -*.log \ No newline at end of file +.image +*.sbom.txt +*.log +*.env \ No newline at end of file diff --git a/README.md b/README.md index 3b9305a..daf3e56 100644 --- a/README.md +++ b/README.md @@ -22,77 +22,108 @@ The repository can be used to build custom Raspberry Pi images with thin-edge.io The following images are included in this repository. -A profile determines what software and configuration is included in the image. +|Image|Description| +|-------|-----------| +|tryboot|Image for Raspberry Pi 4 and 5 devices which use the tryboot bootloader| +|rpi4|Raspberry Pi 4 image which includes the firmware to enable tryboot bootloader| +|u-boot|Image for Raspberry Pi 2, 3, zero 2W| +|u-boot-armhf|Image for Raspberry Pi 1 and zero| -A variant is more hardware specific which uses the same profile but makes hardware specific tweaks based on the hardware limitations. For example Raspberry 2, 3 and Zero 2 W do not support the tryboot feature, so instead the u-boot bootloader is used to facilitate the robust OTA image updates. +## Building -The following sections describe the profiles and variants available. +### Building an image without WIFI credentials (devices must have an ethernet adapter!) -### Profiles +To run the build tasks, install [just](https://just.systems/man/en/chapter_5.html). -|Profile|Description| -|-------|-----------| -|default|Default image which does not include WiFi credentials| -|wifi|All the contents of the default image but also has WiFi credentials included in the image. Suitable for devices without an ethernet adapter| +1. Create a custom `.env` file which will be used to store secrets + ```sh + cp env.template .env + ``` -### Variants +2. Edit the `.env` file -|Variant|Supported Raspberry Pi Versions|Description| -|-------|-------------------------------|-----------| -|pi45|4 and 5|Does not include firmware so rpi4 needs to have up to date firmware for this image to work!| -|pi4|4|Includes firmware which enables the tryboot mechanism| -|pi023|2, 3 and Zero 2 W|Uses u-boot| + If you want to include wifi credentials in your image, then edit the values in the `.env` file: + ```sh + SECRETS_WIFI_SSID=example + SECRETS_WIFI_PASSWORD=yoursecurepassword + SSH_KEYS_bootstrap="ssh-rsa xxxxxxx" + ``` -## Building + **Note** -### Building an image without WIFI credentials (devices must have an ethernet adapter!) + If you include wifi credentials in your image, make sure you don't make the image public, as it would expose your credentials! -To run the build tasks, install [just](https://just.systems/man/en/chapter_5.html). + Alternatively, you could build an image locally which includes the wifi credentials, and then any future builds you don't need to include the wifi credentials as they should be persisted. -1. Create the image (including downloading the supported base Raspberry Pi image) using: +3. Create the image (including downloading the supported base Raspberry Pi image) using: ```sh - just VARIANT=pi45 build-all + just IMAGE=tryboot build ``` -2. Using the path to the image shown in the console to flash the image to the Raspberry Pi. +4. Using the path to the image shown in the console to flash the image to the Raspberry Pi. -3. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) +5. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) For further information on Rugpi, checkout the [quick start guide](https://oss.silitics.com/rugpi/docs/getting-started). -### Building an image with WIFI credentials -For devices that only support WIFI (e.g. don't have an ethernet adapter), the WIFI credentials are required to be part of the image, otherwise you don't have any way to connect via SSH to your device. +### Building for your specific device type + +The different image options can be confusing, so to help users a few device specific tasks were created to help you pick the correct image. -In the future this process will be looked to be improved, and potentially the standard raspberry pi way of using the wpa_supplicant will enable to work out of the box (so that you don't have to bake credentials into the image, and only add them when writing to flash). +#### Raspberry Pi 1 -The default WIFI credentials are as follows, though it assumes that the given WIFI setup is a non-trusted network that is only used for bootstrapping, and then a secure WIFI network is configured. +```sh +just build-pi1 +``` -|SSID|Password| -|----|--------| -|onboarding_jail|onboarding_jail| +#### Raspberry Pi 2 -1. Create the image (including downloading the supported base Raspberry Pi image) using: +```sh +just build-pi2 +``` - ```sh - just PROFILE=wifi VARIANT=pi023 build-all - ``` +#### Raspberry Pi 3 - Possible variants are: +```sh +just build-pi3 +``` + +#### Raspberry Pi 4 / 400 + +```sh +just build-pi4 +``` - * pi023 - * pi4 - * pi45 +**Note** - This profile will use pre-baked credentials for the WIFI which are defined in [profiles/wifi.toml](profiles/wifi.toml). +All Raspberry Pi 4 and 400 don't support tryboot by default, and need their firmware updated before the `tryboot` image can be used. -### Building for Raspberry 1 or Zero +You can build an image which also includes the firmware used to enable tryboot. Afterwards you can switch back to using an image without the firmware included in it. ```sh -just IMAGE_ARCH=armhf PROFILE=armhf VARIANT=pi01 build-all +just build-pi4-include-firmware +``` + +#### Raspberry Pi 5 + +```sh +just build-pi5 +``` + +#### Raspberry Pi Zero + +```sh +just build-pizero +``` + +#### Raspberry Pi Zero 2W + +```sh +just build-pizero2w ``` ## Project Tasks @@ -122,7 +153,7 @@ You will need [go-c8y-cli](https://goc8ycli.netlify.app/) and [gh](https://cli.g 1. In the console, using go-c8y-cli, set your session to the tenant where you want to upload the firmware to - ``` + ```sh set-session mytenant ``` @@ -143,3 +174,27 @@ You will need [go-c8y-cli](https://goc8ycli.netlify.app/) and [gh](https://cli.g This script will create firmware items (name and version) in Cumulocity IoT. The firmware versions will be just links to the external artifacts which are available from the Github Release artifacts. 3. Now you can select the firmware in Cumulocity IoT to deploy to your devices (assuming you have flashed the base image to the device first ;)! + +## Add SSH and/or wifi to Github workflow + +You can customize the images built by the Github workflow by creating a secret within Github. + +1. Create a repository secret with the following settings + + **Name** + + ```sh + IMAGE_CONFIG + ``` + + **Value** + + ```sh + SECRETS_WIFI_SSID="mywifi" + SECRETS_WIFI_PASSWORD="somepassword" + SSH_KEYS_bootstrap="ssh-rsa xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx bootstrap" + ``` + + Remove any lines which are not applicable to your build. + +2. Build the workflow from Github using the UI (or creating a new git tag) diff --git a/env.template b/env.template new file mode 100644 index 0000000..a38ad89 --- /dev/null +++ b/env.template @@ -0,0 +1,9 @@ +# wifi credentials - it will be ignored if the ssid is empty +#SECRETS_WIFI_ID=wifi +SECRETS_WIFI_SSID= +SECRETS_WIFI_PASSWORD= + +# SSH authorized keys +SSH_KEYS_bootstrap="ssh-rsa xxxxxxx" +#SSH_KEYS_user1="ssh-rsa xxxxxxx" +#SSH_KEYS_user2="ssh-rsa xxxxxxx" diff --git a/images/pi01.toml b/images/pi01.toml deleted file mode 100644 index e1cf20c..0000000 --- a/images/pi01.toml +++ /dev/null @@ -1,5 +0,0 @@ -architecture = "armhf" - -boot_flow = "u-boot" - -include_firmware = "none" diff --git a/images/pi023.toml b/images/pi023.toml deleted file mode 100644 index edeb682..0000000 --- a/images/pi023.toml +++ /dev/null @@ -1,3 +0,0 @@ -boot_flow = "u-boot" - -include_firmware = "none" diff --git a/images/pi4.toml b/images/pi4.toml deleted file mode 100644 index 7418bf7..0000000 --- a/images/pi4.toml +++ /dev/null @@ -1,4 +0,0 @@ -boot_flow = "tryboot" - -# Include firmware as some older pi4 need a firmware update before tryboot will work -include_firmware = "pi4" diff --git a/images/pi45.toml b/images/pi45.toml deleted file mode 100644 index f15ef5d..0000000 --- a/images/pi45.toml +++ /dev/null @@ -1,4 +0,0 @@ -boot_flow = "tryboot" - -# Make image generic so it can be used for pi4 and pi5 -include_firmware = "none" diff --git a/justfile b/justfile index a594bbd..e453b2d 100644 --- a/justfile +++ b/justfile @@ -1,24 +1,12 @@ +set dotenv-load -export IMAGE_URL_ARM64 := "https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-12-11/2023-12-11-raspios-bookworm-arm64-lite.img.xz" -export IMAGE_URL_ARMHF := "https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2023-12-11/2023-12-11-raspios-bookworm-armhf-lite.img.xz" +export IMAGE := "tryboot" -export IMAGE_ARCH := "arm64" - -export IMAGE_URL := if IMAGE_ARCH != "armhf" { IMAGE_URL_ARM64 } else { IMAGE_URL_ARMHF } -export RUGPI_IMAGE := "ghcr.io/silitics/rugpi-bakery:v0.5" +export RUGPI_IMAGE := "ghcr.io/silitics/rugpi-bakery:feat-layers" export PREFIX := "tedge_rugpi_" -export PROFILE := "default" - -export BASE_IMAGE := replace_regex(file_stem(IMAGE_URL), ".img$", "") -export BASE_TAR := "build" / BASE_IMAGE + ".base.tar" -export CUSTOM_TAR := "build" / BASE_IMAGE + "." + PROFILE + ".tar" - -export CUSTOMIZATION_PROFILE := "profiles" / PROFILE + ".toml" -export VARIANT := "pi45" -export IMAGE_CONFIG := "images/" + VARIANT + ".toml" export VERSION := env_var_or_default("VERSION", `date +'%Y%m%d.%H%M'`) -export IMAGE_NAME := PREFIX + PROFILE + "_" + VARIANT + "_" + VERSION +export IMAGE_NAME := PREFIX + IMAGE + "_" + VERSION export OUTPUT_IMAGE := "build" / IMAGE_NAME + ".img" export BUILD_INFO := IMAGE_NAME @@ -28,17 +16,11 @@ generate_version: # Show the install paths show: - @echo "IMAGE_URL: {{IMAGE_URL}}" - @echo "IMAGE_NAME: {{IMAGE_NAME}}" - @echo "CUSTOMIZATION_PROFILE: {{CUSTOMIZATION_PROFILE}}" - @echo "IMAGE_CONFIG: {{IMAGE_CONFIG}}" - - @echo "BASE_TAR: {{BASE_TAR}}" - @echo "CUSTOM_TAR: {{CUSTOM_TAR}}" - - @echo "OUTPUT_IMAGE: {{OUTPUT_IMAGE}}" - @echo "VERSION: {{VERSION}}" - @echo "BUILD_INFO: {{BUILD_INFO}}" + @echo "PREFIX={{PREFIX}}" + @echo "IMAGE={{IMAGE}}" + @echo "IMAGE_NAME={{IMAGE_NAME}}" + @echo "VERSION={{VERSION}}" + @echo "OUTPUT_IMAGE={{OUTPUT_IMAGE}}" # Setup binfmt tools # Note: technically only arm64,armhf are required, however install 'all' avoids the error message @@ -46,23 +28,20 @@ show: setup: docker run --privileged --rm tonistiigi/binfmt --install all -# Clean build +# Clean rugpi cache and build folders clean: + @rm -Rf .rugpi @rm -Rf build/ -# Download and extract the base image -extract: - ./run-bakery extract "{{IMAGE_URL}}" "{{BASE_TAR}}" - -# Apply recipes to the base image -customize: - echo "{{BUILD_INFO}}" > "{{justfile_directory()}}/recipes/build-info/files/.build_info" - ./run-bakery --config "{{CUSTOMIZATION_PROFILE}}" customize "{{BASE_TAR}}" "{{CUSTOM_TAR}}" - # Create the image that can be flashed to an SD card or applied using the rugpi interface -bake: - ./run-bakery --config "{{IMAGE_CONFIG}}" bake "{{CUSTOM_TAR}}" "{{OUTPUT_IMAGE}}" - @echo "" +build: + mkdir -p "{{parent_directory(OUTPUT_IMAGE)}}" + echo "{{IMAGE_NAME}}" > {{justfile_directory()}}/.image + ./run-bakery bake image {{IMAGE}} {{OUTPUT_IMAGE}} + just VERSION={{VERSION}} IMAGE={{IMAGE}} compress + +# Compress +compress: @echo "Compressing image" scripts/compress.sh "{{OUTPUT_IMAGE}}" @echo "" @@ -78,11 +57,6 @@ bake: @echo " {{justfile_directory()}}/{{OUTPUT_IMAGE}}.xz" @echo "" -# Build the entire image -build-all: setup extract customize bake - -# Build the image from an already downloaded image -build-local: customize bake # Publish latest image to Cumulocity publish: @@ -92,11 +66,6 @@ publish: publish-external tag *args="": cd {{justfile_directory()}} && ./scripts/c8y-publish-release.sh {{tag}} {{args}} -build-all-variants: extract customize - just VARIANT=pi023 bake - # just VARIANT=pi4 bake - just VARIANT=pi45 bake - # Trigger a release (by creating a tag) release: git tag -a "{{VERSION}}" -m "{{VERSION}}" @@ -104,3 +73,73 @@ release: @echo @echo "Created release (tag): {{VERSION}}" @echo + +# +# Help users to select the correct image for them +# +build-pi1: + just IMAGE=u-boot-armhf build compress + @echo + @echo "This image can be applied to" + @echo " * pi1" + @echo " * pi2 (early models)" + @echo " * pizero" + @echo + +build-pizero: + just IMAGE=u-boot-armhf build compress + @echo + @echo "This image can be applied to" + @echo " * pi1" + @echo " * pi2 (early models)" + @echo " * pizero" + @echo + +build-pi2: + just IMAGE=u-boot build compress + @echo + @echo "This image can be applied to" + @echo " * pi2" + @echo " * pi3" + @echo " * pizero2" + @echo + +build-pi3: + just IMAGE=u-boot build compress + @echo + @echo "This image can be applied to" + @echo " * pi2" + @echo " * pi3" + @echo " * pizero2" + @echo + +build-pizero2w: + just IMAGE=u-boot build compress + @echo + @echo "This image can be applied to" + @echo " * pi2" + @echo " * pi3" + @echo + +build-pi4: + just IMAGE=tryboot build compress + @echo + @echo "This image can be applied to" + @echo " * pi4" + @echo " * pi5" + @echo + +build-pi4-include-firmware: + just IMAGE=pi4 build compress + @echo + @echo "This image can be applied to" + @echo " * pi4" + @echo + +build-pi5: + just IMAGE=tryboot build compress + @echo + @echo "This image can be applied to" + @echo " * pi4" + @echo " * pi5" + @echo diff --git a/layers/containers.toml b/layers/containers.toml new file mode 100644 index 0000000..72f731b --- /dev/null +++ b/layers/containers.toml @@ -0,0 +1,7 @@ +name = "containers" +parent = "tedge-rugpi-core/tedge" + +recipes = [ + "tedge-rugpi-core/defaults", + "tedge-rugpi-core/docker", +] diff --git a/layers/default.toml b/layers/default.toml new file mode 100644 index 0000000..ba0b1f0 --- /dev/null +++ b/layers/default.toml @@ -0,0 +1,6 @@ +name = "default" +parent = "tedge-rugpi-core/tedge" + +recipes = [ + "tedge-rugpi-core/defaults", +] diff --git a/profiles/armhf.toml b/profiles/armhf.toml deleted file mode 100644 index cb6511f..0000000 --- a/profiles/armhf.toml +++ /dev/null @@ -1,26 +0,0 @@ -recipes = [ - "persist-root-home", - "ssh", - "zsh", - "persist-overlay", - "tedge-firmware-update", - "set-wifi", -] -exclude = ["mosquitto"] -architecture = "armhf" - -[parameters.apt-cleanup] -autoremove = true - -[parameters.ssh] -root_authorized_keys = """ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfhQGWWw73ponAokdNSRZ5cQc9/CIX1TLQgYlr+BtObKoO4UNFP1YSbgK03GjhjeUid+QPmV+UURqxQTqLQoYWqUFP2CYkILFccVPmTvx9HLwupI+6QQKWfMDx9Djfph9GzInymaA5fT7hKppqittFrC/l3lkKgKTX5ohEOGshIbRgtgOYIaW3ByTx3urnaBbYCIgOyOZzSIyS0dUkwsiLu3XjPspgmn3Fs/+vofT/yhBe1carW0UM3ivV0JFfJzrxbCl/F7I2qwfjZXsypjkwlpNupUMuo3xPMi8YvNvyEu4d+IEAqO1dCcdGcxlkiHxrdITIpVLt5mjJ2LauHE/H bootstrap -""" - -[parameters.set-wifi] -# These values should be modified if you want to enable default wifi credentials in the image -ssid = "onboarding_jail" -password = "onboarding_jail" - -[parameters.rugpi-ctrl] -rugpi_admin = true # Enable Rugpi Admin. diff --git a/profiles/default.toml b/profiles/default.toml deleted file mode 100644 index 2782949..0000000 --- a/profiles/default.toml +++ /dev/null @@ -1,18 +0,0 @@ -recipes = [ - "persist-root-home", - "ssh", - "zsh", - "persist-overlay", - "tedge-firmware-update", -] - -[parameters.apt-cleanup] -autoremove = true - -[parameters.ssh] -root_authorized_keys = """ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfhQGWWw73ponAokdNSRZ5cQc9/CIX1TLQgYlr+BtObKoO4UNFP1YSbgK03GjhjeUid+QPmV+UURqxQTqLQoYWqUFP2CYkILFccVPmTvx9HLwupI+6QQKWfMDx9Djfph9GzInymaA5fT7hKppqittFrC/l3lkKgKTX5ohEOGshIbRgtgOYIaW3ByTx3urnaBbYCIgOyOZzSIyS0dUkwsiLu3XjPspgmn3Fs/+vofT/yhBe1carW0UM3ivV0JFfJzrxbCl/F7I2qwfjZXsypjkwlpNupUMuo3xPMi8YvNvyEu4d+IEAqO1dCcdGcxlkiHxrdITIpVLt5mjJ2LauHE/H bootstrap -""" - -[parameters.rugpi-ctrl] -rugpi_admin = true # Enable Rugpi Admin. diff --git a/profiles/wifi.toml b/profiles/wifi.toml deleted file mode 100644 index c8c7eff..0000000 --- a/profiles/wifi.toml +++ /dev/null @@ -1,26 +0,0 @@ -recipes = [ - "persist-root-home", - "ssh", - "zsh", - - # wifi credentials are required as Raspberry Pi Zero's don't have an ethernet adapter - "set-wifi", - "persist-overlay", - "tedge-firmware-update", -] - -[parameters.apt-cleanup] -autoremove = true - -[parameters.ssh] -root_authorized_keys = """ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfhQGWWw73ponAokdNSRZ5cQc9/CIX1TLQgYlr+BtObKoO4UNFP1YSbgK03GjhjeUid+QPmV+UURqxQTqLQoYWqUFP2CYkILFccVPmTvx9HLwupI+6QQKWfMDx9Djfph9GzInymaA5fT7hKppqittFrC/l3lkKgKTX5ohEOGshIbRgtgOYIaW3ByTx3urnaBbYCIgOyOZzSIyS0dUkwsiLu3XjPspgmn3Fs/+vofT/yhBe1carW0UM3ivV0JFfJzrxbCl/F7I2qwfjZXsypjkwlpNupUMuo3xPMi8YvNvyEu4d+IEAqO1dCcdGcxlkiHxrdITIpVLt5mjJ2LauHE/H bootstrap -""" - -[parameters.set-wifi] -# These values should be modified if you want to enable default wifi credentials in the image -ssid = "onboarding_jail" -password = "onboarding_jail" - -[parameters.rugpi-ctrl] -rugpi_admin = true # Enable Rugpi Admin. diff --git a/recipes/build-info/files/.gitignore b/recipes/build-info/files/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/recipes/build-info/recipe.toml b/recipes/build-info/recipe.toml deleted file mode 100644 index 42fa956..0000000 --- a/recipes/build-info/recipe.toml +++ /dev/null @@ -1,2 +0,0 @@ -description = "Add build-info about the image" -priority = -1 # Execute at the end \ No newline at end of file diff --git a/recipes/build-info/steps/00-install.sh b/recipes/build-info/steps/00-install.sh deleted file mode 100755 index 8ff942c..0000000 --- a/recipes/build-info/steps/00-install.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -set -e - -BUILD_INFO_HOST="$RECIPE_DIR/files/.build_info" -BUILD_INFO_TARGET=/etc/.build_info - -if [ -f "$BUILD_INFO_HOST" ]; then - echo "Adding build-info: $BUILD_INFO_TARGET" - cat "$BUILD_INFO_HOST" > "$BUILD_INFO_TARGET" -fi diff --git a/recipes/health-check/files/health.d/00-time-sync b/recipes/health-check/files/health.d/00-time-sync deleted file mode 100755 index ed72c22..0000000 --- a/recipes/health-check/files/health.d/00-time-sync +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -# -# Wait for network to be ready but don't block if still not available as the mender commit -# might be used to restore network connectivity. -# - -set -e - -OK=0 - -log() { - echo "$*" >&2 -} - -attempt=0 -max_attempts=10 - -# Network ready: 0 = no, 1 = yes -ready=0 -log "Waiting for network to be ready, and time to be synced" - -while [ "$attempt" -lt "$max_attempts" ]; do - TIME_IN_SYNC=$(timedatectl | awk '/System clock synchronized/{print $NF}') - case "${TIME_IN_SYNC}" in - yes) - ready=1 - break - ;; - esac - attempt=$((attempt + 1)) - log "Network not ready yet (attempt: $attempt from $max_attempts)" - sleep 30 -done - -# Duration can only be based on uptime since the device's clock might not be synced yet, so 'date' will not be monotonic -duration=$(awk '{print $1}' /proc/uptime) - -log "Network: ready=$ready (after ${duration}s)" -if [ "$ready" = "1" ]; then - log "Network is ready after ${duration}s (from startup)" -else - # Don't fail, as the downstream checks might still work - log "WARNING: System time is still not in sync but continuing anyway" -fi - -exit ${OK} diff --git a/recipes/health-check/files/health.d/10-tedge-health b/recipes/health-check/files/health.d/10-tedge-health deleted file mode 100755 index 3f89bb4..0000000 --- a/recipes/health-check/files/health.d/10-tedge-health +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -set -e -MAPPERS="c8y az aws" - -is_mapper_connected() { - CLOUD_MAPPER="$1" - - if [ -n "$(tedge config get "$CLOUD_MAPPER.url" 2>/dev/null)" ]; then - tedge connect "$CLOUD_MAPPER" --test - else - # If the configuration is not configured, then treat the device as healthy - echo "Mapper is not configured: $CLOUD_MAPPER" >&2 - return 0 - fi -} - -for name in $MAPPERS; do - is_mapper_connected "$name" -done diff --git a/recipes/health-check/files/healthcheck.sh b/recipes/health-check/files/healthcheck.sh deleted file mode 100755 index 7da1013..0000000 --- a/recipes/health-check/files/healthcheck.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh -set -eu -HEALTH_CHECK_DIR=/etc/health.d -_NEWLINE=$(printf '\n') - -log() { - message="$(date -Iseconds || date --iso-8601=seconds) $*" - echo "$message" -} - -is_healthy() { - # 0 = healthy, 1 = not healthy (to align with linux exit code convention) - not_ok=0 - if command -V run-parts >/dev/null 2>&1; then - log "Using run-parts to execute scripts in $HEALTH_CHECK_DIR" - if ! run-parts --exit-on-error --new-session --lsbsysinit --verbose "$HEALTH_CHECK_DIR"; then - not_ok=1 - fi - else - log "Using for loop to execute scripts in $HEALTH_CHECK_DIR" - for file in "$HEALTH_CHECK_DIR"/*; do - if [ -x "$file" ]; then - if ! "$file"; then - not_ok=1 - break - fi - fi - done - fi - - return "$not_ok" -} - -main() { - counter=0 - NOT_OK=1 - RETRY_DELAY=30 - - while [ "$counter" -lt 10 ]; do - if is_healthy; then - NOT_OK=0 - break - fi - - if command -V bc >/dev/null 2>&1; then - counter=$(echo "$counter+1"|bc) - else - counter=$((counter + 1)) - fi - log "Waiting $RETRY_DELAY seconds before checking the health again" - sleep "$RETRY_DELAY" - done - - exit "$NOT_OK" -} - -main diff --git a/recipes/health-check/recipe.toml b/recipes/health-check/recipe.toml deleted file mode 100644 index 5bf06a6..0000000 --- a/recipes/health-check/recipe.toml +++ /dev/null @@ -1,2 +0,0 @@ -description = "Health check runner" -priority = 80_000 diff --git a/recipes/health-check/steps/00-install.sh b/recipes/health-check/steps/00-install.sh deleted file mode 100755 index a749117..0000000 --- a/recipes/health-check/steps/00-install.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -set -eu - -mkdir -p /etc/health.d -chmod 755 /etc/health.d - -install -D -m 755 "${RECIPE_DIR}/files/health.d/"* -t /etc/health.d/ -install -D -m 755 "${RECIPE_DIR}/files/healthcheck.sh" -t /usr/bin/ diff --git a/recipes/mosquitto/recipe.toml b/recipes/mosquitto/recipe.toml deleted file mode 100644 index 2bedd1a..0000000 --- a/recipes/mosquitto/recipe.toml +++ /dev/null @@ -1,2 +0,0 @@ -description = "install latest mosquitto version" -priority = 200_000 # Execut before thin-edge.io \ No newline at end of file diff --git a/recipes/mosquitto/steps/00-install.sh b/recipes/mosquitto/steps/00-install.sh deleted file mode 100755 index b9eb1f8..0000000 --- a/recipes/mosquitto/steps/00-install.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -e -# Install more recent version of mosquitto >= 2.0.18 from debian sid to avoid mosquitto following bugs: -# The mosquitto repo can't be used as it does not included builds for arm64/aarch64 (only amd64 and armhf) -# * https://github.com/eclipse/mosquitto/issues/2604 (2.0.11) -# * https://github.com/eclipse/mosquitto/issues/2634 (2.0.15) -echo 'deb [signed-by=/usr/share/keyrings/debian-archive-keyring.gpg] http://deb.debian.org/debian bookworm-backports main' > /etc/apt/sources.list.d/debian-bookworm-backports.list -apt-get update - -DEBIAN_FRONTEND=noninteractive apt-get -o DPkg::Options::=--force-confold -y --no-install-recommends install -t bookworm-backports \ - mosquitto \ - mosquitto-clients diff --git a/recipes/persist-data/files/data.toml b/recipes/persist-data/files/data.toml deleted file mode 100644 index 1f25dc4..0000000 --- a/recipes/persist-data/files/data.toml +++ /dev/null @@ -1,2 +0,0 @@ -[[persist]] -directory = "/data" diff --git a/recipes/persist-data/recipe.toml b/recipes/persist-data/recipe.toml deleted file mode 100644 index 56cebf3..0000000 --- a/recipes/persist-data/recipe.toml +++ /dev/null @@ -1,2 +0,0 @@ -description = "install state file for `/data`" -priority = 600_000 # Execute rather early. diff --git a/recipes/persist-data/steps/00-install.sh b/recipes/persist-data/steps/00-install.sh deleted file mode 100755 index c6e79ba..0000000 --- a/recipes/persist-data/steps/00-install.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -set -eu -install -D -m 644 "${RECIPE_DIR}/files/data.toml" -t /etc/rugpi/state - -# Create directory where backup files can be stored -mkdir -p /data -chmod 1777 /data diff --git a/recipes/persist-network-manager/files/network-manager-config.toml b/recipes/persist-network-manager/files/network-manager-config.toml deleted file mode 100644 index b3bfa41..0000000 --- a/recipes/persist-network-manager/files/network-manager-config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[[persist]] -directory = "/etc/NetworkManager/system-connections" \ No newline at end of file diff --git a/recipes/persist-network-manager/recipe.toml b/recipes/persist-network-manager/recipe.toml deleted file mode 100644 index c404c02..0000000 --- a/recipes/persist-network-manager/recipe.toml +++ /dev/null @@ -1,2 +0,0 @@ -description = "install state file for `/etc/NetworkManager/system-connections`" -priority = 600_000 # Execute rather early. diff --git a/recipes/persist-network-manager/steps/00-install.sh b/recipes/persist-network-manager/steps/00-install.sh deleted file mode 100755 index 34adc25..0000000 --- a/recipes/persist-network-manager/steps/00-install.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -set -eu -install -D -m 644 "${RECIPE_DIR}/files/network-manager-config.toml" -t /etc/rugpi/state diff --git a/recipes/persist-overlay/files/ctrl.toml b/recipes/persist-overlay/files/ctrl.toml deleted file mode 100644 index ce2e88b..0000000 --- a/recipes/persist-overlay/files/ctrl.toml +++ /dev/null @@ -1 +0,0 @@ -overlay = "persist" \ No newline at end of file diff --git a/recipes/persist-overlay/recipe.toml b/recipes/persist-overlay/recipe.toml deleted file mode 100644 index 666e5e9..0000000 --- a/recipes/persist-overlay/recipe.toml +++ /dev/null @@ -1,2 +0,0 @@ -description = "Persist general overaly across reboots" -default = false \ No newline at end of file diff --git a/recipes/persist-overlay/steps/00-install.sh b/recipes/persist-overlay/steps/00-install.sh deleted file mode 100755 index f9169ed..0000000 --- a/recipes/persist-overlay/steps/00-install.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -set -eu -install -D -m 644 "${RECIPE_DIR}/files/ctrl.toml" -t /etc/rugpi/ diff --git a/recipes/sbom/recipe.toml b/recipes/sbom/recipe.toml deleted file mode 100644 index 54d6f51..0000000 --- a/recipes/sbom/recipe.toml +++ /dev/null @@ -1,2 +0,0 @@ -description = "Create software bill of materials" -priority = -1000 # Execute at the end \ No newline at end of file diff --git a/recipes/sbom/steps/00-install.sh b/recipes/sbom/steps/00-install.sh deleted file mode 100755 index 3771d79..0000000 --- a/recipes/sbom/steps/00-install.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e -echo "Creating Software Bill Of Materials" -if [ -n "$RECIPE_DIR" ]; then - dpkg --list > "$RECIPE_DIR/debian-packages.list" -else - dpkg --list -fi diff --git a/recipes/set-wifi/recipe.toml b/recipes/set-wifi/recipe.toml deleted file mode 100644 index 937883e..0000000 --- a/recipes/set-wifi/recipe.toml +++ /dev/null @@ -1,7 +0,0 @@ -description = "Set wifi access" -default = false - -[parameters] -id = { default = "wifi" } -ssid = {} -password = {} diff --git a/recipes/set-wifi/steps/00-install.sh b/recipes/set-wifi/steps/00-install.sh deleted file mode 100755 index cbf7141..0000000 --- a/recipes/set-wifi/steps/00-install.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -set -e -echo "Setting wifi access" - -cat << EOT > /etc/NetworkManager/system-connections/wifi.nmconnection -[connection] -id=${RECIPE_PARAM_ID} -uuid=354ca6a0-bc96-4a29-82f4-c7cbc6e43fac -type=wifi - -[wifi] -mode=infrastructure -ssid=${RECIPE_PARAM_SSID} - -[wifi-security] -key-mgmt=wpa-psk -psk=${RECIPE_PARAM_PASSWORD} - -[ipv4] -method=auto - -[ipv6] -addr-gen-mode=default -method=auto - -[proxy] -EOT - -chmod 600 /etc/NetworkManager/system-connections/wifi.nmconnection diff --git a/recipes/tedge-bootstrap/files/hostname.toml b/recipes/tedge-bootstrap/files/hostname.toml deleted file mode 100644 index 786f0be..0000000 --- a/recipes/tedge-bootstrap/files/hostname.toml +++ /dev/null @@ -1,2 +0,0 @@ -[[persist]] -file = "/etc/hostname" \ No newline at end of file diff --git a/recipes/tedge-bootstrap/files/tedge-bootstrap b/recipes/tedge-bootstrap/files/tedge-bootstrap deleted file mode 100755 index 7c632f9..0000000 --- a/recipes/tedge-bootstrap/files/tedge-bootstrap +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -set -e - -C8Y_URL= -RAN_MARKER=/etc/tedge/.bootstrapped - -log() { - echo "$@" >&2 -} - -create_cert() { - name="$1" - if tedge cert show >/dev/null 2>&1; then - echo "tedge device certificate has already been created" >&2 - - echo "If your device is still not connected, try uploading the cert using:" >&2 - echo "" >&2 - echo " tedge cert upload c8y --user " >&2 - echo "" >&2 - return - fi - tedge cert create --device-id "$name" -} - -configure_c8y() { - if [ -n "$1" ]; then - C8Y_URL="$1" - else - printf "Enter your Cumulocity IoT url:\n" - read -r C8Y_URL - - if [ -z "$C8Y_URL" ]; then - return - fi - - # trim the http:// or https:// prefix - C8Y_URL=$(echo "$C8Y_URL" | sed 's|^https*://||g') - tedge config set c8y.url "$C8Y_URL" - fi - - printf "Do you want to upload the Certificate to Cumulocity IoT? [Y/n]: " - read -r UPLOAD_CERT - case "${UPLOAD_CERT:-Y}" in - Y|y|yes) - ;; - N|n|no) - return - ;; - esac - - printf "Enter your Cumulocity IoT username (must have Tenant Manager Role):\n" - read -r C8Y_USER - - if [ -n "$C8Y_USER" ]; then - tedge cert upload c8y --user "$C8Y_USER" - else - echo "" >&2 - fi - - tedge connect c8y -} - -set_hostname() { - host_name="$1" - if [ "$(cat /etc/hostname)" = "$host_name" ]; then - echo "Host name is already set" - return - fi - echo "$host_name" | tee /etc/hostname - - if ! hostnamectl set-hostname "$host_name"; then - log "hostnamectl failed, falling back to writing to /etc/hostname" - echo "$host_name" > /etc/hostname - fi - systemctl restart avahi-daemon --no-block 2>/dev/null ||: -} - -set_etc_hosts() { - # enable local network calls to reference current host name - host_name="$1" - cp /etc/hosts /tmp/hosts.new - sed -i -E 's/^127.0.1.1.*/127.0.1.1\t'"$host_name"'/' /tmp/hosts.new - log "Replacing /etc/hosts with updated file" - cp -f /tmp/hosts.new /etc/hosts - log "Successfully updated /etc/hosts" -} - -if [ $# -gt 0 ]; then - C8Y_URL="$1" -fi - -# set hostname -DEVICE_ID= -attempt=0 -while [ "$attempt" -lt 30 ]; do - DEVICE_ID="$(tedge-identity ||:)" - if [ -n "$DEVICE_ID" ]; then - log "Found valid DEVICE_ID" - break - fi - attempt=$((attempt + 1)) - log "Waiting for tedge-identity" - sleep 5 -done - -create_cert "$DEVICE_ID" -set_hostname "$DEVICE_ID" - -if [ -n "$C8Y_URL" ]; then - configure_c8y "$C8Y_URL" -fi - -# set device type -# FIXME: Work out a better way to get the device type, maybe extend tedge-identity to include device info, it could also -# be referenced from 80_firmware -if [ -f /usr/share/tedge-inventory/scripts.d/80_firmware ]; then - DEVICE_TYPE=$(/usr/share/tedge-inventory/scripts.d/80_firmware | grep "name=" | cut -d= -f2 | tr -d '"' | xargs) - if [ -n "$DEVICE_TYPE" ]; then - log "Setting device.type to $DEVICE_TYPE" - tedge config set device.type "$DEVICE_TYPE" - else - log "Using default device.type: $(tedge config get device.type)" - fi -fi - -set_etc_hosts "$DEVICE_ID" - -touch "$RAN_MARKER" diff --git a/recipes/tedge-bootstrap/files/tedge-bootstrap.service b/recipes/tedge-bootstrap/files/tedge-bootstrap.service deleted file mode 100644 index ecffcb0..0000000 --- a/recipes/tedge-bootstrap/files/tedge-bootstrap.service +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=Set hostname on startup -Wants=network-pre.target -Before=network-pre.target -After=local-fs.target -ConditionPathExists=!/etc/tedge/.bootstrapped - -[Service] -Type=oneshot -ExecStart=/usr/bin/tedge-bootstrap - -[Install] -WantedBy=multi-user.target diff --git a/recipes/tedge-bootstrap/files/tedge-identity b/recipes/tedge-bootstrap/files/tedge-identity deleted file mode 100755 index b0b0a42..0000000 --- a/recipes/tedge-bootstrap/files/tedge-identity +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/sh -set -eu - -IDENTITY_PREFIX= - -get_mac_address() { - SCN=/sys/class/net - min=65535 - arphrd_ether=1 - ifdev= - - # find iface with lowest ifindex, skip non ARPHRD_ETHER types (lo, sit ...) - for dev in "$SCN"/*; do - if [ ! -f "$dev/type" ]; then - continue - fi - - iftype=$(cat "$dev/type") - if [ "$iftype" -ne $arphrd_ether ]; then - continue - fi - - # Skip dummy interfaces - if echo "$dev" | grep -q "$SCN/dummy" 2>/dev/null; then - continue - fi - - idx=$(cat "$dev/ifindex") - if [ "$idx" -lt "$min" ]; then - min=$idx - ifdev=$dev - fi - done - - if [ -z "$ifdev" ]; then - echo "no suitable interfaces found" >&2 - exit 1 - else - echo "using interface $ifdev" >&2 - # grab MAC address - cat "$ifdev/address" - fi -} - -get_model_type() { - MODEL=$(grep Model /proc/cpuinfo | cut -d: -f2 | xargs) - SERIAL_NO=$(grep Serial /proc/cpuinfo | cut -d: -f2 | xargs) - - echo "Detected model: $MODEL" >&2 - echo "Detected serial no.: $SERIAL_NO" >&2 - - MODEL_PREFIX= - - case "$MODEL" in - Raspberry\ Pi\ 5*) - MODEL_PREFIX=rpi5 - ;; - Raspberry\ Pi\ 4*) - MODEL_PREFIX=rpi4 - ;; - Raspberry\ Pi\ 3*) - MODEL_PREFIX=rpi3 - ;; - Raspberry\ Pi\ 2*) - MODEL_PREFIX=rpi2 - ;; - Raspberry\ Pi\ Model*) - MODEL_PREFIX=rpi1 - ;; - Raspberry\ Pi\ Zero\ 2\ W\ Rev*) - MODEL_PREFIX=rpizero2 - ;; - Raspberry\ Pi\ Zero\ W\ Rev*) - MODEL_PREFIX=rpizero - ;; - Raspberry\ Pi\ Compute\ Module\ 3*) - MODEL_PREFIX=rpicm3 - ;; - Raspberry\ Pi\ Compute\ Module\ 4*) - MODEL_PREFIX=rpicm4 - ;; - *) - MODEL_PREFIX=unknown - ;; - esac - echo "$MODEL_PREFIX" -} - -MAC_ADDR=$(get_mac_address) -MODEL=$(get_model_type) - -IDENTITY= - -if [ -n "$IDENTITY_PREFIX" ]; then - echo "Using identity prefix: $IDENTITY_PREFIX" >&2 - IDENTITY=$(echo "${IDENTITY_PREFIX}-${MODEL}-${MAC_ADDR}" | tr -d ":") -else - IDENTITY=$(echo "${MODEL}-${MAC_ADDR}" | tr -d ":") -fi - -echo "$IDENTITY" diff --git a/recipes/tedge-bootstrap/recipe.toml b/recipes/tedge-bootstrap/recipe.toml deleted file mode 100644 index 47882cd..0000000 --- a/recipes/tedge-bootstrap/recipe.toml +++ /dev/null @@ -1 +0,0 @@ -description = "Provide tedge bootstrap scripts to easy onboarding" diff --git a/recipes/tedge-bootstrap/steps/00-install.sh b/recipes/tedge-bootstrap/steps/00-install.sh deleted file mode 100755 index 75185c7..0000000 --- a/recipes/tedge-bootstrap/steps/00-install.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -set -eu -install -D -m 644 "${RECIPE_DIR}/files/hostname.toml" -t /etc/rugpi/state/ -install -D -m 755 "${RECIPE_DIR}/files/tedge-identity" -t /usr/bin/ -install -D -m 755 "${RECIPE_DIR}/files/tedge-bootstrap" -t /usr/bin/ - -install -D -m 644 "${RECIPE_DIR}/files/tedge-bootstrap.service" -t /usr/lib/systemd/system/ -systemctl enable tedge-bootstrap.service diff --git a/recipes/tedge-firmware-update/files/firmware-auto-rollback b/recipes/tedge-firmware-update/files/firmware-auto-rollback deleted file mode 100755 index 73dde24..0000000 --- a/recipes/tedge-firmware-update/files/firmware-auto-rollback +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -set -e - -RUGPI_INFO=$(rugpi-ctrl system info ||:) -HOT=$(echo "$RUGPI_INFO" | grep Hot | cut -d: -f2 | xargs) -DEFAULT=$(echo "$RUGPI_INFO" | grep Default | cut -d: -f2 | xargs) - -if [ "$HOT" = "$DEFAULT" ]; then - echo "Already on default partition. Nothing to rollback to. hot=$HOT, default=$DEFAULT" >&2 - exit 0 -fi - -echo "Rebooting into default partition. hot=$HOT, default=$DEFAULT" -reboot -exit 0 diff --git a/recipes/tedge-firmware-update/files/firmware-auto-rollback.service b/recipes/tedge-firmware-update/files/firmware-auto-rollback.service deleted file mode 100644 index 45ed743..0000000 --- a/recipes/tedge-firmware-update/files/firmware-auto-rollback.service +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Rollback to default partition if this service has not been disabled yet - -[Service] -Type=oneshot -ExecStart=/usr/bin/firmware-auto-rollback - -[Install] -WantedBy=multi-user.target diff --git a/recipes/tedge-firmware-update/files/firmware-auto-rollback.timer b/recipes/tedge-firmware-update/files/firmware-auto-rollback.timer deleted file mode 100644 index 88926eb..0000000 --- a/recipes/tedge-firmware-update/files/firmware-auto-rollback.timer +++ /dev/null @@ -1,8 +0,0 @@ -[Unit] -Description=rugpi auto rollback - -[Timer] -OnBootSec=1800s - -[Install] -WantedBy=timers.target \ No newline at end of file diff --git a/recipes/tedge-firmware-update/files/firmware-version b/recipes/tedge-firmware-update/files/firmware-version deleted file mode 100755 index 070ae93..0000000 --- a/recipes/tedge-firmware-update/files/firmware-version +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -################################################## -# Parse firmware file marker -# -# Example file contents: -# ``` -# tedge_rugpi_default_pi45_20231203.1557 -# ``` -################################################## -set -e -ARTIFACT_FILE=/etc/.build_info - -if [ ! -f "$ARTIFACT_FILE" ]; then - exit 0 -fi - -NAME=$(rev /etc/.build_info | cut -d_ -f2- | rev) -VERSION=$(rev /etc/.build_info | cut -d_ -f1 | rev) - -echo "name=\"$NAME\"" -echo "version=\"$VERSION\"" - -# FIXME: Workaround since thin-edge.io does deduplication detection. -# However this is only needed because the firmware/name is cleared on tedge-agent startup. -# Remove once https://github.com/thin-edge/thin-edge.io/issues/2497 is resolved -echo "updated=\"$(date)\"" diff --git a/recipes/tedge-firmware-update/files/firmware_update.rugpi.toml b/recipes/tedge-firmware-update/files/firmware_update.rugpi.toml deleted file mode 100644 index ebecfdb..0000000 --- a/recipes/tedge-firmware-update/files/firmware_update.rugpi.toml +++ /dev/null @@ -1,67 +0,0 @@ -#:schema https://gist.githubusercontent.com/reubenmiller/4e28e8403fe0c54b7461ac7d1d6838c2/raw/b8599ccf81120bb22bdaa164655e2cc0b8fcb902/tedge.workflow.json -operation = "firmware_update" -on_error = "failed" - -[init] -action = "proceed" -on_success = "scheduled" - -[scheduled] -action = "proceed" -on_success = "executing" - -[executing] -script = "/usr/bin/rugpi_workflow.sh ${.payload.status}" -on_success = "download" -on_error = { status = "failed", reason = "Refusing to start update as the wrong partition is active" } - -[download] -script = "/usr/bin/rugpi_workflow.sh ${.payload.status} --url ${.payload.remoteUrl}" -on_success = "install" -on_error = { status = "failed", reason = "Failed to download image"} - -[install] -script = "/usr/bin/rugpi_workflow.sh ${.payload.status} --url ${.payload.url}" -on_success = "restart" -on_error = { status = "failed", reason = "Failed to install image"} - -[restart] -action = "restart" -on_exec = "restarting" # Internal state used by the "restart" action -on_success = "restarted" -on_error = { status = "failed_restart", reason = "Failed to restart device" } - -[restarted] -script = "/usr/bin/rugpi_workflow.sh ${.payload.status}" -on_success = "verify" -on_error = { status = "rollback_restart", reason = "Unexpected error during restarted check. Rolling back"} - -[failed_restart] -script = "/usr/bin/rugpi_workflow.sh failed_restart" -on_success = { status = "failed", reason = "Device failed to restart" } - -[verify] -script = "/usr/bin/rugpi_workflow.sh ${.payload.status} --firmware-name ${.payload.name} --firmware-version ${.payload.version} --url ${.payload.remoteUrl}" -on_exit.0 = { status = "commit" } -on_exit.4 = { status = "rollback_restart", reason = "Verification failed. Rolling back to default partition" } -on_exit._ = { status = "failed", reason = "Verification failed, no rollback necessary" } - -[commit] -script = "/usr/bin/rugpi_workflow.sh ${.payload.status} --firmware-name ${.payload.name} --firmware-version ${.payload.version} --url ${.payload.remoteUrl}" -on_success = "successful" -on_error = { status = "rollback_restart", reason = "Commit failed. Rolling back to default partition" } - -[rollback_restart] -action = "restart" -on_exec = "restarting" # Internal state used by the "restart" action -on_success = "rollback_successful" - -[rollback_successful] -script = "/usr/bin/rugpi_workflow.sh ${.payload.status}" -on_success = { status = "failed", reason = "Firmware update failed, but the rollback to the default partition was successful" } - -[successful] -action = "cleanup" - -[failed] -action = "cleanup" diff --git a/recipes/tedge-firmware-update/files/rugpi_workflow.sh b/recipes/tedge-firmware-update/files/rugpi_workflow.sh deleted file mode 100755 index 60d923b..0000000 --- a/recipes/tedge-firmware-update/files/rugpi_workflow.sh +++ /dev/null @@ -1,313 +0,0 @@ -#!/bin/sh -set -e -FIRMWARE_NAME= -FIRMWARE_VERSION= -FIRMWARE_URL= -FIRMWARE_META_FILE=/etc/tedge/.firmware -MANUAL_DOWNLOAD=0 - -# Exit codes -OK=0 -FAILED=1 -REQUEST_RESTART=4 - -# Use temp directory so that the file can't accidentally persist across partitions -# thus always booting into the spare partition -REBOOT_SPARE_REQUEST=/tmp/.reboot_spare - -# Detect if sudo should be used or not. It will be used if it is found -SUDO="" -if command -V sudo >/dev/null 2>&1; then - SUDO="sudo" -fi - -_WORKDIR=$(pwd) - -# Change to a directory which is readable otherwise rugpi-ctrl can have problems reading the mounts -cd /tmp || cd / - -HOT=$(rugpi-ctrl system info | grep Hot | cut -d: -f2 | tr '[:lower:]' '[:upper:]' | xargs) -DEFAULT=$(rugpi-ctrl system info | grep Default | cut -d: -f2 | tr '[:lower:]' '[:upper:]' | xargs) -SPARE=$(rugpi-ctrl system info | grep Spare | cut -d: -f2 | tr '[:lower:]' '[:upper:]' | xargs) - -ACTION="$1" -shift - -log() { - msg="$(date +%Y-%m-%dT%H:%M:%S) [current=$ACTION] $*" - echo "$msg" >&2 - - # publish to pub for better resolution - tedge mqtt pub -q 2 te/device/main///e/firmware_update "{\"text\":\"Firmware Workflow: [$ACTION] $*\",\"state\":\"$ACTION\",\"partition\":\"$HOT\"}" - sleep 1 -} - -local_log() { - # Only log locally and don't push to the cloud - msg="$(date +%Y-%m-%dT%H:%M:%S) [current=$ACTION] $*" - echo "$msg" >&2 -} - -update_state() { - echo ":::begin-tedge:::" - echo "$1" - echo ":::end-tedge:::" - sleep 1 -} - -set_reason() { - reason="$1" - message=$(printf '{"reason":"%s"}' "$reason") - update_state "$message" -} - -# -# main -# -while [ $# -gt 0 ]; do - case "$1" in - --firmware-name) - FIRMWARE_NAME="$2" - shift - ;; - --firmware-version) - FIRMWARE_VERSION="$2" - shift - ;; - --url) - FIRMWARE_URL="$2" - shift - ;; - esac - shift -done - -wait_for_network() { - # - # Wait for network to be ready but don't block if still not available as the commit - # might be used to restore network connectivity. - # - attempt=0 - max_attempts=10 - # Network ready: 0 = no, 1 = yes - ready=0 - local_log "Waiting for network to be ready, and time to be synced" - - while [ "$attempt" -lt "$max_attempts" ]; do - # TIME_SYNC_ACTIVE=$(timedatectl | grep NTP | awk '{print $NF}') - TIME_IN_SYNC=$(timedatectl | awk '/System clock synchronized/{print $NF}') - case "${TIME_IN_SYNC}" in - yes) - ready=1 - break - ;; - esac - attempt=$((attempt + 1)) - local_log "Network not ready yet (attempt: $attempt from $max_attempts)" - sleep 30 - done - - # Duration can only be based on uptime since the device's clock might not be synced yet, so 'date' will not be monotonic - duration=$(awk '{print $1}' /proc/uptime) - - local_log "Network: ready=$ready (after ${duration}s)" - if [ "$ready" = "1" ]; then - log "Network is ready after ${duration}s (from startup)" - return 0 - fi - - # Don't send cloud message if it is not ready - return 1 -} - -executing() { - if [ "$HOT" != "$DEFAULT" ]; then - set_reason "Refusing to install update as the current (hot) partition is not the default partition. This indicates that you may be in the middle of an update. Please reboot to switch to the default partition" - exit "$FAILED" - fi - log "Starting firmware update. Current partition is $HOT, so update will be applied to $SPARE" -} - -download() { - url="$1" - - # - # Change url to a local url using the c8y proxy - # - case "$url" in - https://*/inventory/binaries/*) - # Cumulocity URL, use the c8y auth proxy service - partial_path=$(echo "$url" | sed 's|https://[^/]*/||g') - c8y_proxy_host=$(tedge config get c8y.proxy.client.host) - c8y_proxy_port=$(tedge config get c8y.proxy.client.port) - tedge_url="http://${c8y_proxy_host}:${c8y_proxy_port}/c8y/$partial_path" - ;; - http://*|https://*) - # External URL, pass it untouched - # NOTE: If a service required authorization, then this would be the place to add it - # For example some blob stores support signed URLS - partial_path=$(echo "$url" | sed 's|https://[^/]*/||g') - tedge_url="$url" - ;; - *) - # Assume url is actually a file and just go to the next state - update_state "$(printf '{"url":"%s"}\n' "$url")" - return "$OK" - ;; - esac - - if [ "$MANUAL_DOWNLOAD" = 1 ]; then - TEDGE_DATA=$(tedge config get data.path) - - # Removing any older files to ensure space for next file to download - # Note: busy box does not support the -delete flag - find "$TEDGE_DATA" -name "*.firmware" -exec rm {} \; - - last_part=$(echo "$partial_path" | rev | cut -d/ -f1 | rev) - local_file="$TEDGE_DATA/${last_part}.firmware" - log "Manually downloading artifact from $tedge_url and saving to $local_file" - wget -c -O "$local_file" "$tedge_url" >&2 - log "Downloaded file from: $tedge_url" - update_state "$(printf '{"url":"%s"}\n' "$local_file")" - else - log "Replacing url with a tedge url: $tedge_url" - update_state "$(printf '{"url":"%s"}\n' "$tedge_url")" - fi -} - -install() { - url="$1" - set +e - case "$url" in - http://*.img|https://*.img) - log "Downloading and streaming uncompressed image to rugpi" - wget -c -q -t 0 -O - "$url" | $SUDO rugpi-ctrl update install --stream --no-reboot - - ;; - - # Assume a xz compressed file - http://*|https://*) - log "Downloading and streaming xz compressed image to rugpi" - wget -c -q -t 0 -O - "$url" | xz -d | $SUDO rugpi-ctrl update install --stream --no-reboot - - ;; - - # It is a file - *) - # Check file type using mime types - mime_type=$(file "$url" --mime-type | cut -d: -f2 | xargs) - - case "$mime_type" in - application/x-xz) - # Decode the file and stream it into rugpi (decompressing on the fly) - log "Installing local xz compressed image to rugpi" - xz --decompress --stdout -T0 "$url" | $SUDO rugpi-ctrl update install --stream --no-reboot - - ;; - *) - # Uncompressed file - log "Installing local uncompressed image to rugpi" - $SUDO rugpi-ctrl update install --no-reboot "$url" - ;; - esac - ;; - esac - EXIT_CODE=$? - set -e - - case "$EXIT_CODE" in - 0) - log "OK, RESTART required" - ;; - *) - log "ERROR. Unexpected return code. code=$EXIT_CODE" - ;; - esac - - # Create mark file which is used by the restart state to reboot into the spare partition - touch "$REBOOT_SPARE_REQUEST" - exit "$EXIT_CODE" -} - -restart() { - # NOTE: This function should not be called in the script directly but rather via the system.toml - if [ -f "$REBOOT_SPARE_REQUEST" ]; then - rm -f "$REBOOT_SPARE_REQUEST" - - message=$(printf '{"text":"Rebooting into spare partition (%s -> %s)","partition":"%s"}' "$HOT" "$SPARE" "$HOT") - tedge mqtt pub -q 1 "te/device/main///e/reboot_spare" "$message" ||: - sleep 5 - $SUDO rugpi-ctrl system reboot --spare - else - message=$(printf '{"text":"Rebooting into default partition (%s -> %s)","partition":"%s"}' "$HOT" "$DEFAULT" "$HOT") - tedge mqtt pub -q 1 "te/device/main///e/reboot_default" "$message" ||: - sleep 5 - $SUDO rugpi-ctrl system reboot - fi - exit "$OK" -} - -verify() { - log "Checking device health" - - if [ "$HOT" = "$DEFAULT" ]; then - # Don't both to reboot if no partition swap occurred because we are already in the ok partition - set_reason "Partition swap did not occur. Reasons could be, corrupt/non-bootable image, someone did a manual rollback or the machine was restarted manually before the health check was run" - exit "$FAILED" - fi - - # Allow users to also call addition logic by adding their scripts to the /etc/health.d/ directory - if /usr/bin/healthcheck.sh; then - exit "$OK" - else - set_reason "Health check failed on new partition" - exit "$REQUEST_RESTART" - fi -} - -commit() { - log "Executing: rugpi-ctrl system commit" - set +e - $SUDO rugpi-ctrl system commit - EXIT_CODE=$? - set -e - - case "$EXIT_CODE" in - 0) - # Check what the updated default partition is - DEFAULT=$(rugpi-ctrl system info | grep Default | cut -d: -f2 | tr '[:lower:]' '[:upper:]' | xargs) - - log "Commit successful. New default partition is $DEFAULT" - # Save firmware meta information to file (for reading on startup during normal operation) - local_log "Saving firmware info to $FIRMWARE_META_FILE" - printf 'FIRMWARE_NAME=%s\nFIRMWARE_VERSION=%s\nFIRMWARE_URL=%s\n' "$FIRMWARE_NAME" "$FIRMWARE_VERSION" "$FIRMWARE_URL" > "$FIRMWARE_META_FILE" - ;; - *) - log "rugpi-ctrl returned code: $EXIT_CODE. Rolling back to previous partition" - ;; - esac - exit "$EXIT_CODE" -} - -case "$ACTION" in - executing) executing; ;; - download) download "$FIRMWARE_URL"; ;; - install) install "$FIRMWARE_URL"; ;; - verify) verify; ;; - commit) commit; ;; - restart) restart; ;; - restarted) - wait_for_network ||: - log "Device has been restarted...continuing workflow. partition=$HOT, default=$DEFAULT" - ;; - rollback_successful) - log "Firmware update failed, but the rollback was successful. partition=$HOT, default=$DEFAULT" - ;; - failed_restart) ;; - *) - log "Unknown command. This script only accepts: download, install, commit, rollback, rollback_successful, failed_restart" - exit "$FAILED" - ;; -esac - -# switch back to original directory -cd "$_WORKDIR" ||: - -exit "$OK" diff --git a/recipes/tedge-firmware-update/files/system.toml b/recipes/tedge-firmware-update/files/system.toml deleted file mode 100644 index f87cea3..0000000 --- a/recipes/tedge-firmware-update/files/system.toml +++ /dev/null @@ -1,2 +0,0 @@ -[system] -reboot = ["/usr/bin/rugpi_workflow.sh", "restart"] \ No newline at end of file diff --git a/recipes/tedge-firmware-update/files/tedge-firmware b/recipes/tedge-firmware-update/files/tedge-firmware deleted file mode 100644 index 4e4e994..0000000 --- a/recipes/tedge-firmware-update/files/tedge-firmware +++ /dev/null @@ -1 +0,0 @@ -tedge ALL = (ALL) NOPASSWD: /usr/bin/rugpi-ctrl, /usr/bin/rugpi_workflow.sh \ No newline at end of file diff --git a/recipes/tedge-firmware-update/recipe.toml b/recipes/tedge-firmware-update/recipe.toml deleted file mode 100644 index a9fe007..0000000 --- a/recipes/tedge-firmware-update/recipe.toml +++ /dev/null @@ -1,7 +0,0 @@ -description = "Add workflow scripts to support firmware updates" -default = false -priority = 10_000 -dependencies = ["thin-edge.io", "health-check"] - -[parameters] -autorollback = { default = true } diff --git a/recipes/tedge-firmware-update/steps/00-install.sh b/recipes/tedge-firmware-update/steps/00-install.sh deleted file mode 100755 index 322900a..0000000 --- a/recipes/tedge-firmware-update/steps/00-install.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -set -eu -install -D -m 644 "${RECIPE_DIR}/files/tedge-firmware" -t /etc/sudoers.d/ -install -D -m 644 "${RECIPE_DIR}/files/system.toml" -t /etc/tedge/ -install -D -m 644 "${RECIPE_DIR}/files/firmware_update.rugpi.toml" -t /usr/share/tedge-workflows/ -install -D -m 755 "${RECIPE_DIR}/files/rugpi_workflow.sh" -t /usr/bin/ -install -D -m 755 "${RECIPE_DIR}/files/firmware-version" /usr/share/tedge-inventory/scripts.d/80_firmware - -# auto rollback service incase if new agent is corrupt (only rely on tooling which is definitely there) -install -D -m 755 "${RECIPE_DIR}/files/firmware-auto-rollback" /usr/bin/firmware-auto-rollback -install -D -m 644 "${RECIPE_DIR}/files/firmware-auto-rollback.service" -t /usr/lib/systemd/system/ -install -D -m 644 "${RECIPE_DIR}/files/firmware-auto-rollback.timer" -t /usr/lib/systemd/system/ - -if [ "${RECIPE_PARAM_AUTOROLLBACK}" = "true" ]; then - systemctl enable firmware-auto-rollback.timer -fi - -# Use symlink so that the workflow file can be updated within the image -ln -s /usr/share/tedge-workflows/firmware_update.rugpi.toml /etc/tedge/operations/firmware_update.toml diff --git a/recipes/thin-edge.io/files/custom.conf b/recipes/thin-edge.io/files/custom.conf deleted file mode 100644 index a60c684..0000000 --- a/recipes/thin-edge.io/files/custom.conf +++ /dev/null @@ -1 +0,0 @@ -pid_file /run/mosquitto/mosquitto.pid diff --git a/recipes/thin-edge.io/files/tedge-config.toml b/recipes/thin-edge.io/files/tedge-config.toml deleted file mode 100644 index f1d0c65..0000000 --- a/recipes/thin-edge.io/files/tedge-config.toml +++ /dev/null @@ -1,12 +0,0 @@ -[[persist]] -directory = "/etc/tedge" - -[[persist]] -directory = "/var/log/tedge" - -# mosquitto db file must be persisted -[[persist]] -directory = "/var/lib/mosquitto" - -[[persist]] -file = "/etc/hosts" diff --git a/recipes/thin-edge.io/files/tedge-configuration-plugin.toml b/recipes/thin-edge.io/files/tedge-configuration-plugin.toml deleted file mode 100644 index cff4fd3..0000000 --- a/recipes/thin-edge.io/files/tedge-configuration-plugin.toml +++ /dev/null @@ -1,14 +0,0 @@ -[[files]] -path = "/etc/tedge/tedge.toml" -type = "tedge.toml" - -[[files]] -path = "/etc/tedge/mosquitto-conf/tedge-mosquitto.conf" -type = "tedge-mosquitto.conf" - -[[files]] -path = "/etc/tedge/plugins/tedge-log-plugin.toml" -type = "tedge-log-plugin" -user = "tedge" -group = "tedge" -mode = 0o0644 diff --git a/recipes/thin-edge.io/files/tedge-log-plugin.toml b/recipes/thin-edge.io/files/tedge-log-plugin.toml deleted file mode 100644 index 5b07634..0000000 --- a/recipes/thin-edge.io/files/tedge-log-plugin.toml +++ /dev/null @@ -1,11 +0,0 @@ -[[files]] -type = "software-management" -path = "/var/log/tedge/agent/software-*" - -[[files]] -type = "firmware_update" -path = "/var/log/tedge/agent/workflow-firmware_update-*" - -[[files]] -type = "c8y_Command" -path = "/var/log/tedge/agent/c8y_Command-*" diff --git a/recipes/thin-edge.io/files/thin-edge.io.sh b/recipes/thin-edge.io/files/thin-edge.io.sh deleted file mode 100755 index afd6efa..0000000 --- a/recipes/thin-edge.io/files/thin-edge.io.sh +++ /dev/null @@ -1,655 +0,0 @@ -#!/bin/sh -set -e - -TYPE=full -TMPDIR=/tmp/tedge -LOGFILE=/tmp/tedge/install.log -REPO_CHANNEL="${REPO_CHANNEL:-release}" -ARCH="${ARCH:-}" -SETUP_COMMUNITY_REPO="${SETUP_COMMUNITY_REPO:-1}" -COMMUNITY_REPO="community" -INSTALL_PREDEPENDS="${INSTALL_PREDEPENDS:-1}" -PREDEPENDS_PACKAGES= - -# TODO -# * Support installing a specific version - check if this is really required? -# - -# Set shell used by the script (can be overwritten during dry run mode) -sh_c='sh -c' - -usage() { - cat <] [--minimal] [--package-manager ] - -ARGUMENTS: - Install specific version of thin-edge.io - if not provided installs latest minor release - -OPTIONS: - --minimal Install only basic set of components - tedge cli and tedge mappers - --channel string Repository channel to use, e.g. official 'release', or 'main' etc. - Available: release, main - -p, --package-manager string Package manager to use to install thin-edge.io. Defaults to auto detection - Available: apt, apk, dnf, microdnf, zypper, tarball - --skip-community Don't setup the community repo (only applies if using a package manager) - --dry-run Don't install anything, just let me know what it does - --help Show this help - -EOF -} - -log() { - # Some embedded devices do not have tee installed! - echo "$@" - echo "$@" >> "$LOGFILE" -} - -debug() { - echo "$@" >> "$LOGFILE" 2>&1 -} - -print_debug() { - echo - echo "--------------- machine details ---------------------" - echo "date: $(date || true)" - echo "tedge: $VERSION" - echo "Machine: $(uname -a || true)" - echo "Architecture: $(dpkg --print-architecture 2>/dev/null || true)" - if command_exists "lsb_release"; then - DISTRIBUTION=$(lsb_release -a 2>/dev/null | grep "Description" | cut -d: -f2- | xargs) - echo "Distribution: $DISTRIBUTION" - elif [ -f /etc/os-release ]; then - echo "os-release details:" - head -4 /etc/os-release - fi - echo - echo "--------------- error details ------------------------" - - if [ -f "$LOGFILE" ]; then - cat "$LOGFILE" - fi - - echo "------------------------------------------------------" - echo -} - -# Enable print of info if something unexpected happens -trap print_debug EXIT - -fail() { - exit_code="$1" - shift - - log "Failed to install thin-edge.io" - echo - log "Reason: $*" - log "Please create a ticket using the following link and include the console output" - log " https://github.com/thin-edge/thin-edge.io/issues/new?assignees=&labels=bug&template=bug_report.md" - - exit "$exit_code" -} - -command_exists() { - command -v "$@" > /dev/null 2>&1 -} - -is_dry_run() { - if [ -z "$DRY_RUN" ]; then - return 1 - else - return 0 - fi -} - -should_install_predepends() { - [ "$INSTALL_PREDEPENDS" = 1 ] -} - -configure_shell() { - # Check if has sudo rights or if it can be requested - user="$(id -un 2>/dev/null || true)" - sh_c='sh -c' - if [ "$user" != 'root' ]; then - if command_exists sudo; then - sh_c='sudo -E sh -c' - elif command_exists su; then - sh_c='su -c' - else - cat >&2 <<-EOF -Error: this installer needs the ability to run commands as root. -We are unable to find either "sudo" or "su" available to make this happen. -EOF - exit 1 - fi - fi - - if is_dry_run; then - sh_c="echo" - fi -} - -install_via_tarball() { - # - # Install tarballs - # - url_arch="" - ARCH=$(get_arch) - case "$ARCH" in - *86_64*|*amd64*) - url_arch="amd64" - ;; - *aarch64*|*arm64*) - url_arch="arm64" - ;; - *armv7*) - url_arch="armv7" - ;; - *armv6*) - url_arch="armv6" - ;; - *) - fail 1 "Unsupported architecture: $ARCH. Supported architectures are: amd64, arm64, armv7, armv6" - ;; - esac - - # Download tarball - download_file "https://dl.cloudsmith.io/public/thinedge/${PACKAGE_REPO}/raw/names/tedge-${url_arch}/versions/latest/tedge.tar.gz" - DOWNLOADED_TARBALL="$TMPDIR/tedge.tar.gz" - - # Prefer gtar over tar, as gtar is guaranteed to be GNU tar - # where tar could also be bsdtar which has different options - # and some systems only have gtar (e.g. rockylinux 9 minimal) - tar_cmd="tar" - if command_exists gtar; then - tar_cmd="gtar" - fi - - log "Expanding tar: $DOWNLOADED_TARBALL $*" - $sh_c "$tar_cmd xzf '$DOWNLOADED_TARBALL' -C /usr/bin/ $*" - - # Run manual initializations - log "Running post installation tasks" - tarball_postinstall -} - -download_file() { - # - # Download a file either using curl or wget (whatever is available) - # The file is downloaded to the temp directory - # - # Usage - # download_file - # - url="$1" - - echo - printf 'Downloading %s...' "$url" - - if [ ! -d "$TMPDIR" ]; then - mkdir -p "$TMPDIR" - fi - - # Prefer curl over wget as docs instruct the user to download this script using curl - if command_exists curl; then - if ! (cd "$TMPDIR" && $sh_c "curl -1fsSLO '$url'" >> "$LOGFILE" 2>&1 ); then - fail 2 "Could not download package from url: $url" - fi - elif command_exists wget; then - if ! $sh_c "wget --quiet '$url' -P '$TMPDIR'" >> "$LOGFILE" 2>&1; then - fail 2 "Could not download package from url: $url" - fi - else - # This should not happen due to the pre-requisite check - echo "FAILED" - fail 1 "Could not download file because neither wget or curl is installed. Please install 'wget' or 'curl' and try again" - fi - if is_dry_run; then - echo "OK (DRY-RUN)" - else - echo "OK" - fi -} - -is_root() { - user="$(id -un 2>/dev/null || true)" - [ "$user" = "root" ] -} - -run_repo_setup() { - filename="$1" - - REPO_OPTS= - if [ -n "$ARCH" ]; then - # curl -1sLf \ - # 'https://dl.cloudsmith.io/public/thinedge/tedge-main-armv6/setup.deb.sh' \ - # | sudo -E distro=some-distro codename=some-codename arch=some-arch bash - echo "Using custom arch: $ARCH" >&2 - REPO_OPTS="arch=$ARCH" - fi - - # Use generic distribution version and codement to be compatible with different OSs - if is_root; then - env version=any-version codename="" $REPO_OPTS bash "$filename" - elif command_exists sudo; then - sudo -E env version=any-version codename="" $REPO_OPTS bash "$filename" - fi -} - -install_via_apk() { - if should_install_predepends && [ -n "$PREDEPENDS_PACKAGES" ]; then - $sh_c "apk add --no-cache $PREDEPENDS_PACKAGES" - fi - download_file "https://dl.cloudsmith.io/public/thinedge/${PACKAGE_REPO}/setup.alpine.sh" - run_repo_setup "$TMPDIR/setup.alpine.sh" - - # setup community repo - if [ "$SETUP_COMMUNITY_REPO" = "1" ]; then - download_file "https://dl.cloudsmith.io/public/thinedge/${COMMUNITY_REPO}/setup.alpine.sh" - run_repo_setup "$TMPDIR/setup.alpine.sh" - fi - - $sh_c "apk add --no-cache $*" -} - -install_via_apt() { - if should_install_predepends && [ -n "$PREDEPENDS_PACKAGES" ]; then - $sh_c "apt-get update && apt-get install -y $PREDEPENDS_PACKAGES" - fi - download_file "https://dl.cloudsmith.io/public/thinedge/${PACKAGE_REPO}/setup.deb.sh" - run_repo_setup "$TMPDIR/setup.deb.sh" - - # setup community repo - if [ "$SETUP_COMMUNITY_REPO" = "1" ]; then - download_file "https://dl.cloudsmith.io/public/thinedge/${COMMUNITY_REPO}/setup.deb.sh" - run_repo_setup "$TMPDIR/setup.deb.sh" - fi - - $sh_c "DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y $*" -} - -install_via_dnf() { - if should_install_predepends && [ -n "$(dnf repoquery epel-release --refresh 2>/dev/null)" ]; then - log "Adding epel-release" - $sh_c "dnf --setopt=install_weak_deps=0 install -y epel-release" - fi - - if should_install_predepends && [ -n "$PREDEPENDS_PACKAGES" ]; then - $sh_c "dnf install -y $PREDEPENDS_PACKAGES" - fi - download_file "https://dl.cloudsmith.io/public/thinedge/${PACKAGE_REPO}/setup.rpm.sh" - run_repo_setup "$TMPDIR/setup.rpm.sh" - - # setup community repo - if [ "$SETUP_COMMUNITY_REPO" = "1" ]; then - download_file "https://dl.cloudsmith.io/public/thinedge/${COMMUNITY_REPO}/setup.rpm.sh" - run_repo_setup "$TMPDIR/setup.rpm.sh" - fi - - $sh_c "dnf install --best --refresh -y $*" -} - -install_via_microdnf() { - if should_install_predepends && [ -n "$(microdnf repoquery epel-release --refresh 2>/dev/null)" ]; then - log "Adding epel-release" - $sh_c "microdnf --setopt=install_weak_deps=0 install -y epel-release" - fi - - if should_install_predepends && [ -n "$PREDEPENDS_PACKAGES" ]; then - $sh_c "microdnf install -y $PREDEPENDS_PACKAGES" - fi - download_file "https://dl.cloudsmith.io/public/thinedge/${PACKAGE_REPO}/setup.rpm.sh" - run_repo_setup "$TMPDIR/setup.rpm.sh" - - # setup community repo - if [ "$SETUP_COMMUNITY_REPO" = "1" ]; then - download_file "https://dl.cloudsmith.io/public/thinedge/${COMMUNITY_REPO}/setup.rpm.sh" - run_repo_setup "$TMPDIR/setup.rpm.sh" - fi - - $sh_c "microdnf install --best --refresh -y $*" -} - -install_via_zypper() { - if should_install_predepends && [ -n "$PREDEPENDS_PACKAGES" ]; then - $sh_c "zypper install -y $PREDEPENDS_PACKAGES" - fi - download_file "https://dl.cloudsmith.io/public/thinedge/${PACKAGE_REPO}/setup.rpm.sh" - run_repo_setup "$TMPDIR/setup.rpm.sh" - - # setup community repo - if [ "$SETUP_COMMUNITY_REPO" = "1" ]; then - download_file "https://dl.cloudsmith.io/public/thinedge/${COMMUNITY_REPO}/setup.rpm.sh" - run_repo_setup "$TMPDIR/setup.rpm.sh" - fi - - $sh_c "zypper install -y $*" -} - -group_exists() { - name="$1" - if command_exists getent; then - getent group "$name" >/dev/null - else - # Fallback to plain grep, as busybox does not have getent - grep -q "^${name}:" /etc/group - fi -} - -user_exists() { - name="$1" - if command_exists getent; then - getent passwd "$name" >/dev/null - else - # Fallback to plain grep, as busybox does not have getent - grep -q "^${name}:" /etc/passwd - fi -} - -tarball_postinstall() { - ### Create groups - if ! group_exists tedge; then - if command_exists groupadd; then - $sh_c "groupadd --system tedge" - elif command_exists addgroup; then - $sh_c "addgroup -S tedge" - else - echo "WARNING: Could not create group: tedge" >&2 - fi - fi - - ### Create users - # Create user tedge with no home(--no-create-home), no login(--shell) and in group tedge(--gid) - if ! user_exists tedge; then - if command_exists useradd; then - $sh_c "useradd --system --no-create-home --shell /sbin/nologin --gid tedge tedge" - elif command_exists adduser; then - $sh_c "adduser -g '' -H -D tedge -G tedge" - else - echo "WARNING: Could not create user: tedge" >&2 - fi - fi - - ### Create file in /etc/sudoers.d directory. With this configuration, the tedge user have the right to call the tedge command with sudo rights, which is required for system-wide configuration in "/etc/tedge" - if [ -d /etc/sudoers.d ]; then - $sh_c "echo 'tedge ALL = (ALL) NOPASSWD: /usr/bin/tedge, /etc/tedge/sm-plugins/[a-zA-Z0-9]*, /bin/sync, /sbin/init' >/etc/sudoers.d/tedge" - - if [ -f "/etc/sudoers.d/010_pi-nopasswd" ]; then - $sh_c "echo 'tedge ALL = (ALL) NOPASSWD: /usr/bin/tedge, /etc/tedge/sm-plugins/[a-zA-Z0-9]*, /bin/sync, /sbin/init' >/etc/sudoers.d/tedge-nopasswd" - fi - fi - - ### Add include to mosquitto.conf so tedge specific conf will be loaded - if [ -f /etc/mosquitto/mosquitto.conf ]; then - if ! grep -q "include_dir /etc/tedge/mosquitto-conf" "/etc/mosquitto/mosquitto.conf"; then - # Insert `include_dir /etc/tedge/mosquitto-conf` before any `include_dir` - # directive so that all other partial conf files inherit the - # `per_listener_settings` defined in /etc/tedge/mosquitto-conf. - # `per_listener_settings` has to be defined once, before other listener - # settings or else it causes the following error: - # - # Error: per_listener_settings must be set before any other security - # settings. - # Match any included_dir directive as different distributions have different default settings: - # On Fedora: `#include_dir`. mosquitto does not use a /etc/mosquitto/conf.d folder - # On Debian: `include_dir /etc/mosquitto/conf.d`. Uses a conf.d folder, so the tedge setting must be before this - - # Check if `include_dir` or `#include_dir` (as the latter could be a future problem if the user uncomments it) - if grep -qE '^#?include_dir' /etc/mosquitto/mosquitto.conf; then - # Don't assume awk exists - if command_exists awk; then - # insert tedge include_dir before the first `included_dir` (but only the first!) - awk '!found && /^#?include_dir/ \ - { print "include_dir /etc/tedge/mosquitto-conf"; found=1 }1' \ - /etc/mosquitto/mosquitto.conf > "$TMPDIR/mosquitto.conf" - - # replace existing file, but preserve permissions of the original file - $sh_c "cat $TMPDIR/mosquitto.conf > /etc/mosquitto/mosquitto.conf" - else - # fallback to appending the setting to file - $sh_c "echo 'include_dir /etc/tedge/mosquitto-conf' >> /etc/mosquitto/mosquitto.conf" - fi - else - # config does not contain any include_dir directive, so we can safely append it - $sh_c "echo 'include_dir /etc/tedge/mosquitto-conf' >> /etc/mosquitto/mosquitto.conf" - fi - fi - fi - - # Initialize the tedge - $sh_c "tedge init" ||: - - if command_exists c8y-remote-access-plugin; then - $sh_c "c8y-remote-access-plugin --init" ||: - fi -} - -get_package_manager() { - package_manager= - if command_exists apt-get; then - package_manager="apt" - elif command_exists apk; then - package_manager="apk" - elif command_exists dnf; then - package_manager="dnf" - elif command_exists microdnf; then - package_manager="microdnf" - elif command_exists zypper; then - package_manager="zypper" - fi - - echo "$package_manager" -} - -try_install_dependencies() { - _package_manager="$(get_package_manager)" - case "$_package_manager" in - apk) - $sh_c "apk add --no-cache $*" - ;; - apt) - $sh_c "apt-get update" - $sh_c "apt-get install --no-install-recommends -y $*" - ;; - dnf) - $sh_c "dnf install -y $*" - ;; - microdnf) - $sh_c "microdnf install -y $*" - ;; - zypper) - $sh_c "zypper install -y $*" - ;; - *) - debug "Package manager ($_package_manager) does not support installing extra packages. Trying to continue anyway" - ;; - esac -} - -configure_pre_depends() { - # Some distributions have curl-minimal installed, which then causes - # problems when trying to install the "curl" package. So only install it if the command is not available - PREDEPENDS_PACKAGES="ca-certificates" - if ! command_exists curl && ! command_exists wget; then - PREDEPENDS_PACKAGES="$PREDEPENDS_PACKAGES curl" - fi -} - -get_arch() { - if [ -z "$ARCH" ]; then - ARCH="$(uname -m)" - fi - echo "$ARCH" -} - -main() { - configure_pre_depends - configure_shell - - if [ -d "$TMPDIR" ]; then - $sh_c "rm -Rf $TMPDIR" - fi - mkdir -p "$TMPDIR" - touch "$LOGFILE" && chmod 0666 "$LOGFILE" - - echo "Thank you for trying thin-edge.io!" - echo - - ARCH=$(get_arch) - export ARCH - case "$ARCH" in - *armv6*) - PACKAGE_REPO="tedge-${REPO_CHANNEL}-armv6" - ;; - *) - PACKAGE_REPO="tedge-${REPO_CHANNEL}" - ;; - esac - - # Detect package manager - if [ -z "$PACKAGE_MANAGER" ]; then - PACKAGE_MANAGER=$(get_package_manager) - if [ -z "$PACKAGE_MANAGER" ]; then - PACKAGE_MANAGER="tarball" - fi - fi - - # Fallback to tarball if curl or bash is not available - if [ "$PACKAGE_MANAGER" != "tarball" ]; then - if command_exists bash && command_exists curl; then - log "Package management dependencies met" >/dev/null - else - log "Fallback to installing from tarball as curl and bash were not found. curl and bash are required to install thin-edge.io using a package manager" - PACKAGE_MANAGER="tarball" - fi - fi - - ONLY_INCLUDE_BINARIES= - case "$TYPE" in - minimal) - PACKAGES="tedge-minimal" - ONLY_INCLUDE_BINARIES="tedge tedge-mapper" - ;; - full) - PACKAGES="tedge-full" - # An empty value will include all binaries - ONLY_INCLUDE_BINARIES="" - ;; - *) - log "Unsupported argument type." - exit 1 - ;; - esac - - log "Detected package manager: $PACKAGE_MANAGER" - - case "$PACKAGE_MANAGER" in - tarball) - # Note: If binaries are empty, then all included binaries are extracted - # Also install mosquitto if possible - # shellcheck disable=SC2086 - if command_exists mosquitto; then - # Note: mosquitto could either be manually installed (e.g. in a container) and not via a package manager - # so don't install mosquitto if the binary exists - try_install_dependencies $PREDEPENDS_PACKAGES - else - try_install_dependencies mosquitto $PREDEPENDS_PACKAGES - fi - # shellcheck disable=SC2086 - install_via_tarball $ONLY_INCLUDE_BINARIES - ;; - apk) - install_via_apk $PACKAGES - ;; - apt) - install_via_apt $PACKAGES - ;; - dnf) - install_via_dnf $PACKAGES - ;; - microdnf) - install_via_microdnf $PACKAGES - ;; - zypper) - install_via_zypper $PACKAGES - ;; - *) - # Should only happen if there is a bug in the script - fail 1 "Unknown package manager: $PACKAGE_MANAGER" - ;; - esac - - if is_dry_run; then - echo - echo "Dry run complete" - # Test if tedge command is there and working - elif tedge help >/dev/null 2>&1; then - # remove error handler - trap - EXIT - - # Only delete when everything was ok to help with debugging - $sh_c "rm -Rf $TMPDIR" - - echo - echo "thin-edge.io is now installed on your system!" - echo - echo "You can go to our documentation to find next steps: https://thin-edge.github.io/thin-edge.io/start/getting-started" - else - echo "Something went wrong in the installation process please try the manual installation steps instead:" - echo "https://thin-edge.github.io/thin-edge.io/install/" - fi -} - -# Support reading setting from environment variables -DRY_RUN=${DRY_RUN:-} -VERSION=${VERSION:-} -PACKAGE_MANAGER="${PACKAGE_MANAGER:-}" - -while [ $# -gt 0 ]; do - case $1 in - --minimal) - TYPE="minimal" - ;; - # Allow user to specify which packages manager they would like - # e.g. they might opt for the 'tarball' option even if they are on debian - --package-manager|-p) - PACKAGE_MANAGER="$2" - shift - ;; - --dry-run) - DRY_RUN=1 - ;; - --channel) - REPO_CHANNEL="$2" - shift - ;; - --arch) - ARCH="$2" - shift - ;; - --skip-community) - SETUP_COMMUNITY_REPO=0 - ;; - --help|-h) - usage - exit 0 - ;; - --*|-*) - log "Unknown option: $1" - usage - exit 1 - ;; - *) - VERSION="$1" - ;; - esac - # Use if statement as some devices - # don't support math $((arith)) statements - if [ $# -gt 0 ]; then - shift 1 - fi -done - -# wrapped up in a function so that we have some protection against only getting -# half the file during "curl | sh" -main \ No newline at end of file diff --git a/recipes/thin-edge.io/recipe.toml b/recipes/thin-edge.io/recipe.toml deleted file mode 100644 index 563523d..0000000 --- a/recipes/thin-edge.io/recipe.toml +++ /dev/null @@ -1,2 +0,0 @@ -description = "install thin-edge.io" -priority = 20_000 \ No newline at end of file diff --git a/recipes/thin-edge.io/steps/00-install.sh b/recipes/thin-edge.io/steps/00-install.sh deleted file mode 100755 index fb3ebc1..0000000 --- a/recipes/thin-edge.io/steps/00-install.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -set -e -echo "----------------------------------------------------------------------------------" -echo "Executing $0" -echo "----------------------------------------------------------------------------------" -echo "uname -a: $(uname -a)" | tee -a "${RECIPE_DIR}/build.log" -echo "uname -m: $(uname -m)" | tee -a "${RECIPE_DIR}/build.log" -echo - -# install thin-edge.io -arch=$(uname -m) -case "$arch" in - *armv7*) - # Due to differences between the build process and the target device, the arch - # used for installation needs to be forced to armv6. - echo "Using armv6 workaround" | tee -a "${RECIPE_DIR}/build.log" - curl -1sLf 'https://dl.cloudsmith.io/public/thinedge/community/gpg.2E65716592E5C6D4.key' | gpg --no-default-keyring --dearmor > /usr/share/keyrings/thinedge-community-archive-keyring.gpg - "${RECIPE_DIR}/files/thin-edge.io.sh" --channel main --arch armv6 2>&1 | tee -a "${RECIPE_DIR}/build.log" - ;; - *) - wget -O - thin-edge.io/install.sh | sh -s -- --channel main | tee -a "${RECIPE_DIR}/build.log" - ;; -esac - - -# Install collectd -apt-get install -y -o DPkg::Options::=--force-confnew --no-install-recommends \ - mosquitto-clients \ - c8y-command-plugin \ - tedge-collectd-setup \ - tedge-monit-setup \ - tedge-inventory-plugin | tee -a "${RECIPE_DIR}/build.log" - -# custom tedge configuration -tedge config set apt.name "(tedge|c8y|python|wget|vim|curl|apt|mosquitto|ssh|sudo).*" -tedge config set c8y.enable.firmware_update "true" - -# Enable network manager by default -systemctl enable NetworkManager || true - -# Enable services by default to have sensible default settings once tedge is configured -systemctl enable tedge-agent -systemctl enable tedge-mapper-c8y -systemctl enable tedge-mapper-collectd -systemctl enable collectd -systemctl disable c8y-firmware-plugin - -# Custom mosquitto configuration -if ! grep -q '^pid_file' /etc/mosquitto/mosquitto.conf; then - install -D -m 644 "${RECIPE_DIR}/files/custom.conf" -t /etc/tedge/mosquitto-conf/ -fi - -# Persist tedge configuration and related components (e.g. mosquitto) -install -D -m 644 "${RECIPE_DIR}/files/tedge-config.toml" -t /etc/rugpi/state - -# Add default plugin configurations -install -D -m 644 -g tedge -o tedge "${RECIPE_DIR}/files/tedge-configuration-plugin.toml" -t /etc/tedge/plugins/ -install -D -m 644 -g tedge -o tedge "${RECIPE_DIR}/files/tedge-log-plugin.toml" -t /etc/tedge/plugins/ diff --git a/recipes/x-avahi-daemon/files/tedge.service b/recipes/x-avahi-daemon/files/tedge.service deleted file mode 100644 index 789c40f..0000000 --- a/recipes/x-avahi-daemon/files/tedge.service +++ /dev/null @@ -1,19 +0,0 @@ - - - - thin-edge.io (%h) - - _thin-edge_mqtt._tcp - 1883 - topics=te/ - - - _thin-edge_http._tcp - 8000 - - - _thin-edge_c8y._tcp - 8001 - topics=/c8y - - \ No newline at end of file diff --git a/recipes/x-avahi-daemon/recipe.toml b/recipes/x-avahi-daemon/recipe.toml deleted file mode 100644 index 5466a13..0000000 --- a/recipes/x-avahi-daemon/recipe.toml +++ /dev/null @@ -1 +0,0 @@ -description = "install and configure Avahi" \ No newline at end of file diff --git a/recipes/x-avahi-daemon/steps/00-packages b/recipes/x-avahi-daemon/steps/00-packages deleted file mode 100644 index 89feeb5..0000000 --- a/recipes/x-avahi-daemon/steps/00-packages +++ /dev/null @@ -1,2 +0,0 @@ -avahi-daemon -avahi-utils \ No newline at end of file diff --git a/recipes/x-avahi-daemon/steps/01-install.sh b/recipes/x-avahi-daemon/steps/01-install.sh deleted file mode 100755 index d5130bf..0000000 --- a/recipes/x-avahi-daemon/steps/01-install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Enable discovery of the SSH service. -cp /usr/share/doc/avahi-daemon/examples/ssh.service /etc/avahi/services - -# Enable discovery of the SFTP service. -cp /usr/share/doc/avahi-daemon/examples/sftp-ssh.service /etc/avahi/services - -# Enable discovery of the HTTP interface. -install -D -m 644 "${RECIPE_DIR}/files/tedge.service" -t /etc/avahi/services \ No newline at end of file diff --git a/rugpi-bakery.toml b/rugpi-bakery.toml new file mode 100644 index 0000000..0e84b36 --- /dev/null +++ b/rugpi-bakery.toml @@ -0,0 +1,25 @@ +[repositories] +rugpi-extra = { git = "https://github.com/silitics/rugpi-extra.git" } +tedge-rugpi-core = { git = "https://github.com/thin-edge/tedge-rugpi-core.git" } + +[images.tryboot] +layer = "default" + +[images.tryboot-containers] +layer = "containers" + +# A specific image including the firmware update for Raspberry Pi 4 and CM4. +[images.pi4] +layer = "default" +include_firmware = "pi4" + +# An image using the U-Boot boot flow for Raspberry Pi 3 and Zero 2. +[images.u-boot] +layer = "default" +boot_flow = "u-boot" + +# An `armhf` image for older Raspberry Pi's using the U-Boot boot flow. +[images.u-boot-armhf] +layer = "default" +architecture = "armhf" +boot_flow = "u-boot" diff --git a/run-bakery b/run-bakery index e89356c..a9a7eb7 100755 --- a/run-bakery +++ b/run-bakery @@ -3,7 +3,7 @@ set -e DOCKER=${DOCKER:-docker} -RUGPI_IMAGE=${RUGPI_IMAGE:-ghcr.io/silitics/rugpi-bakery:v0.5} +RUGPI_IMAGE=${RUGPI_IMAGE:-ghcr.io/silitics/rugpi-bakery:feat-layers} $DOCKER run --rm --privileged \ -v "$(pwd)":/project \ From e323f28f0eee3698c63c017165d7ef5562e0e8a5 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 13 Jan 2024 16:57:56 +0100 Subject: [PATCH 02/18] update github actions --- .github/workflows/bake-image.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/bake-image.yml b/.github/workflows/bake-image.yml index 914dc7b..1dff7fa 100644 --- a/.github/workflows/bake-image.yml +++ b/.github/workflows/bake-image.yml @@ -76,7 +76,7 @@ jobs: just IMAGE=${{ matrix.job.image }} build - name: Upload Image - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ steps.info.outputs.PREFIX }}${{ matrix.job.image }}_${{ needs.info.outputs.version }} path: | @@ -92,8 +92,8 @@ jobs: - bake-image steps: - name: Checkout - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 + uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 with: path: release - name: Show release artifacts From b97ecd9dc978d5fa151a9f2b548f28121b963ac0 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 13 Jan 2024 18:48:00 +0100 Subject: [PATCH 03/18] remove docker recipe (as it is stored in another repo) --- recipes/docker/recipe.toml | 4 ---- recipes/docker/steps/00-install.sh | 26 -------------------------- 2 files changed, 30 deletions(-) delete mode 100644 recipes/docker/recipe.toml delete mode 100644 recipes/docker/steps/00-install.sh diff --git a/recipes/docker/recipe.toml b/recipes/docker/recipe.toml deleted file mode 100644 index 53dd456..0000000 --- a/recipes/docker/recipe.toml +++ /dev/null @@ -1,4 +0,0 @@ -description = "install latest docker version" -priority = 10_000 -dependencies = ["thin-edge.io"] -default = false \ No newline at end of file diff --git a/recipes/docker/steps/00-install.sh b/recipes/docker/steps/00-install.sh deleted file mode 100644 index d6c13d4..0000000 --- a/recipes/docker/steps/00-install.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -e - -# Add Docker's official GPG key: - -apt-get update -apt-get install -y --no-install-recommends ca-certificates curl gnupg -install -m 0755 -d /etc/apt/keyrings -curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg -chmod a+r /etc/apt/keyrings/docker.gpg - -# Add the repository to Apt sources: -echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ - $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ - tee /etc/apt/sources.list.d/docker.list > /dev/null -apt-get update - -apt-get install -y --no-install-recommends \ - docker-ce \ - docker-ce-cli \ - containerd.io \ - docker-buildx-plugin \ - docker-compose-plugin \ - tedge-container-plugin - -usermod -aG docker tedge From 694fd57e77ab0fae47b15c8265891de75b4cc8d9 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 13 Jan 2024 19:30:36 +0100 Subject: [PATCH 04/18] remove unused variables --- justfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/justfile b/justfile index e453b2d..c14acee 100644 --- a/justfile +++ b/justfile @@ -1,14 +1,12 @@ set dotenv-load -export IMAGE := "tryboot" - export RUGPI_IMAGE := "ghcr.io/silitics/rugpi-bakery:feat-layers" export PREFIX := "tedge_rugpi_" +export IMAGE := "tryboot" export VERSION := env_var_or_default("VERSION", `date +'%Y%m%d.%H%M'`) export IMAGE_NAME := PREFIX + IMAGE + "_" + VERSION export OUTPUT_IMAGE := "build" / IMAGE_NAME + ".img" -export BUILD_INFO := IMAGE_NAME # Generate a version name (that can be used in follow up commands) generate_version: From dca9ca85be827626df08c0d2e072b14274ffe725 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 13 Jan 2024 23:12:24 +0100 Subject: [PATCH 05/18] fixup! feat!: use rugpi repositories and layers feature --- justfile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/justfile b/justfile index c14acee..5cba74a 100644 --- a/justfile +++ b/justfile @@ -76,7 +76,7 @@ release: # Help users to select the correct image for them # build-pi1: - just IMAGE=u-boot-armhf build compress + just IMAGE=u-boot-armhf build @echo @echo "This image can be applied to" @echo " * pi1" @@ -85,7 +85,7 @@ build-pi1: @echo build-pizero: - just IMAGE=u-boot-armhf build compress + just IMAGE=u-boot-armhf build @echo @echo "This image can be applied to" @echo " * pi1" @@ -94,7 +94,7 @@ build-pizero: @echo build-pi2: - just IMAGE=u-boot build compress + just IMAGE=u-boot build @echo @echo "This image can be applied to" @echo " * pi2" @@ -103,7 +103,7 @@ build-pi2: @echo build-pi3: - just IMAGE=u-boot build compress + just IMAGE=u-boot build @echo @echo "This image can be applied to" @echo " * pi2" @@ -112,7 +112,7 @@ build-pi3: @echo build-pizero2w: - just IMAGE=u-boot build compress + just IMAGE=u-boot build @echo @echo "This image can be applied to" @echo " * pi2" @@ -120,7 +120,7 @@ build-pizero2w: @echo build-pi4: - just IMAGE=tryboot build compress + just IMAGE=tryboot build @echo @echo "This image can be applied to" @echo " * pi4" @@ -128,14 +128,14 @@ build-pi4: @echo build-pi4-include-firmware: - just IMAGE=pi4 build compress + just IMAGE=pi4 build @echo @echo "This image can be applied to" @echo " * pi4" @echo build-pi5: - just IMAGE=tryboot build compress + just IMAGE=tryboot build @echo @echo "This image can be applied to" @echo " * pi4" From 39b9b8dda75bad0f2d02a61e074c93cb5ed69fd5 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sun, 14 Jan 2024 01:06:51 +0100 Subject: [PATCH 06/18] enable rugpi admin --- layers/containers.toml | 6 ++++++ layers/default.toml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/layers/containers.toml b/layers/containers.toml index 72f731b..5dda44e 100644 --- a/layers/containers.toml +++ b/layers/containers.toml @@ -5,3 +5,9 @@ recipes = [ "tedge-rugpi-core/defaults", "tedge-rugpi-core/docker", ] + +[parameters."core/apt-cleanup"] +autoremove = true + +[parameters."core/rugpi-ctrl"] +rugpi_admin = true # Enable Rugpi Admin. diff --git a/layers/default.toml b/layers/default.toml index ba0b1f0..2e8bf84 100644 --- a/layers/default.toml +++ b/layers/default.toml @@ -4,3 +4,9 @@ parent = "tedge-rugpi-core/tedge" recipes = [ "tedge-rugpi-core/defaults", ] + +[parameters."core/apt-cleanup"] +autoremove = true + +[parameters."core/rugpi-ctrl"] +rugpi_admin = true # Enable Rugpi Admin. From 67c5a1e98dd0d3c177766afb04e3dcfcf4523921 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sun, 14 Jan 2024 09:50:12 +0100 Subject: [PATCH 07/18] dev: add clean-cache to clean rugpi repo cache --- justfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/justfile b/justfile index 5cba74a..ddb8d66 100644 --- a/justfile +++ b/justfile @@ -26,8 +26,12 @@ show: setup: docker run --privileged --rm tonistiigi/binfmt --install all +# Clean rugpi repository cache (to force running recipes to build an image) +clean-cache: + @rm -Rf .rugpi/repositories + # Clean rugpi cache and build folders -clean: +clean-all: @rm -Rf .rugpi @rm -Rf build/ From a8a4c99526a3a86004d89a680b8484bf39c7f8c6 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sun, 14 Jan 2024 10:37:21 +0100 Subject: [PATCH 08/18] add descriptions to images --- rugpi-bakery.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rugpi-bakery.toml b/rugpi-bakery.toml index 0e84b36..c100558 100644 --- a/rugpi-bakery.toml +++ b/rugpi-bakery.toml @@ -2,9 +2,11 @@ rugpi-extra = { git = "https://github.com/silitics/rugpi-extra.git" } tedge-rugpi-core = { git = "https://github.com/thin-edge/tedge-rugpi-core.git" } +# Image for Raspberry Pi 4, 5, CM4, 400 [images.tryboot] layer = "default" +# Image for Raspberry Pi 4, 5, CM4, 400 - includes containerization dependencies [images.tryboot-containers] layer = "containers" @@ -18,6 +20,11 @@ include_firmware = "pi4" layer = "default" boot_flow = "u-boot" +# An image using the U-Boot boot flow for Raspberry Pi 3 and Zero 2 with containerization dependencies +[images.u-boot-containers] +layer = "containers" +boot_flow = "u-boot" + # An `armhf` image for older Raspberry Pi's using the U-Boot boot flow. [images.u-boot-armhf] layer = "default" From f2b53c3cf4a9aa5a61bf7fecea5348856afee322 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Mon, 15 Jan 2024 15:53:59 +0100 Subject: [PATCH 09/18] update instructions for the next branch --- README.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index daf3e56..d695811 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # thin-edge.io image using rugpi +:warning: This repository is using a new [layers features](https://github.com/silitics/rugpi/tree/feat-layers) from Rugpi. It is currently under development. + The repository can be used to build custom Raspberry Pi images with thin-edge.io and Rugpi for robust OTA Operation System updates. ## Compatible devices @@ -31,7 +33,7 @@ The following images are included in this repository. ## Building -### Building an image without WIFI credentials (devices must have an ethernet adapter!) +### Building an image To run the build tasks, install [just](https://just.systems/man/en/chapter_5.html). @@ -43,7 +45,7 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm 2. Edit the `.env` file - If you want to include wifi credentials in your image, then edit the values in the `.env` file: + If your device does not have an ethernet adapter, or you the device to connect to a Wifi network for onboarding, then you will have to add the Wifi credentials to the `.env` file. ```sh SECRETS_WIFI_SSID=example @@ -53,9 +55,9 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm **Note** - If you include wifi credentials in your image, make sure you don't make the image public, as it would expose your credentials! + The Wifi credentials only need to be included in the image that is flashed to the SD card. Subsequent images don't need to included the Wifi credentials, as the network connection configuration files are persisted across images. - Alternatively, you could build an image locally which includes the wifi credentials, and then any future builds you don't need to include the wifi credentials as they should be persisted. + If an image has Wifi credentials baked in, then you should not make this image public, as it would expose your credentials! 3. Create the image (including downloading the supported base Raspberry Pi image) using: @@ -63,6 +65,17 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm just IMAGE=tryboot build ``` + **Note** + + If you notice that the recipes are not being run, then you can clear the cache by running the following command: + + ```sh + just clean-cache + + # Then you can rebuild the image and the recipes should be run + just IMAGE=tryboot build + ``` + 4. Using the path to the image shown in the console to flash the image to the Raspberry Pi. 5. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) @@ -190,9 +203,8 @@ You can customize the images built by the Github workflow by creating a secret w **Value** ```sh - SECRETS_WIFI_SSID="mywifi" - SECRETS_WIFI_PASSWORD="somepassword" SSH_KEYS_bootstrap="ssh-rsa xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx bootstrap" + SSH_KEYS_seconduser="ssh-rsa xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx myseconduser" ``` Remove any lines which are not applicable to your build. From b9c470ee1420e871a4cd4670082001b6e0589c5b Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Mon, 15 Jan 2024 15:54:53 +0100 Subject: [PATCH 10/18] dev: add script to add ssk keys to .env file --- scripts/fetch-ssh-keys.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 scripts/fetch-ssh-keys.sh diff --git a/scripts/fetch-ssh-keys.sh b/scripts/fetch-ssh-keys.sh new file mode 100755 index 0000000..bf81b15 --- /dev/null +++ b/scripts/fetch-ssh-keys.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -e + +ENV_FILE=".env" + +if [ -d ~/.ssh ]; then + echo "Looking for public keys in ~/.ssh" >&2 + + for file in ~/.ssh/*.pub; do + CONTENTS=$(head -n1 "$file" | tr -d '\r\n') + + if grep -qF "$CONTENTS" "$ENV_FILE"; then + echo "Key ($file) already exists in $ENV_FILE" + else + echo "Adding $file" >&2 + ssh_id=$(basename "$file" | md5sum | cut -d' ' -f1) + echo SSH_KEYS_"$ssh_id"=\""$CONTENTS"\" >> "$ENV_FILE" + fi + done +fi From a794dcdd074b657ae62cd338459a974c1c04dd28 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Mon, 15 Jan 2024 16:01:17 +0100 Subject: [PATCH 11/18] docs: add note about cloning the next branch --- README.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d695811..6680e12 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ The following images are included in this repository. |Image|Description| |-------|-----------| |tryboot|Image for Raspberry Pi 4 and 5 devices which use the tryboot bootloader| +|tryboot-containers|Image for Raspberry Pi 4 and 5 devices which use the tryboot bootloader and with docker pre-installed| |rpi4|Raspberry Pi 4 image which includes the firmware to enable tryboot bootloader| |u-boot|Image for Raspberry Pi 2, 3, zero 2W| |u-boot-armhf|Image for Raspberry Pi 1 and zero| @@ -37,13 +38,21 @@ The following images are included in this repository. To run the build tasks, install [just](https://just.systems/man/en/chapter_5.html). -1. Create a custom `.env` file which will be used to store secrets +1. Clone the repository (use the `next` branch by default) + + ```sh + git clone -b next https://github.com/thin-edge/tedge-rugpi-image.git + ``` + +2. Create a custom `.env` file which will be used to store secrets ```sh cp env.template .env ``` -2. Edit the `.env` file + The `.env` file will not be committed to the repo + +3. Edit the `.env` file If your device does not have an ethernet adapter, or you the device to connect to a Wifi network for onboarding, then you will have to add the Wifi credentials to the `.env` file. @@ -59,7 +68,7 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm If an image has Wifi credentials baked in, then you should not make this image public, as it would expose your credentials! -3. Create the image (including downloading the supported base Raspberry Pi image) using: +4. Create the image (including downloading the supported base Raspberry Pi image) using: ```sh just IMAGE=tryboot build @@ -76,9 +85,13 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm just IMAGE=tryboot build ``` -4. Using the path to the image shown in the console to flash the image to the Raspberry Pi. +5. Using the path to the image shown in the console to flash the image to the Raspberry Pi. + +6. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) + + **Notes** -5. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) + You can apply image updates via the device's localhost:8088 interface, however you will have to uncompress the `.xz` image file to a `.img` file. For further information on Rugpi, checkout the [quick start guide](https://oss.silitics.com/rugpi/docs/getting-started). From 94b1e8c34ee2124708d0ecb0a440315af3b6b9e5 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Mon, 22 Jan 2024 16:14:04 +0100 Subject: [PATCH 12/18] docs: add setup dependencies step --- README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6680e12..9fafb2d 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,17 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm git clone -b next https://github.com/thin-edge/tedge-rugpi-image.git ``` -2. Create a custom `.env` file which will be used to store secrets +2. Install the dependencies + + ```sh + just setup + ``` + + **Notes** + + This step is required to allow you to run binaries built for different CPU architectures, e.g. building an aarch64 or armhf image on a x86_64 machine. + +3. Create a custom `.env` file which will be used to store secrets ```sh cp env.template .env @@ -52,7 +62,7 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm The `.env` file will not be committed to the repo -3. Edit the `.env` file +4. Edit the `.env` file If your device does not have an ethernet adapter, or you the device to connect to a Wifi network for onboarding, then you will have to add the Wifi credentials to the `.env` file. @@ -68,7 +78,7 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm If an image has Wifi credentials baked in, then you should not make this image public, as it would expose your credentials! -4. Create the image (including downloading the supported base Raspberry Pi image) using: +5. Create the image (including downloading the supported base Raspberry Pi image) using: ```sh just IMAGE=tryboot build @@ -85,9 +95,9 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm just IMAGE=tryboot build ``` -5. Using the path to the image shown in the console to flash the image to the Raspberry Pi. +6. Using the path to the image shown in the console to flash the image to the Raspberry Pi. -6. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) +7. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) **Notes** From 0e1fe639df20ce7d9ee24ab602bd9f4ccc82e262 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 3 Feb 2024 14:10:04 +0100 Subject: [PATCH 13/18] remove unnecessary repository reference --- rugpi-bakery.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rugpi-bakery.toml b/rugpi-bakery.toml index c100558..3b56f8b 100644 --- a/rugpi-bakery.toml +++ b/rugpi-bakery.toml @@ -1,5 +1,4 @@ [repositories] -rugpi-extra = { git = "https://github.com/silitics/rugpi-extra.git" } tedge-rugpi-core = { git = "https://github.com/thin-edge/tedge-rugpi-core.git" } # Image for Raspberry Pi 4, 5, CM4, 400 From 86f28aa4f70585486df01f890cb9cdfdaa551ee4 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 3 Feb 2024 14:10:41 +0100 Subject: [PATCH 14/18] ignore stdout --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index ddb8d66..7a1afec 100644 --- a/justfile +++ b/justfile @@ -24,7 +24,7 @@ show: # Note: technically only arm64,armhf are required, however install 'all' avoids the error message # on arm64 hosts setup: - docker run --privileged --rm tonistiigi/binfmt --install all + docker run --privileged --rm tonistiigi/binfmt --install all >/dev/null # Clean rugpi repository cache (to force running recipes to build an image) clean-cache: From 0be75266e62df5707c6f27ee9bdb67cacccd2fd5 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 3 Feb 2024 14:11:08 +0100 Subject: [PATCH 15/18] automatically run setup on build --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index 7a1afec..f8834b3 100644 --- a/justfile +++ b/justfile @@ -36,7 +36,7 @@ clean-all: @rm -Rf build/ # Create the image that can be flashed to an SD card or applied using the rugpi interface -build: +build: setup mkdir -p "{{parent_directory(OUTPUT_IMAGE)}}" echo "{{IMAGE_NAME}}" > {{justfile_directory()}}/.image ./run-bakery bake image {{IMAGE}} {{OUTPUT_IMAGE}} From 23d32104d5a716d06aea05c4e99720cc96b3f13f Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 3 Feb 2024 14:11:54 +0100 Subject: [PATCH 16/18] update run-bakery to align with rugpi template project --- justfile | 2 +- run-bakery | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/justfile b/justfile index f8834b3..e5a1339 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,6 @@ set dotenv-load -export RUGPI_IMAGE := "ghcr.io/silitics/rugpi-bakery:feat-layers" +export RUGPI_BAKERY_IMAGE := "ghcr.io/silitics/rugpi-bakery:v0.6" export PREFIX := "tedge_rugpi_" export IMAGE := "tryboot" diff --git a/run-bakery b/run-bakery index a9a7eb7..8d08f36 100755 --- a/run-bakery +++ b/run-bakery @@ -2,12 +2,28 @@ set -e -DOCKER=${DOCKER:-docker} -RUGPI_IMAGE=${RUGPI_IMAGE:-ghcr.io/silitics/rugpi-bakery:feat-layers} +DOCKER=${DOCKER:-"docker"} +DOCKER_FLAGS=${DOCKER_FLAGS:-""} -$DOCKER run --rm --privileged \ +RUGPI_DEV=${RUGPI_DEV:-"false"} + +if [ "${RUGPI_DEV}" = "false" ]; then + DOCKER_FLAGS="${DOCKER_FLAGS} --pull always" + RUGPI_VERSION=${RUGPI_VERSION:-"v0.6"} +else + RUGPI_VERSION=${RUGPI_VERSION:-"dev"} +fi + +RUGPI_BAKERY_IMAGE=${RUGPI_BAKERY_IMAGE:-"ghcr.io/silitics/rugpi-bakery:${RUGPI_VERSION}"} + +if [ -t 0 ] && [ -t 1 ]; then + DOCKER_FLAGS="${DOCKER_FLAGS} -it" +fi + +# shellcheck disable=SC2086 +exec $DOCKER run --rm --privileged \ + $DOCKER_FLAGS \ -v "$(pwd)":/project \ -v /dev:/dev \ - --pull always \ - "$RUGPI_IMAGE" \ + "${RUGPI_BAKERY_IMAGE}" \ "$@" From 00b3f05700bdf6e72b98fa284ba885b46c0e2be5 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 3 Feb 2024 14:12:09 +0100 Subject: [PATCH 17/18] update readme instructions --- README.md | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9fafb2d..920224c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# thin-edge.io image using rugpi +# thin-edge.io image using Rugpi :warning: This repository is using a new [layers features](https://github.com/silitics/rugpi/tree/feat-layers) from Rugpi. It is currently under development. @@ -84,24 +84,13 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm just IMAGE=tryboot build ``` - **Note** - - If you notice that the recipes are not being run, then you can clear the cache by running the following command: - - ```sh - just clean-cache - - # Then you can rebuild the image and the recipes should be run - just IMAGE=tryboot build - ``` - 6. Using the path to the image shown in the console to flash the image to the Raspberry Pi. 7. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) **Notes** - You can apply image updates via the device's localhost:8088 interface, however you will have to uncompress the `.xz` image file to a `.img` file. + You can apply image updates via the device's localhost:8088 interface, however you will have to expand the `.xz` image file to a `.img` file. For further information on Rugpi, checkout the [quick start guide](https://oss.silitics.com/rugpi/docs/getting-started). From 4ee5a563e5561f8f63ec10538fcfe7529a0077a6 Mon Sep 17 00:00:00 2001 From: Reuben Miller Date: Sat, 3 Feb 2024 14:21:09 +0100 Subject: [PATCH 18/18] simplify readme by removing unnecessary steps --- README.md | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 920224c..e8e6f9e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # thin-edge.io image using Rugpi -:warning: This repository is using a new [layers features](https://github.com/silitics/rugpi/tree/feat-layers) from Rugpi. It is currently under development. - -The repository can be used to build custom Raspberry Pi images with thin-edge.io and Rugpi for robust OTA Operation System updates. +The repository can be used to build custom Raspberry Pi images with thin-edge.io and [Rugpi](https://oss.silitics.com/rugpi/) for robust OTA Operating System updates. ## Compatible devices @@ -38,23 +36,13 @@ The following images are included in this repository. To run the build tasks, install [just](https://just.systems/man/en/chapter_5.html). -1. Clone the repository (use the `next` branch by default) - - ```sh - git clone -b next https://github.com/thin-edge/tedge-rugpi-image.git - ``` - -2. Install the dependencies +1. Clone the repository ```sh - just setup + git clone https://github.com/thin-edge/tedge-rugpi-image.git ``` - **Notes** - - This step is required to allow you to run binaries built for different CPU architectures, e.g. building an aarch64 or armhf image on a x86_64 machine. - -3. Create a custom `.env` file which will be used to store secrets +2. Create a custom `.env` file which will be used to store secrets ```sh cp env.template .env @@ -62,7 +50,7 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm The `.env` file will not be committed to the repo -4. Edit the `.env` file +3. Edit the `.env` file If your device does not have an ethernet adapter, or you the device to connect to a Wifi network for onboarding, then you will have to add the Wifi credentials to the `.env` file. @@ -78,15 +66,15 @@ To run the build tasks, install [just](https://just.systems/man/en/chapter_5.htm If an image has Wifi credentials baked in, then you should not make this image public, as it would expose your credentials! -5. Create the image (including downloading the supported base Raspberry Pi image) using: +4. Create the image (including downloading the supported base Raspberry Pi image) using: ```sh just IMAGE=tryboot build ``` -6. Using the path to the image shown in the console to flash the image to the Raspberry Pi. +5. Using the path to the image shown in the console to flash the image to the Raspberry Pi. -7. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) +6. Subsequent A/B updates can be done using Cumulocity IoT or the local Rugpi interface on (localhost:8088) **Notes**