├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── configuration ├── base │ └── common.yml ├── documentation │ └── packages-baseline.yml ├── mender │ ├── identity │ │ └── mender-device-identity │ ├── inventory │ │ └── mender-inventory-bootloader-integration │ └── mender.yml └── overlay │ ├── pi-cross-dev.global.yml │ ├── pi2-gitops.global.yml │ ├── pi2.global.yml │ ├── pi3-gitops.global.yml │ ├── pi3.global.yml │ ├── pi4-gitops.global.yml │ ├── pi4.global.yml │ ├── pi5-gitops.global.yml │ └── pi5.global.yml ├── docs ├── kernel_build.md └── wifi_setup.md ├── pi-cross-dev.yml ├── pi2-gitops.yml ├── pi2.yml ├── pi3-gitops.yml ├── pi3.yml ├── pi4-gitops.yml ├── pi4.yml ├── pi5-gitops.yml ├── pi5.yml ├── plugins ├── playbooks │ └── os_setup │ │ ├── collections │ │ └── ansible_collections │ │ ├── main.yml │ │ └── roles │ │ ├── bootloader │ │ ├── defaults │ │ │ └── main.yml │ │ ├── files │ │ │ ├── boot.scr.txt │ │ │ ├── cmdline.txt.u-boot │ │ │ ├── config.txt.u-boot.arm64 │ │ │ ├── config.txt.u-boot.armhf │ │ │ ├── generate-archives │ │ │ ├── raspberrypi-bootloader.tar.gz │ │ │ ├── u-boot-bootloader.arm64.pi3.tar.gz │ │ │ ├── u-boot-bootloader.arm64.pi4-v2.tar.gz │ │ │ ├── u-boot-bootloader.arm64.pi4.tar.gz │ │ │ ├── u-boot-bootloader.armhf.pi2.tar.gz │ │ │ └── u-boot-bootloader.armhf.pi3.tar.gz │ │ ├── tasks │ │ │ └── main.yml │ │ └── templates │ │ │ ├── cmdline.txt.raspberry-pi │ │ │ ├── config.txt.raspberry-pi.arm64 │ │ │ ├── fw_env.config │ │ │ └── multiboot.cfg │ │ ├── essential_bare_metal_packages │ │ ├── files │ │ │ ├── 85-systemd_networkd.preset │ │ │ ├── 95-wpa_supplicant.preset │ │ │ └── brcmfmac.conf │ │ ├── tasks │ │ │ └── main.yml │ │ ├── templates │ │ │ └── edi-set-hostname.override.conf │ │ └── vars │ │ │ └── main.yml │ │ ├── mender │ │ ├── defaults │ │ │ └── main.yml │ │ ├── files │ │ │ ├── 05_mender_update │ │ │ ├── empty.json │ │ │ ├── mender-io-archive-keyring.gpg │ │ │ ├── override.conf │ │ │ └── pi-uboot │ │ ├── tasks │ │ │ └── main.yml │ │ └── templates │ │ │ ├── device_type │ │ │ ├── mender-connect.conf │ │ │ ├── mender-io.list │ │ │ └── mender.conf │ │ └── repositories │ │ ├── files │ │ ├── 50-get-edi-io │ │ └── get-edi-io-archive-keyring.gpg │ │ ├── tasks │ │ └── main.yml │ │ └── templates │ │ └── get-edi-io.list ├── postprocessing_commands │ ├── container_image │ │ └── buildah2image.edi │ ├── documentation │ │ ├── write_doc │ │ └── write_doc.edi │ ├── fully_named_artifacts │ │ └── create_full_names.edi │ ├── genimage │ │ ├── exclude-patterns │ │ ├── fstab │ │ ├── genimage.cfg │ │ ├── hostname │ │ ├── hosts │ │ └── rootfs2image.edi │ ├── mender │ │ ├── ArtifactInstall_Enter_50_BootpartitionSetup │ │ ├── ArtifactInstall_Leave_50_ConfigurationBackup │ │ ├── ArtifactReboot_Leave_50_ConfigurationRestore │ │ ├── image2mender │ │ └── image2mender.edi │ ├── rootfs │ │ └── buildah2rootfs.edi │ └── timestamp │ │ └── timestamp.edi └── preprocessing_commands │ ├── bootstrap │ └── mmdebstrap.edi │ └── prerequisites │ ├── check_prerequisites │ └── check_prerequisites.edi └── ssh_pub_keys └── README.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # edi build artifacts 2 | 3 | artifacts/* 4 | main.retry 5 | 6 | # pycharm files 7 | .idea/* 8 | /configuration/mender/mender_custom.yml 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodules/ansible_collections/get_edi_io/debian_setup"] 2 | path = submodules/ansible_collections/get_edi_io/debian_setup 3 | url = https://github.com/lueschem/debian_setup.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Matthias Lüscher 4 | 5 | ----------------------------------------------------------------------------- 6 | Please note that some bash scripts within the plugins/postprocessing_commands 7 | folder are licensed under the GNU Lesser General Public License. 8 | ----------------------------------------------------------------------------- 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # edi Project Configuration for Raspberry Pi Devices 2 | 3 | Debian tool chain and image generation for the Raspberry Pi 2, 3, 4 and 5. 4 | 5 | Raspberry Pi 6 | 7 | > [!NOTE] 8 | > The *master* branch is **experimental** and currently based on Debian *trixie*. 9 | > To get the stable Debian *bookworm* configuration please check out the *debian_bookworm* branch. 10 | 11 | ## Introduction 12 | 13 | The edi configuration contained in this repository can be used to 14 | generate the following artifacts: 15 | 16 | * A Debian trixie arm64 (64bit) image suitable for the Raspberry Pi 3, 4 or 5. 17 | * A Debian trixie armhf (32bit) image suitable for the Raspberry Pi 2. 18 | * Matching Mender update artifacts for the above configurations. 19 | * A Podman/Docker image with a pre-installed cross development toolchains (armhf/arm64) for C and C++. 20 | 21 | > [!NOTE] 22 | > The Raspberry Pi 3 images are now making use of the tryboot feature too and do no longer 23 | > rely on u-boot to switch the boot partitions. A bookworm or older image is therefore incompatible 24 | > with a trixie or newer image. A migration to the new approach during the upgrade might be possible 25 | > but is currently not implemented. Feel free to write a feature request in case your existing project 26 | > would benefit from such a feature. 27 | 28 | ## Basic Usage 29 | 30 | ### Preparation 31 | 32 | Prior to using this edi project configuration you have to install 33 | [edi](https://www.get-edi.io) according to 34 | [this instructions](https://docs.get-edi.io/en/stable/getting_started_v2.html). 35 | Please take a careful look at the "Setting up ssh Keys" section since you 36 | will need a proper ssh key setup in order to access the 37 | the target device using ssh. 38 | 39 | The artifact generation requires some additional tools. On 40 | Ubuntu 24.04 and newer those tools can be installed as follows: 41 | 42 | ``` bash 43 | sudo apt install buildah containers-storage crun curl distrobox dosfstools e2fsprogs fakeroot genimage git mender-artifact mmdebstrap mtools parted python3-sphinx python3-testinfra podman rsync zerofree 44 | ``` 45 | 46 | ### Cloning this Repository 47 | 48 | The edi-pi project configuration contained in this git repository can be cloned as follows: 49 | 50 | ``` bash 51 | mkdir -p ~/edi-workspace/ && cd ~/edi-workspace/ 52 | git clone --recursive https://github.com/lueschem/edi-pi.git 53 | ``` 54 | 55 | The following steps assume that you are located within the project configuration directory: 56 | 57 | ``` bash 58 | cd ~/edi-workspace/edi-pi/ 59 | ``` 60 | 61 | If the repository has already been cloned earlier, do not forget to update the submodules: 62 | 63 | ``` bash 64 | git submodule update --init 65 | ``` 66 | 67 | ### Optional: Connecting to Mender 68 | 69 | To enable over the air (OTA) updates, the generated images are configured 70 | to connect to [https://hosted.mender.io/](https://hosted.mender.io/). 71 | In order to connect to your Mender tenant you have to provide your tenant token prior to building the images. 72 | The tenant token can be added to `configuration/mender/mender.yml`. If you do not want to 73 | add the tenant token to the version control system you can also copy `configuration/mender/mender.yml` to 74 | `configuration/mender/mender_custom.yml` and add the tenant token there. 75 | 76 | ### Creating a Raspberry Pi Image 77 | 78 | A Raspberry Pi image can be created using the following command: 79 | 80 | For Raspberry Pi 5, arm64: 81 | 82 | ``` bash 83 | edi -v project make pi5.yml 84 | ``` 85 | 86 | For Raspberry Pi 5, arm64, prepared for GitOps (git and Ansible preinstalled): 87 | 88 | ``` bash 89 | edi -v project make pi5-gitops.yml 90 | ``` 91 | 92 | For Raspberry Pi 4, arm64: 93 | 94 | ``` bash 95 | edi -v project make pi4.yml 96 | ``` 97 | 98 | For Raspberry Pi 4, arm64, prepared for GitOps (git and Ansible preinstalled): 99 | 100 | ``` bash 101 | edi -v project make pi4-gitops.yml 102 | ``` 103 | 104 | For Raspberry Pi 3, arm64: 105 | 106 | ``` bash 107 | edi -v project make pi3.yml 108 | ``` 109 | 110 | For Raspberry Pi 2, armhf: 111 | 112 | ``` bash 113 | edi -v project make pi2.yml 114 | ``` 115 | 116 | The resulting image can be copied to a SD card (here /dev/mmcblk0) 117 | using the following command 118 | (**Please note that everything on the SD card will be erased!**): 119 | 120 | Example for Raspberry Pi 5, arm64: 121 | 122 | ``` bash 123 | sudo umount /dev/mmcblk0p? 124 | sudo dd if=artifacts/pi5.img of=/dev/mmcblk0 bs=4M conv=fsync status=progress 125 | ``` 126 | 127 | Once you have booted the Raspberry Pi using this SD card you can 128 | access it using ssh (the access should be granted thanks to your 129 | ssh keys): 130 | 131 | ``` bash 132 | ssh pi@IP_ADDRESS 133 | ``` 134 | 135 | The password for the user _pi_ is _raspberry_ (just in case you want to 136 | execute a command using `sudo` or login via a local terminal). 137 | 138 | ### Creating a Cross Development Container 139 | 140 | A Podman image of a cross development container can be created using the 141 | following command: 142 | 143 | ``` bash 144 | edi -v project make pi-cross-dev.yml 145 | ``` 146 | 147 | distrobox can be used to transform the image into a convenient development container: 148 | 149 | ``` bash 150 | source artifacts/pi-cross-dev_manifest 151 | distrobox create --image ${podman_image} --name SOME_CONTAINER_NAME --init --unshare-all --additional-packages "systemd libpam-systemd" 152 | ``` 153 | 154 | For all the development work the container can be entered as follows: 155 | 156 | ``` bash 157 | distrobox enter SOME_CONTAINER_NAME 158 | ``` 159 | 160 | You can directly start to cross compile applications: 161 | 162 | For the Raspberry Pi 3, 4 or 5, arm64: 163 | 164 | ``` bash 165 | aarch64-linux-gnu-g++ ... 166 | ``` 167 | 168 | For the Raspberry Pi 2, armhf: 169 | 170 | ``` bash 171 | arm-linux-gnueabihf-g++ 172 | ``` 173 | 174 | ## Documenting an Artifact 175 | 176 | During the image build the documentation gets rendered to artifacts/CONFIGNAME_documentation 177 | as reStructuredText. The text files can be transformed into a nice pdf file with some 178 | additional tools that need to be installed first: 179 | 180 | ``` bash 181 | sudo apt install texlive-latex-recommended texlive-pictures texlive-latex-extra texlive-xetex latexmk 182 | ``` 183 | 184 | Then the pdf can be generated using the following commands: 185 | 186 | ``` bash 187 | cd artifacts/CONFIGNAME_documentation 188 | make PDFLATEX=xelatex latexpdf 189 | make PDFLATEX=xelatex latexpdf 190 | ``` 191 | 192 | ### More Information 193 | 194 | For more information about this setup please read the [edi documentation](https://docs.get-edi.io) and 195 | [this blog post](https://www.get-edi.io/Rootless-Creation-of-Debian-OS-and-OCI-Images/). 196 | 197 | For details about the Mender based robust update integration please refer to this 198 | [blog post](https://www.get-edi.io/Updating-a-Debian-Based-IoT-Fleet/). 199 | 200 | If you are curious about the U-Boot bootloader setup please take a look at this 201 | [blog post](https://www.get-edi.io/Booting-Debian-with-U-Boot/). 202 | 203 | For the kernel build instructions related to the Raspberry Pi 4 and 5 please check 204 | [this blog post](https://www.get-edi.io/Getting-Started-with-a-new-Embedded-System/). 205 | 206 | The WiFi setup is [documented here](docs/wifi_setup.md). 207 | 208 | A GitOps example can be found [here](https://www.get-edi.io/Surprisingly-Easy-IoT-Device-Management/). 209 | -------------------------------------------------------------------------------- /configuration/base/common.yml: -------------------------------------------------------------------------------- 1 | general: 2 | edi_required_minimal_edi_version: 1.19.0 3 | parameters: 4 | mender_device_type: generic 5 | ansible_pipelining: true 6 | ebs_bootloader_type: "u-boot" 7 | default_user_name: pi 8 | default_user_group_name: pi 9 | debian_distribution_release: trixie 10 | ansible_python_interpreter: /usr/bin/python3 11 | 12 | preprocessing_commands: 13 | 100_prerequisites: 14 | path: preprocessing_commands/prerequisites/check_prerequisites.edi 15 | output: 16 | edi_prerequisites_log: 17 | location: {{ edi_configuration_name }}_prerequisites.log 18 | type: path 19 | 200_mmdebstrap: 20 | path: preprocessing_commands/bootstrap/mmdebstrap.edi 21 | output: 22 | edi_bootstrapped_rootfs: 23 | location: {{ edi_configuration_name }}_bootstrapped-rootfs.tar 24 | type: path 25 | 26 | playbooks: 27 | 100_os_setup: 28 | path: playbooks/os_setup/main.yml 29 | parameters: 30 | create_default_user: True 31 | # password is raspberry 32 | default_user_password: "$6$UFxTVMw7t4D3xPRl$GikrlPLW3hr34zssKC1w9rP9kUoSoa1UPoGMIylT8qb3fYM2lDAe9Mvr7hl1VRjz8wR84tfEkZ6.uot.K2B/F0" 33 | install_openssh_server: True 34 | disable_ssh_password_authentication: True 35 | install_documentation: changelog 36 | translations_filter: en_translations_only 37 | base_system_sources_list_template: debian.list 38 | document_build_setup: true 39 | document_installed_packages: true 40 | ssh_host_key_backup_folder: /data/backup/ssh 41 | 42 | postprocessing_commands: 43 | 100_timestamp: 44 | path: postprocessing_commands/timestamp/timestamp.edi 45 | output: 46 | pp_timestamp: 47 | location: {{ edi_configuration_name }}_timestamp 48 | type: path 49 | 200_buildah2rootfs: 50 | path: postprocessing_commands/rootfs/buildah2rootfs.edi 51 | output: 52 | pp_rootfs_archive: 53 | location: {{ edi_configuration_name }}_configured-rootfs.tar 54 | type: path 55 | 300_rootfs2image: 56 | path: postprocessing_commands/genimage/rootfs2image.edi 57 | require_root: "fakeroot" 58 | output: 59 | pp_image: 60 | location: {{ edi_configuration_name }}.img 61 | type: path 62 | pp_partition_image: 63 | location: {{ edi_configuration_name }}_rootfs.ext4 64 | type: path 65 | parameters: 66 | hostname: raspberry 67 | 400_mender: 68 | path: postprocessing_commands/mender/image2mender.edi 69 | output: 70 | pp_mender_artifact: 71 | location: {{ edi_configuration_name }}.mender 72 | type: path 73 | 500_documentation: 74 | path: postprocessing_commands/documentation/write_doc.edi 75 | output: 76 | pp_documentation: 77 | location: {{ edi_configuration_name }}_documentation 78 | type: path 79 | parameters: 80 | author: The edi-pi Project Team 81 | 600_fully_named_artifacts: 82 | path: postprocessing_commands/fully_named_artifacts/create_full_names.edi 83 | output: 84 | pp_fully_named_artifacts: 85 | location: {{ edi_configuration_name }}_fully_named_artifacts 86 | type: path 87 | 88 | documentation_steps: 89 | 100_index: 90 | path: documentation_steps/rst/templates/index.rst.j2 91 | output: 92 | file: index.rst 93 | parameters: 94 | edi_doc_include_packages: [] 95 | toctree_items: ['setup', 'versions', 'changelog'] 96 | 200_setup: 97 | path: documentation_steps/rst/templates/setup.rst.j2 98 | output: 99 | file: setup.rst 100 | parameters: 101 | edi_doc_include_packages: [] 102 | 300_versions: 103 | output: 104 | file: versions.rst 105 | path: documentation_steps/rst/templates/versions.rst.j2 106 | 400_changelog: 107 | path: documentation_steps/rst/templates/changelog.rst.j2 108 | output: 109 | file: changelog.rst 110 | parameters: 111 | edi_doc_include_changelog: True 112 | edi_doc_changelog_baseline: 2023-06-10 00:00:00 GMT 113 | edi_doc_replacements: 114 | - pattern: '(CVE-[0-9]{4}-[0-9]{4,6})' 115 | replacement: '`\1 `_' 116 | - pattern: '(?i)[#]*(Closes:\s[#])([0-9]{6,10})' 117 | replacement: '`\1\2 `_' 118 | - pattern: '(?i)[#]*(LP:\s[#])([0-9]{6,10})' 119 | replacement: '`\1\2 `_' 120 | 121 | 122 | -------------------------------------------------------------------------------- /configuration/documentation/packages-baseline.yml: -------------------------------------------------------------------------------- 1 | - package: adduser 2 | architecture: all 3 | version: "3.118" 4 | source_package: adduser 5 | status: ii 6 | - package: apt 7 | architecture: arm64 8 | version: "1.8.2" 9 | source_package: apt 10 | status: ii 11 | - package: base-files 12 | architecture: arm64 13 | version: "10.3+deb10u2" 14 | source_package: base-files 15 | status: ii 16 | - package: base-passwd 17 | architecture: arm64 18 | version: "3.5.46" 19 | source_package: base-passwd 20 | status: ii 21 | - package: bash 22 | architecture: arm64 23 | version: "5.0-4" 24 | source_package: bash 25 | status: ii 26 | - package: bsdutils 27 | architecture: arm64 28 | version: "1:2.33.1-0.1" 29 | source_package: util-linux 30 | status: ii 31 | - package: ca-certificates 32 | architecture: all 33 | version: "20190110" 34 | source_package: ca-certificates 35 | status: ii 36 | - package: coreutils 37 | architecture: arm64 38 | version: "8.30-3" 39 | source_package: coreutils 40 | status: ii 41 | - package: cpio 42 | architecture: arm64 43 | version: "2.12+dfsg-9" 44 | source_package: cpio 45 | status: ii 46 | - package: dash 47 | architecture: arm64 48 | version: "0.5.10.2-5" 49 | source_package: dash 50 | status: ii 51 | - package: dbus 52 | architecture: arm64 53 | version: "1.12.16-1" 54 | source_package: dbus 55 | status: ii 56 | - package: debconf 57 | architecture: all 58 | version: "1.5.71" 59 | source_package: debconf 60 | status: ii 61 | - package: debian-archive-keyring 62 | architecture: all 63 | version: "2019.1" 64 | source_package: debian-archive-keyring 65 | status: ii 66 | - package: debianutils 67 | architecture: arm64 68 | version: "4.8.6.1" 69 | source_package: debianutils 70 | status: ii 71 | - package: diffutils 72 | architecture: arm64 73 | version: "1:3.7-3" 74 | source_package: diffutils 75 | status: ii 76 | - package: dirmngr 77 | architecture: arm64 78 | version: "2.2.12-1+deb10u1" 79 | source_package: gnupg2 80 | status: ii 81 | - package: distro-info-data 82 | architecture: all 83 | version: "0.41+deb10u1" 84 | source_package: distro-info-data 85 | status: ii 86 | - package: dmsetup 87 | architecture: arm64 88 | version: "2:1.02.155-3" 89 | source_package: lvm2 90 | status: ii 91 | - package: dosfstools 92 | architecture: arm64 93 | version: "4.1-2" 94 | source_package: dosfstools 95 | status: ii 96 | - package: dpkg 97 | architecture: arm64 98 | version: "1.19.7" 99 | source_package: dpkg 100 | status: ii 101 | - package: dumb-init 102 | architecture: arm64 103 | version: "1.2.2-1.1" 104 | source_package: dumb-init 105 | status: ii 106 | - package: e2fsprogs 107 | architecture: arm64 108 | version: "1.44.5-1+deb10u2" 109 | source_package: e2fsprogs 110 | status: ii 111 | - package: edi-boot-shim 112 | architecture: all 113 | version: "0.8.0+deb10" 114 | source_package: edi-boot-shim 115 | status: ii 116 | - package: fdisk 117 | architecture: arm64 118 | version: "2.33.1-0.1" 119 | source_package: util-linux 120 | status: ii 121 | - package: findutils 122 | architecture: arm64 123 | version: "4.6.0+git+20190209-2" 124 | source_package: findutils 125 | status: ii 126 | - package: firmware-brcm80211 127 | architecture: all 128 | version: "1:20190114-1+rpt4" 129 | source_package: firmware-nonfree 130 | status: ii 131 | - package: gcc-8-base 132 | architecture: arm64 133 | version: "8.3.0-6" 134 | source_package: gcc-8 135 | status: ii 136 | - package: gnupg 137 | architecture: all 138 | version: "2.2.12-1+deb10u1" 139 | source_package: gnupg2 140 | status: ii 141 | - package: gnupg-l10n 142 | architecture: all 143 | version: "2.2.12-1+deb10u1" 144 | source_package: gnupg2 145 | status: ii 146 | - package: gnupg-utils 147 | architecture: arm64 148 | version: "2.2.12-1+deb10u1" 149 | source_package: gnupg2 150 | status: ii 151 | - package: gpg 152 | architecture: arm64 153 | version: "2.2.12-1+deb10u1" 154 | source_package: gnupg2 155 | status: ii 156 | - package: gpg-agent 157 | architecture: arm64 158 | version: "2.2.12-1+deb10u1" 159 | source_package: gnupg2 160 | status: ii 161 | - package: gpg-wks-client 162 | architecture: arm64 163 | version: "2.2.12-1+deb10u1" 164 | source_package: gnupg2 165 | status: ii 166 | - package: gpg-wks-server 167 | architecture: arm64 168 | version: "2.2.12-1+deb10u1" 169 | source_package: gnupg2 170 | status: ii 171 | - package: gpgconf 172 | architecture: arm64 173 | version: "2.2.12-1+deb10u1" 174 | source_package: gnupg2 175 | status: ii 176 | - package: gpgsm 177 | architecture: arm64 178 | version: "2.2.12-1+deb10u1" 179 | source_package: gnupg2 180 | status: ii 181 | - package: gpgv 182 | architecture: arm64 183 | version: "2.2.12-1+deb10u1" 184 | source_package: gnupg2 185 | status: ii 186 | - package: grep 187 | architecture: arm64 188 | version: "3.3-1" 189 | source_package: grep 190 | status: ii 191 | - package: gzip 192 | architecture: arm64 193 | version: "1.9-3" 194 | source_package: gzip 195 | status: ii 196 | - package: haveged 197 | architecture: arm64 198 | version: "1.9.1-7" 199 | source_package: haveged 200 | status: ii 201 | - package: hostname 202 | architecture: arm64 203 | version: "3.21" 204 | source_package: hostname 205 | status: ii 206 | - package: ifupdown 207 | architecture: arm64 208 | version: "0.8.35" 209 | source_package: ifupdown 210 | status: ii 211 | - package: init-system-helpers 212 | architecture: all 213 | version: "1.56+nmu1" 214 | source_package: init-system-helpers 215 | status: ii 216 | - package: initramfs-tools 217 | architecture: all 218 | version: "0.133+deb10u1" 219 | source_package: initramfs-tools 220 | status: ii 221 | - package: initramfs-tools-core 222 | architecture: all 223 | version: "0.133+deb10u1" 224 | source_package: initramfs-tools 225 | status: ii 226 | - package: iproute2 227 | architecture: arm64 228 | version: "4.20.0-2" 229 | source_package: iproute2 230 | status: ii 231 | - package: iputils-ping 232 | architecture: arm64 233 | version: "3:20180629-2" 234 | source_package: iputils 235 | status: ii 236 | - package: isc-dhcp-client 237 | architecture: arm64 238 | version: "4.4.1-2" 239 | source_package: isc-dhcp 240 | status: ii 241 | - package: iso-codes 242 | architecture: all 243 | version: "4.2-1" 244 | source_package: iso-codes 245 | status: ii 246 | - package: klibc-utils 247 | architecture: arm64 248 | version: "2.0.6-1" 249 | source_package: klibc 250 | status: ii 251 | - package: kmod 252 | architecture: arm64 253 | version: "26-1" 254 | source_package: kmod 255 | status: ii 256 | - package: libacl1 257 | architecture: arm64 258 | version: "2.2.53-4" 259 | source_package: acl 260 | status: ii 261 | - package: libapparmor1 262 | architecture: arm64 263 | version: "2.13.2-10" 264 | source_package: apparmor 265 | status: ii 266 | - package: libapt-inst2.0 267 | architecture: arm64 268 | version: "1.8.2" 269 | source_package: apt 270 | status: ii 271 | - package: libapt-pkg5.0 272 | architecture: arm64 273 | version: "1.8.2" 274 | source_package: apt 275 | status: ii 276 | - package: libargon2-1 277 | architecture: arm64 278 | version: "0~20171227-0.2" 279 | source_package: argon2 280 | status: ii 281 | - package: libassuan0 282 | architecture: arm64 283 | version: "2.5.2-1" 284 | source_package: libassuan 285 | status: ii 286 | - package: libattr1 287 | architecture: arm64 288 | version: "1:2.4.48-4" 289 | source_package: attr 290 | status: ii 291 | - package: libaudit-common 292 | architecture: all 293 | version: "1:2.8.4-3" 294 | source_package: audit 295 | status: ii 296 | - package: libaudit1 297 | architecture: arm64 298 | version: "1:2.8.4-3" 299 | source_package: audit 300 | status: ii 301 | - package: libblkid1 302 | architecture: arm64 303 | version: "2.33.1-0.1" 304 | source_package: util-linux 305 | status: ii 306 | - package: libbsd0 307 | architecture: arm64 308 | version: "0.9.1-2" 309 | source_package: libbsd 310 | status: ii 311 | - package: libbz2-1.0 312 | architecture: arm64 313 | version: "1.0.6-9.2~deb10u1" 314 | source_package: bzip2 315 | status: ii 316 | - package: libc-bin 317 | architecture: arm64 318 | version: "2.28-10" 319 | source_package: glibc 320 | status: ii 321 | - package: libc6 322 | architecture: arm64 323 | version: "2.28-10" 324 | source_package: glibc 325 | status: ii 326 | - package: libcap-ng0 327 | architecture: arm64 328 | version: "0.7.9-2" 329 | source_package: libcap-ng 330 | status: ii 331 | - package: libcap2 332 | architecture: arm64 333 | version: "1:2.25-2" 334 | source_package: libcap2 335 | status: ii 336 | - package: libcap2-bin 337 | architecture: arm64 338 | version: "1:2.25-2" 339 | source_package: libcap2 340 | status: ii 341 | - package: libcom-err2 342 | architecture: arm64 343 | version: "1.44.5-1+deb10u2" 344 | source_package: e2fsprogs 345 | status: ii 346 | - package: libcryptsetup12 347 | architecture: arm64 348 | version: "2:2.1.0-5+deb10u2" 349 | source_package: cryptsetup 350 | status: ii 351 | - package: libdb5.3 352 | architecture: arm64 353 | version: "5.3.28+dfsg1-0.5" 354 | source_package: db5.3 355 | status: ii 356 | - package: libdbus-1-3 357 | architecture: arm64 358 | version: "1.12.16-1" 359 | source_package: dbus 360 | status: ii 361 | - package: libdebconfclient0 362 | architecture: arm64 363 | version: "0.249" 364 | source_package: cdebconf 365 | status: ii 366 | - package: libdevmapper1.02.1 367 | architecture: arm64 368 | version: "2:1.02.155-3" 369 | source_package: lvm2 370 | status: ii 371 | - package: libdns-export1104 372 | architecture: arm64 373 | version: "1:9.11.5.P4+dfsg-5.1" 374 | source_package: bind9 375 | status: ii 376 | - package: libedit2 377 | architecture: arm64 378 | version: "3.1-20181209-1" 379 | source_package: libedit 380 | status: ii 381 | - package: libelf1 382 | architecture: arm64 383 | version: "0.176-1.1" 384 | source_package: elfutils 385 | status: ii 386 | - package: libexpat1 387 | architecture: arm64 388 | version: "2.2.6-2+deb10u1" 389 | source_package: expat 390 | status: ii 391 | - package: libext2fs2 392 | architecture: arm64 393 | version: "1.44.5-1+deb10u2" 394 | source_package: e2fsprogs 395 | status: ii 396 | - package: libfdisk1 397 | architecture: arm64 398 | version: "2.33.1-0.1" 399 | source_package: util-linux 400 | status: ii 401 | - package: libffi6 402 | architecture: arm64 403 | version: "3.2.1-9" 404 | source_package: libffi 405 | status: ii 406 | - package: libgcc1 407 | architecture: arm64 408 | version: "1:8.3.0-6" 409 | source_package: gcc-8 410 | status: ii 411 | - package: libgcrypt20 412 | architecture: arm64 413 | version: "1.8.4-5" 414 | source_package: libgcrypt20 415 | status: ii 416 | - package: libgmp10 417 | architecture: arm64 418 | version: "2:6.1.2+dfsg-4" 419 | source_package: gmp 420 | status: ii 421 | - package: libgnutls30 422 | architecture: arm64 423 | version: "3.6.7-4" 424 | source_package: gnutls28 425 | status: ii 426 | - package: libgpg-error0 427 | architecture: arm64 428 | version: "1.35-1" 429 | source_package: libgpg-error 430 | status: ii 431 | - package: libgssapi-krb5-2 432 | architecture: arm64 433 | version: "1.17-3" 434 | source_package: krb5 435 | status: ii 436 | - package: libhavege1 437 | architecture: arm64 438 | version: "1.9.1-7" 439 | source_package: haveged 440 | status: ii 441 | - package: libhogweed4 442 | architecture: arm64 443 | version: "3.4.1-1" 444 | source_package: nettle 445 | status: ii 446 | - package: libidn11 447 | architecture: arm64 448 | version: "1.33-2.2" 449 | source_package: libidn 450 | status: ii 451 | - package: libidn2-0 452 | architecture: arm64 453 | version: "2.0.5-1" 454 | source_package: libidn2 455 | status: ii 456 | - package: libip4tc0 457 | architecture: arm64 458 | version: "1.8.2-4" 459 | source_package: iptables 460 | status: ii 461 | - package: libisc-export1100 462 | architecture: arm64 463 | version: "1:9.11.5.P4+dfsg-5.1" 464 | source_package: bind9 465 | status: ii 466 | - package: libiw30 467 | architecture: arm64 468 | version: "30~pre9-13" 469 | source_package: wireless-tools 470 | status: ii 471 | - package: libjson-c3 472 | architecture: arm64 473 | version: "0.12.1+ds-2" 474 | source_package: json-c 475 | status: ii 476 | - package: libk5crypto3 477 | architecture: arm64 478 | version: "1.17-3" 479 | source_package: krb5 480 | status: ii 481 | - package: libkeyutils1 482 | architecture: arm64 483 | version: "1.6-6" 484 | source_package: keyutils 485 | status: ii 486 | - package: libklibc 487 | architecture: arm64 488 | version: "2.0.6-1" 489 | source_package: klibc 490 | status: ii 491 | - package: libkmod2 492 | architecture: arm64 493 | version: "26-1" 494 | source_package: kmod 495 | status: ii 496 | - package: libkrb5-3 497 | architecture: arm64 498 | version: "1.17-3" 499 | source_package: krb5 500 | status: ii 501 | - package: libkrb5support0 502 | architecture: arm64 503 | version: "1.17-3" 504 | source_package: krb5 505 | status: ii 506 | - package: libksba8 507 | architecture: arm64 508 | version: "1.3.5-2" 509 | source_package: libksba 510 | status: ii 511 | - package: libldap-2.4-2 512 | architecture: arm64 513 | version: "2.4.47+dfsg-3+deb10u1" 514 | source_package: openldap 515 | status: ii 516 | - package: libldap-common 517 | architecture: all 518 | version: "2.4.47+dfsg-3+deb10u1" 519 | source_package: openldap 520 | status: ii 521 | - package: liblz4-1 522 | architecture: arm64 523 | version: "1.8.3-1" 524 | source_package: lz4 525 | status: ii 526 | - package: liblzma5 527 | architecture: arm64 528 | version: "5.2.4-1" 529 | source_package: xz-utils 530 | status: ii 531 | - package: libmnl0 532 | architecture: arm64 533 | version: "1.0.4-2" 534 | source_package: libmnl 535 | status: ii 536 | - package: libmount1 537 | architecture: arm64 538 | version: "2.33.1-0.1" 539 | source_package: util-linux 540 | status: ii 541 | - package: libmpdec2 542 | architecture: arm64 543 | version: "2.4.2-2" 544 | source_package: mpdecimal 545 | status: ii 546 | - package: libncurses6 547 | architecture: arm64 548 | version: "6.1+20181013-2+deb10u2" 549 | source_package: ncurses 550 | status: ii 551 | - package: libncursesw6 552 | architecture: arm64 553 | version: "6.1+20181013-2+deb10u2" 554 | source_package: ncurses 555 | status: ii 556 | - package: libnettle6 557 | architecture: arm64 558 | version: "3.4.1-1" 559 | source_package: nettle 560 | status: ii 561 | - package: libnl-3-200 562 | architecture: arm64 563 | version: "3.4.0-1" 564 | source_package: libnl3 565 | status: ii 566 | - package: libnl-genl-3-200 567 | architecture: arm64 568 | version: "3.4.0-1" 569 | source_package: libnl3 570 | status: ii 571 | - package: libnl-route-3-200 572 | architecture: arm64 573 | version: "3.4.0-1" 574 | source_package: libnl3 575 | status: ii 576 | - package: libnpth0 577 | architecture: arm64 578 | version: "1.6-1" 579 | source_package: npth 580 | status: ii 581 | - package: libp11-kit0 582 | architecture: arm64 583 | version: "0.23.15-2" 584 | source_package: p11-kit 585 | status: ii 586 | - package: libpam-modules 587 | architecture: arm64 588 | version: "1.3.1-5" 589 | source_package: pam 590 | status: ii 591 | - package: libpam-modules-bin 592 | architecture: arm64 593 | version: "1.3.1-5" 594 | source_package: pam 595 | status: ii 596 | - package: libpam-runtime 597 | architecture: all 598 | version: "1.3.1-5" 599 | source_package: pam 600 | status: ii 601 | - package: libpam0g 602 | architecture: arm64 603 | version: "1.3.1-5" 604 | source_package: pam 605 | status: ii 606 | - package: libparted2 607 | architecture: arm64 608 | version: "3.2-25" 609 | source_package: parted 610 | status: ii 611 | - package: libpcre3 612 | architecture: arm64 613 | version: "2:8.39-12" 614 | source_package: pcre3 615 | status: ii 616 | - package: libpcsclite1 617 | architecture: arm64 618 | version: "1.8.24-1" 619 | source_package: pcsc-lite 620 | status: ii 621 | - package: libprocps7 622 | architecture: arm64 623 | version: "2:3.3.15-2" 624 | source_package: procps 625 | status: ii 626 | - package: libpython-stdlib 627 | architecture: arm64 628 | version: "2.7.16-1" 629 | source_package: python-defaults 630 | status: ii 631 | - package: libpython2-stdlib 632 | architecture: arm64 633 | version: "2.7.16-1" 634 | source_package: python-defaults 635 | status: ii 636 | - package: libpython2.7-minimal 637 | architecture: arm64 638 | version: "2.7.16-2+deb10u1" 639 | source_package: python2.7 640 | status: ii 641 | - package: libpython2.7-stdlib 642 | architecture: arm64 643 | version: "2.7.16-2+deb10u1" 644 | source_package: python2.7 645 | status: ii 646 | - package: libpython3-stdlib 647 | architecture: arm64 648 | version: "3.7.3-1" 649 | source_package: python3-defaults 650 | status: ii 651 | - package: libpython3.7-minimal 652 | architecture: arm64 653 | version: "3.7.3-2" 654 | source_package: python3.7 655 | status: ii 656 | - package: libpython3.7-stdlib 657 | architecture: arm64 658 | version: "3.7.3-2" 659 | source_package: python3.7 660 | status: ii 661 | - package: libreadline7 662 | architecture: arm64 663 | version: "7.0-5" 664 | source_package: readline 665 | status: ii 666 | - package: libsasl2-2 667 | architecture: arm64 668 | version: "2.1.27+dfsg-1" 669 | source_package: cyrus-sasl2 670 | status: ii 671 | - package: libsasl2-modules-db 672 | architecture: arm64 673 | version: "2.1.27+dfsg-1" 674 | source_package: cyrus-sasl2 675 | status: ii 676 | - package: libseccomp2 677 | architecture: arm64 678 | version: "2.3.3-4" 679 | source_package: libseccomp 680 | status: ii 681 | - package: libselinux1 682 | architecture: arm64 683 | version: "2.8-1+b1" 684 | source_package: libselinux 685 | status: ii 686 | - package: libsemanage-common 687 | architecture: all 688 | version: "2.8-2" 689 | source_package: libsemanage 690 | status: ii 691 | - package: libsemanage1 692 | architecture: arm64 693 | version: "2.8-2" 694 | source_package: libsemanage 695 | status: ii 696 | - package: libsepol1 697 | architecture: arm64 698 | version: "2.8-1" 699 | source_package: libsepol 700 | status: ii 701 | - package: libsmartcols1 702 | architecture: arm64 703 | version: "2.33.1-0.1" 704 | source_package: util-linux 705 | status: ii 706 | - package: libsqlite3-0 707 | architecture: arm64 708 | version: "3.27.2-3" 709 | source_package: sqlite3 710 | status: ii 711 | - package: libss2 712 | architecture: arm64 713 | version: "1.44.5-1+deb10u2" 714 | source_package: e2fsprogs 715 | status: ii 716 | - package: libssl1.1 717 | architecture: arm64 718 | version: "1.1.1d-0+deb10u2" 719 | source_package: openssl 720 | status: ii 721 | - package: libstdc++6 722 | architecture: arm64 723 | version: "8.3.0-6" 724 | source_package: gcc-8 725 | status: ii 726 | - package: libsystemd0 727 | architecture: arm64 728 | version: "241-7~deb10u2" 729 | source_package: systemd 730 | status: ii 731 | - package: libtasn1-6 732 | architecture: arm64 733 | version: "4.13-3" 734 | source_package: libtasn1-6 735 | status: ii 736 | - package: libtinfo6 737 | architecture: arm64 738 | version: "6.1+20181013-2+deb10u2" 739 | source_package: ncurses 740 | status: ii 741 | - package: libudev1 742 | architecture: arm64 743 | version: "241-7~deb10u2" 744 | source_package: systemd 745 | status: ii 746 | - package: libunistring2 747 | architecture: arm64 748 | version: "0.9.10-1" 749 | source_package: libunistring 750 | status: ii 751 | - package: libuuid1 752 | architecture: arm64 753 | version: "2.33.1-0.1" 754 | source_package: util-linux 755 | status: ii 756 | - package: libwrap0 757 | architecture: arm64 758 | version: "7.6.q-28" 759 | source_package: tcp-wrappers 760 | status: ii 761 | - package: libxtables12 762 | architecture: arm64 763 | version: "1.8.2-4" 764 | source_package: iptables 765 | status: ii 766 | - package: libzstd1 767 | architecture: arm64 768 | version: "1.3.8+dfsg-3" 769 | source_package: libzstd 770 | status: ii 771 | - package: linux-base 772 | architecture: all 773 | version: "4.6" 774 | source_package: linux-base 775 | status: ii 776 | - package: linux-image-4.19.93-v8+ 777 | architecture: arm64 778 | version: "4.19.93-v8+-1" 779 | source_package: linux-4.19.93-v8+ 780 | status: ii 781 | - package: login 782 | architecture: arm64 783 | version: "1:4.5-1.1" 784 | source_package: shadow 785 | status: ii 786 | - package: lsb-base 787 | architecture: all 788 | version: "10.2019051400" 789 | source_package: lsb 790 | status: ii 791 | - package: lsb-release 792 | architecture: all 793 | version: "10.2019051400" 794 | source_package: lsb 795 | status: ii 796 | - package: mawk 797 | architecture: arm64 798 | version: "1.3.3-17+b3" 799 | source_package: mawk 800 | status: ii 801 | - package: mender-client 802 | architecture: arm64 803 | version: "1.7.0-4+b12" 804 | source_package: mender-client 805 | status: ii 806 | - package: mime-support 807 | architecture: all 808 | version: "3.62" 809 | source_package: mime-support 810 | status: ii 811 | - package: mount 812 | architecture: arm64 813 | version: "2.33.1-0.1" 814 | source_package: util-linux 815 | status: ii 816 | - package: ncurses-base 817 | architecture: all 818 | version: "6.1+20181013-2+deb10u2" 819 | source_package: ncurses 820 | status: ii 821 | - package: ncurses-bin 822 | architecture: arm64 823 | version: "6.1+20181013-2+deb10u2" 824 | source_package: ncurses 825 | status: ii 826 | - package: net-tools 827 | architecture: arm64 828 | version: "1.60+git20180626.aebd88e-1" 829 | source_package: net-tools 830 | status: ii 831 | - package: netbase 832 | architecture: all 833 | version: "5.6" 834 | source_package: netbase 835 | status: ii 836 | - package: openssh-client 837 | architecture: arm64 838 | version: "1:7.9p1-10+deb10u1" 839 | source_package: openssh 840 | status: ii 841 | - package: openssh-server 842 | architecture: arm64 843 | version: "1:7.9p1-10+deb10u1" 844 | source_package: openssh 845 | status: ii 846 | - package: openssh-sftp-server 847 | architecture: arm64 848 | version: "1:7.9p1-10+deb10u1" 849 | source_package: openssh 850 | status: ii 851 | - package: openssl 852 | architecture: arm64 853 | version: "1.1.1d-0+deb10u2" 854 | source_package: openssl 855 | status: ii 856 | - package: parted 857 | architecture: arm64 858 | version: "3.2-25" 859 | source_package: parted 860 | status: ii 861 | - package: passwd 862 | architecture: arm64 863 | version: "1:4.5-1.1" 864 | source_package: shadow 865 | status: ii 866 | - package: perl-base 867 | architecture: arm64 868 | version: "5.28.1-6" 869 | source_package: perl 870 | status: ii 871 | - package: pinentry-curses 872 | architecture: arm64 873 | version: "1.1.0-2" 874 | source_package: pinentry 875 | status: ii 876 | - package: procps 877 | architecture: arm64 878 | version: "2:3.3.15-2" 879 | source_package: procps 880 | status: ii 881 | - package: python 882 | architecture: arm64 883 | version: "2.7.16-1" 884 | source_package: python-defaults 885 | status: ii 886 | - package: python-apt 887 | architecture: arm64 888 | version: "1.8.4" 889 | source_package: python-apt 890 | status: ii 891 | - package: python-apt-common 892 | architecture: all 893 | version: "1.8.4" 894 | source_package: python-apt 895 | status: ii 896 | - package: python-minimal 897 | architecture: arm64 898 | version: "2.7.16-1" 899 | source_package: python-defaults 900 | status: ii 901 | - package: python2 902 | architecture: arm64 903 | version: "2.7.16-1" 904 | source_package: python-defaults 905 | status: ii 906 | - package: python2-minimal 907 | architecture: arm64 908 | version: "2.7.16-1" 909 | source_package: python-defaults 910 | status: ii 911 | - package: python2.7 912 | architecture: arm64 913 | version: "2.7.16-2+deb10u1" 914 | source_package: python2.7 915 | status: ii 916 | - package: python2.7-minimal 917 | architecture: arm64 918 | version: "2.7.16-2+deb10u1" 919 | source_package: python2.7 920 | status: ii 921 | - package: python3 922 | architecture: arm64 923 | version: "3.7.3-1" 924 | source_package: python3-defaults 925 | status: ii 926 | - package: python3-minimal 927 | architecture: arm64 928 | version: "3.7.3-1" 929 | source_package: python3-defaults 930 | status: ii 931 | - package: python3.7 932 | architecture: arm64 933 | version: "3.7.3-2" 934 | source_package: python3.7 935 | status: ii 936 | - package: python3.7-minimal 937 | architecture: arm64 938 | version: "3.7.3-2" 939 | source_package: python3.7 940 | status: ii 941 | - package: readline-common 942 | architecture: all 943 | version: "7.0-5" 944 | source_package: readline 945 | status: ii 946 | - package: resolvconf 947 | architecture: all 948 | version: "1.79" 949 | source_package: resolvconf 950 | status: ii 951 | - package: sed 952 | architecture: arm64 953 | version: "4.7-1" 954 | source_package: sed 955 | status: ii 956 | - package: sensible-utils 957 | architecture: all 958 | version: "0.0.12" 959 | source_package: sensible-utils 960 | status: ii 961 | - package: sudo 962 | architecture: arm64 963 | version: "1.8.27-1+deb10u1" 964 | source_package: sudo 965 | status: ii 966 | - package: systemd 967 | architecture: arm64 968 | version: "241-7~deb10u2" 969 | source_package: systemd 970 | status: ii 971 | - package: systemd-sysv 972 | architecture: arm64 973 | version: "241-7~deb10u2" 974 | source_package: systemd 975 | status: ii 976 | - package: sysvinit-utils 977 | architecture: arm64 978 | version: "2.93-8" 979 | source_package: sysvinit 980 | status: ii 981 | - package: tar 982 | architecture: arm64 983 | version: "1.30+dfsg-6" 984 | source_package: tar 985 | status: ii 986 | - package: tzdata 987 | architecture: all 988 | version: "2019c-0+deb10u1" 989 | source_package: tzdata 990 | status: ii 991 | - package: u-boot-tools 992 | architecture: arm64 993 | version: "2019.01+dfsg-7" 994 | source_package: u-boot 995 | status: ii 996 | - package: ucf 997 | architecture: all 998 | version: "3.0038+nmu1" 999 | source_package: ucf 1000 | status: ii 1001 | - package: udev 1002 | architecture: arm64 1003 | version: "241-7~deb10u2" 1004 | source_package: systemd 1005 | status: ii 1006 | - package: util-linux 1007 | architecture: arm64 1008 | version: "2.33.1-0.1" 1009 | source_package: util-linux 1010 | status: ii 1011 | - package: wireless-tools 1012 | architecture: arm64 1013 | version: "30~pre9-13" 1014 | source_package: wireless-tools 1015 | status: ii 1016 | - package: wpasupplicant 1017 | architecture: arm64 1018 | version: "2:2.7+git20190128+0c1e29f-6+deb10u1" 1019 | source_package: wpa 1020 | status: ii 1021 | - package: xz-utils 1022 | architecture: arm64 1023 | version: "5.2.4-1" 1024 | source_package: xz-utils 1025 | status: ii 1026 | - package: zlib1g 1027 | architecture: arm64 1028 | version: "1:1.2.11.dfsg-1" 1029 | source_package: zlib 1030 | status: ii 1031 | -------------------------------------------------------------------------------- /configuration/mender/identity/mender-device-identity: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This identity script returns the MAC address of {{ 'end0' if mender_device_type in ['pi4-v3', 'pi5-v3'] else 'eth0' }} as the device identity. 4 | 5 | set -ue 6 | 7 | MAC_FILE=/sys/class/net/{{ 'end0' if mender_device_type in ['pi4-v3', 'pi5-v3'] else 'eth0' }}/address 8 | 9 | if [ ! -f "${MAC_FILE}" ] 10 | then 11 | >&2 echo "Error: ${MAC_FILE} not found!" 12 | exit 1 13 | fi 14 | 15 | echo "mac=$(cat ${MAC_FILE})" 16 | -------------------------------------------------------------------------------- /configuration/mender/inventory/mender-inventory-bootloader-integration: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Tries to determine which type of bootloader integration has been used for the 4 | # running platform. 5 | 6 | if [ -d /boot/efi/EFI/BOOT/mender_grubenv1 ]; then 7 | case "$(uname -m)" in 8 | arm*|aarch*) 9 | echo mender_bootloader_integration=uboot_uefi_grub 10 | ;; 11 | *86*) 12 | echo mender_bootloader_integration=uefi_grub 13 | ;; 14 | *) 15 | echo mender_bootloader_integration=unknown_uefi_grub 16 | ;; 17 | esac 18 | elif [ -d /boot/grub/mender_grubenv1 ]; then 19 | case "$(uname -m)" in 20 | *86*) 21 | echo mender_bootloader_integration=bios_grub 22 | ;; 23 | *) 24 | echo mender_bootloader_integration=unknown_grub 25 | ;; 26 | esac 27 | elif [ -e /etc/fw_env.config ]; then 28 | echo mender_bootloader_integration=uboot 29 | elif [ -e /usr/share/mender/integration/pi-uboot ]; then 30 | echo mender_bootloader_integration=raspberry-pi 31 | else 32 | echo mender_bootloader_integration=unknown 33 | fi 34 | exit 0 35 | -------------------------------------------------------------------------------- /configuration/mender/mender.yml: -------------------------------------------------------------------------------- 1 | --- 2 | mender_inventory_poll_interval_seconds: 600 3 | mender_retry_poll_interval_seconds: 30 4 | mender_server_url: https://hosted.mender.io 5 | mender_tenant_token: "" 6 | mender_update_poll_interval_seconds: 60 7 | -------------------------------------------------------------------------------- /configuration/overlay/pi-cross-dev.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | edi_bootstrap_architecture: {{ edi_host_architecture }} 4 | 5 | playbooks: 6 | 100_os_setup: 7 | parameters: 8 | install_openssh_server: False 9 | authorize_current_user: False 10 | install_documentation: full 11 | translations_filter: "" 12 | target_is_bare_metal: False 13 | install_development_tools: True 14 | install_cross_development_tools: True 15 | cross_development_tools: 16 | - dpkg-cross 17 | - pkg-config 18 | - qemu-user-static 19 | - wget 20 | foreign_base_libraries: 21 | - libc6 22 | - libc6-dev 23 | - libc-dev 24 | - libglib2.0-dev 25 | - liblzma-dev 26 | - libmount-dev 27 | - libssl-dev 28 | - libstdc++6 29 | - linux-libc-dev 30 | 31 | postprocessing_commands: 32 | 100_timestamp: 33 | skip: True 34 | 200_buildah2rootfs: 35 | skip: True 36 | 200_buildah2image: 37 | path: postprocessing_commands/container_image/buildah2image.edi 38 | output: 39 | pp_podman_image_manifest: 40 | location: {{ edi_configuration_name }}_manifest 41 | type: path 42 | pp_podman_image: 43 | location: {{ edi_configuration_name }}-{{ edi_project_directory_hash }}:latest 44 | type: podman-image 45 | 300_rootfs2image: 46 | skip: True 47 | 400_mender: 48 | skip: True 49 | 500_documentation: 50 | skip: True 51 | 600_fully_named_artifacts: 52 | skip: True 53 | -------------------------------------------------------------------------------- /configuration/overlay/pi2-gitops.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | mender_device_type: pi2 4 | edi_bootstrap_architecture: armhf 5 | 6 | playbooks: 7 | 100_os_setup: 8 | parameters: 9 | kernel_image: linux-image-armmp-lpae 10 | enable_gitops: True 11 | -------------------------------------------------------------------------------- /configuration/overlay/pi2.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | mender_device_type: pi2 4 | edi_bootstrap_architecture: armhf 5 | 6 | playbooks: 7 | 100_os_setup: 8 | parameters: 9 | kernel_image: linux-image-armmp-lpae 10 | -------------------------------------------------------------------------------- /configuration/overlay/pi3-gitops.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | mender_device_type: pi3-v3 4 | ebs_bootloader_type: "raspberry-pi" 5 | edi_bootstrap_architecture: arm64 6 | qemu_emulated_cpu: cortex-a57 7 | 8 | playbooks: 9 | 100_os_setup: 10 | parameters: 11 | ebs_template: boot.spec.rpi3.${DEBIAN_ARCHITECTURE} 12 | ebs_bootloader_directory: "/boot/image-kernel" 13 | kernel_image: linux-image-6.6.51-v8+ 14 | enable_gitops: True 15 | -------------------------------------------------------------------------------- /configuration/overlay/pi3.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | mender_device_type: pi3-v3 4 | ebs_bootloader_type: "raspberry-pi" 5 | edi_bootstrap_architecture: arm64 6 | qemu_emulated_cpu: cortex-a57 7 | 8 | playbooks: 9 | 100_os_setup: 10 | parameters: 11 | ebs_template: boot.spec.rpi3.${DEBIAN_ARCHITECTURE} 12 | ebs_bootloader_directory: "/boot/image-kernel" 13 | kernel_image: linux-image-6.6.51-v8+ 14 | 15 | -------------------------------------------------------------------------------- /configuration/overlay/pi4-gitops.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | mender_device_type: pi4-v3 4 | ebs_bootloader_type: "raspberry-pi" 5 | edi_bootstrap_architecture: arm64 6 | qemu_emulated_cpu: cortex-a57 7 | 8 | playbooks: 9 | 100_os_setup: 10 | parameters: 11 | ebs_template: boot.spec.rpi4.${DEBIAN_ARCHITECTURE} 12 | ebs_bootloader_directory: "/boot/image-kernel" 13 | kernel_image: linux-image-6.6.51-v8+ 14 | enable_gitops: True 15 | -------------------------------------------------------------------------------- /configuration/overlay/pi4.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | mender_device_type: pi4-v3 4 | ebs_bootloader_type: "raspberry-pi" 5 | edi_bootstrap_architecture: arm64 6 | qemu_emulated_cpu: cortex-a57 7 | 8 | playbooks: 9 | 100_os_setup: 10 | parameters: 11 | ebs_template: boot.spec.rpi4.${DEBIAN_ARCHITECTURE} 12 | ebs_bootloader_directory: "/boot/image-kernel" 13 | kernel_image: linux-image-6.6.51-v8+ 14 | 15 | -------------------------------------------------------------------------------- /configuration/overlay/pi5-gitops.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | mender_device_type: pi5-v3 4 | ebs_bootloader_type: "raspberry-pi" 5 | edi_bootstrap_architecture: arm64 6 | qemu_emulated_cpu: cortex-a57 7 | 8 | playbooks: 9 | 100_os_setup: 10 | parameters: 11 | ebs_template: boot.spec.rpi5.${DEBIAN_ARCHITECTURE} 12 | ebs_bootloader_directory: "/boot/image-kernel" 13 | kernel_image: linux-image-6.6.51-v8-16k+ 14 | enable_gitops: True 15 | -------------------------------------------------------------------------------- /configuration/overlay/pi5.global.yml: -------------------------------------------------------------------------------- 1 | general: 2 | parameters: 3 | mender_device_type: pi5-v3 4 | ebs_bootloader_type: "raspberry-pi" 5 | edi_bootstrap_architecture: arm64 6 | qemu_emulated_cpu: cortex-a57 7 | 8 | playbooks: 9 | 100_os_setup: 10 | parameters: 11 | ebs_template: boot.spec.rpi5.${DEBIAN_ARCHITECTURE} 12 | ebs_bootloader_directory: "/boot/image-kernel" 13 | kernel_image: linux-image-6.6.51-v8-16k+ 14 | -------------------------------------------------------------------------------- /docs/kernel_build.md: -------------------------------------------------------------------------------- 1 | # Kernel Build Instructions 2 | 3 | The kernel build for the Raspberry Pi 4 and 5 is documented 4 | [here](https://www.get-edi.io/Getting-Started-with-a-new-Embedded-System/#linux-kernel) and gets automatically done by 5 | [this workflow](https://github.com/lueschem/edi-ci-public/blob/main/.github/workflows/kernel-build-rpi.yml). 6 | The Pi 2 and Pi 3 kernels are standard Debian kernels. 7 | -------------------------------------------------------------------------------- /docs/wifi_setup.md: -------------------------------------------------------------------------------- 1 | # WiFi Setup 2 | 3 | As the SSID and password for the WiFi connection are usually unknown during the image build, the WiFi interface (wlan0) 4 | is initially not configured. 5 | 6 | ## Initial Configuration 7 | 8 | It is recommended to configure the WiFi interface using NetworkManager. Please replace 9 | "SSID" and "PASSWORD" as required by your local wireless LAN setup and replace "CONNECTION-NAME" with 10 | a meaningful name: 11 | 12 | ``` 13 | sudo nmcli radio wifi on 14 | sudo nmcli dev wifi con "SSID" password "PASSWORD" name "CONNECTION-NAME" 15 | ``` 16 | 17 | ## Configuration Handling During a Mender Upgrade 18 | 19 | As the gateway might only be connected through WiFi it is essential that the WiFi connection gets re-established 20 | immediately after the OS upgrade. For this reason the NetworkManager connections get backed up to 21 | `/data/backup/NetworkManager` during a Mender based OS upgrade. The new OS image will then re-apply this 22 | NetworkManager connections. 23 | -------------------------------------------------------------------------------- /pi-cross-dev.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /pi2-gitops.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /pi2.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /pi3-gitops.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /pi3.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /pi4-gitops.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /pi4.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /pi5-gitops.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /pi5.yml: -------------------------------------------------------------------------------- 1 | configuration/base/common.yml -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/collections/ansible_collections: -------------------------------------------------------------------------------- 1 | ../../../../submodules/ansible_collections/ -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | vars: 4 | apply_proxy_settings: True 5 | create_default_user: False 6 | install_openssh_server: False 7 | disable_ssh_password_authentication: True 8 | authorize_current_user: True 9 | ssh_pub_key_directory: '{{ edi_project_directory }}/ssh_pub_keys' 10 | install_documentation: full 11 | translations_filter: "" 12 | base_system_sources_list_template: "" 13 | kernel_image: linux-image-arm64 14 | ebs_template: boot.cmd.rpi.${DEBIAN_ARCHITECTURE}.multiboot 15 | ebs_bootloader_directory: "/boot" 16 | ebs_bootloader_type: "u-boot" 17 | mender_device_type: ToBeOverwrittenInConfigurationOverlay 18 | enable_gitops: False 19 | gitops_user_name: gitops 20 | gitops_user_group_name: gitops 21 | target_is_bare_metal: True 22 | install_development_tools: False 23 | install_cross_development_tools: False 24 | cross_architectures: 25 | - amd64 26 | - arm64 27 | - armhf 28 | regenerate_openssh_server_keys: True 29 | # revert proxy settings 30 | cleanup_proxy_settings: True 31 | document_build_setup: False 32 | document_installed_packages: False 33 | package_baseline_source_file: "{{ edi_project_directory }}/configuration/documentation/packages-baseline.yml" 34 | qemu_emulated_cpu: max 35 | environment: 36 | QEMU_CPU: "{{ qemu_emulated_cpu }}" 37 | roles: 38 | - role: get_edi_io.debian_setup.proxy_settings 39 | become: True 40 | become_user: root 41 | when: apply_proxy_settings 42 | - role: get_edi_io.debian_setup.apt_setup 43 | become: True 44 | become_user: root 45 | - role: get_edi_io.debian_setup.default_user 46 | become: True 47 | become_user: root 48 | when: create_default_user 49 | - role: get_edi_io.debian_setup.openssh_server 50 | become: True 51 | become_user: root 52 | when: install_openssh_server 53 | - role: repositories 54 | become: True 55 | become_user: root 56 | - role: bootloader 57 | become: True 58 | become_user: root 59 | when: target_is_bare_metal 60 | - role: essential_bare_metal_packages 61 | become: True 62 | become_user: root 63 | when: target_is_bare_metal 64 | - role: mender 65 | become: True 66 | become_user: root 67 | when: target_is_bare_metal 68 | - role: get_edi_io.debian_setup.gitops_user 69 | become: True 70 | become_user: root 71 | when: enable_gitops 72 | - role: get_edi_io.debian_setup.gitops_tools 73 | become: True 74 | become_user: root 75 | when: enable_gitops 76 | - role: get_edi_io.debian_setup.multiarch_support 77 | become: True 78 | become_user: root 79 | when: install_cross_development_tools 80 | - role: get_edi_io.debian_setup.development_tools 81 | become: True 82 | become_user: root 83 | when: install_development_tools or install_cross_development_tools 84 | - role: get_edi_io.debian_setup.openssh_server_keys 85 | become: True 86 | become_user: root 87 | when: regenerate_openssh_server_keys 88 | - role: get_edi_io.debian_setup.apt_cleanup 89 | become: True 90 | become_user: root 91 | - role: get_edi_io.debian_setup.proxy_settings 92 | become: True 93 | become_user: root 94 | vars: 95 | target_http_proxy: "" 96 | target_https_proxy: "" 97 | target_ftp_proxy: "" 98 | target_socks_proxy: "" 99 | target_no_proxy: "" 100 | when: cleanup_proxy_settings 101 | - role: get_edi_io.debian_setup.replace_temp_hostname 102 | become: True 103 | become_user: root 104 | - role: get_edi_io.debian_setup.document_artifact 105 | become: True 106 | become_user: root 107 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | uboot_env_size: '0x4000' 3 | bootloader_location: /boot/firmware 4 | bootloader_image_location: /boot/image-firmware 5 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/boot.scr.txt: -------------------------------------------------------------------------------- 1 | boot_scr_filesize=${filesize} 2 | 3 | # constant values 4 | setenv mender_boot_part_A 3 5 | setenv mender_boot_part_hex_A 3 6 | setenv mender_boot_part_B 4 7 | setenv mender_boot_part_hex_B 4 8 | setenv bootlimit 1 9 | 10 | # initialize and store variables on first boot 11 | if test "${edi_first_boot_done}" != "true" 12 | then 13 | echo "Going to write environment on first boot!" 14 | setenv bootcount 0 15 | setenv upgrade_available 0 16 | setenv mender_boot_part ${mender_boot_part_A} 17 | setenv mender_boot_part_hex ${mender_boot_part_hex_A} 18 | setenv edi_first_boot_done true 19 | saveenv 20 | fi 21 | 22 | if test ${upgrade_available} = 1 23 | then 24 | # mender will reset bootcount within EnableUpdatedPartition 25 | setexpr bootcount ${bootcount} + 1 26 | saveenv 27 | else 28 | setenv bootcount 0 29 | fi 30 | 31 | if test ${bootcount} -gt ${bootlimit} 32 | then 33 | echo "Switching back to previous setup due to hitting bootlimit!" 34 | if test ${mender_boot_part} = ${mender_boot_part_A} 35 | then 36 | setenv mender_boot_part ${mender_boot_part_B} 37 | setenv mender_boot_part_hex ${mender_boot_part_hex_B} 38 | else 39 | setenv mender_boot_part ${mender_boot_part_A} 40 | setenv mender_boot_part_hex ${mender_boot_part_hex_A} 41 | fi 42 | setenv upgrade_available 0 43 | saveenv 44 | fi 45 | 46 | setexpr secondary_scriptaddr ${scriptaddr} + ${boot_scr_filesize} 47 | 48 | setenv edi_mmc_device 0:${mender_boot_part_hex} 49 | setenv edi_root_device /dev/mmcblk0p${mender_boot_part} 50 | 51 | if ext4load mmc ${edi_mmc_device} ${secondary_scriptaddr} /boot/boot.scr 52 | then 53 | echo "Successfully loaded secondary boot script." 54 | else 55 | echo "Trying to reset an environment setup that does not match the current installation!" 56 | setenv edi_first_boot_done false 57 | saveenv 58 | # avoid busy reboot loop 59 | sleep 60 60 | reset 61 | fi 62 | 63 | source ${secondary_scriptaddr} 64 | 65 | if test ${upgrade_available} = 1 66 | then 67 | reset 68 | fi 69 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/cmdline.txt.u-boot: -------------------------------------------------------------------------------- 1 | dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/edi_root_device rw rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait 2 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/config.txt.u-boot.arm64: -------------------------------------------------------------------------------- 1 | # Switch the CPU from ARMv7 into ARMv8 (aarch64) mode 2 | arm_64bit=1 3 | 4 | enable_uart=1 5 | disable_overscan=1 6 | 7 | kernel=u-boot.bin 8 | 9 | device_tree_address=0x2600000 10 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/config.txt.u-boot.armhf: -------------------------------------------------------------------------------- 1 | enable_uart=1 2 | disable_overscan=1 3 | 4 | kernel=u-boot.bin 5 | 6 | device_tree_address=0x2600000 7 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/generate-archives: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Small helper utility that creates Broadcom Raspberry Pi 4 | # and u-boot bootloader archives. 5 | 6 | set -o errexit 7 | set -o nounset 8 | set -o pipefail 9 | 10 | echo_usage() 11 | { 12 | echo "Usage: generate-archives BOOTLOADER_TYPE VERSION_LABEL" 13 | echo "Example: generate-archives raspberrypi 1.20180924" 14 | echo "Example: generate-archives u-boot v2019.10" 15 | } 16 | 17 | cleanup() 18 | { 19 | rm -rf ${TEMPDIR} 20 | } 21 | 22 | cleanup_and_error() 23 | { 24 | cleanup 25 | >&2 echo "Error: Abnormal script termination." 26 | } 27 | 28 | create_raspberrypi_archive() 29 | { 30 | echo "Going to create raspberrypi archive!" 31 | tar -xf "${UPSTREAM_ARCHIVE}" -C "${TEMPDIR}/" 32 | 33 | BOOTLOADER_FILES=( "bootcode.bin" "LICENCE.broadcom" "fixup_cd.dat" "start_cd.elf" "fixup.dat" 34 | "start_db.elf" "fixup_db.dat" "start.elf" "fixup_x.dat" "start_x.elf" 35 | "fixup4cd.dat" "fixup4.dat" "fixup4db.dat" "fixup4x.dat" 36 | "start4cd.elf" "start4db.elf" "start4.elf" "start4x.elf" ) 37 | 38 | mkdir ${TEMPDIR}/output 39 | for file in "${BOOTLOADER_FILES[@]}" 40 | do 41 | cp "${TEMPDIR}/firmware-${VERSION_LABEL}/boot/${file}" "${TEMPDIR}/output" 42 | done 43 | 44 | echo "${VERSION_LABEL}" > "${TEMPDIR}/output/raspberrypi-bootloader.version" 45 | 46 | FINAL_ARCHIVE="${SCRIPTDIR}/raspberrypi-bootloader.tar.gz" 47 | tar -cf "${FINAL_ARCHIVE}" -C "${TEMPDIR}/output" "." 48 | echo "Successfully created ${FINAL_ARCHIVE}!" 49 | } 50 | 51 | create_u_boot_archive() 52 | { 53 | local ARCHITECTURE=$1 54 | local CONFIGURATION=$2 55 | local COMPILER_PREFIX=$3 56 | local RASPBERRY_PI_TYPE=$4 57 | 58 | echo "Going to create u-boot (${ARCHITECTURE}) archive!" 59 | WORKDIR="${TEMPDIR}/u-boot-${VERSION_LABEL#"v"}" 60 | rm -rf "${WORKDIR}" 61 | 62 | tar -xf "${UPSTREAM_ARCHIVE}" -C "${TEMPDIR}/" 63 | 64 | cd "${WORKDIR}" 65 | export CROSS_COMPILE="${COMPILER_PREFIX}" 66 | 67 | make "${CONFIGURATION}" 68 | 69 | make -j8 70 | 71 | mkdir -p ${TEMPDIR}/output/licenses.u-boot 72 | cp u-boot.bin ${TEMPDIR}/output 73 | cp Licenses/* ${TEMPDIR}/output/licenses.u-boot/ 74 | echo "${VERSION_LABEL}" > "${TEMPDIR}/output/u-boot-bootloader.version" 75 | 76 | FINAL_ARCHIVE="${SCRIPTDIR}/u-boot-bootloader.${ARCHITECTURE}.${RASPBERRY_PI_TYPE}.tar.gz" 77 | tar -cf "${FINAL_ARCHIVE}" -C "${TEMPDIR}/output" "." 78 | echo "Successfully created ${FINAL_ARCHIVE}!" 79 | } 80 | 81 | if [[ "$#" -eq 1 && ( "$1" == "-h" || "$1" == "--help" ) ]] 82 | then 83 | echo_usage 84 | exit 0 85 | fi 86 | 87 | if [ "$#" -ne 2 ] 88 | then 89 | >&2 echo "Error: Illegal number of parameters." 90 | echo_usage 91 | exit 1 92 | fi 93 | 94 | if [[ $EUID -eq 0 ]] 95 | then 96 | >&2 echo "Error: Do not run this script as root." 97 | exit 1 98 | fi 99 | 100 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 101 | TEMPDIR="$(mktemp -p ${SCRIPTDIR} -d -t .tmp.XXXXXXXX)" 102 | 103 | trap cleanup_and_error EXIT 104 | 105 | BOOTLOADER_TYPE=$1 106 | VERSION_LABEL=$2 107 | 108 | if [[ "${BOOTLOADER_TYPE}" == "raspberrypi" ]] 109 | then 110 | ARCHIVE_URL="https://github.com/raspberrypi/firmware/archive/${VERSION_LABEL}.tar.gz" 111 | PROCESSING_INSTRUCTIONS=( "create_raspberrypi_archive" ) 112 | elif [[ "${BOOTLOADER_TYPE}" == "u-boot" ]] 113 | then 114 | ARCHIVE_URL="https://github.com/u-boot/u-boot/archive/${VERSION_LABEL}.tar.gz" 115 | PROCESSING_INSTRUCTIONS=( 116 | "create_u_boot_archive armhf rpi_2_defconfig arm-linux-gnueabihf- pi2" 117 | "create_u_boot_archive armhf rpi_3_32b_defconfig arm-linux-gnueabihf- pi3" 118 | "create_u_boot_archive arm64 rpi_3_defconfig aarch64-linux-gnu- pi3" 119 | "create_u_boot_archive arm64 rpi_4_defconfig aarch64-linux-gnu- pi4" 120 | ) 121 | else 122 | >&2 echo "Error: Unknown bootloader type ${BOOTLOADER_TYPE}." 123 | exit 1 124 | fi 125 | 126 | UPSTREAM_ARCHIVE="${SCRIPTDIR}/upstream-${BOOTLOADER_TYPE}-${VERSION_LABEL}.tar.gz" 127 | if [ ! -f "${UPSTREAM_ARCHIVE}" ] 128 | then 129 | wget -O "${UPSTREAM_ARCHIVE}" "${ARCHIVE_URL}" 130 | fi 131 | 132 | for item in "${PROCESSING_INSTRUCTIONS[@]}" 133 | do 134 | ${item} 135 | done 136 | 137 | cleanup 138 | trap - EXIT 139 | 140 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/raspberrypi-bootloader.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lueschem/edi-pi/4af84ad72adccf8736f5beaf3f772163d82b1c21/plugins/playbooks/os_setup/roles/bootloader/files/raspberrypi-bootloader.tar.gz -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.arm64.pi3.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lueschem/edi-pi/4af84ad72adccf8736f5beaf3f772163d82b1c21/plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.arm64.pi3.tar.gz -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.arm64.pi4-v2.tar.gz: -------------------------------------------------------------------------------- 1 | u-boot-bootloader.arm64.pi4.tar.gz -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.arm64.pi4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lueschem/edi-pi/4af84ad72adccf8736f5beaf3f772163d82b1c21/plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.arm64.pi4.tar.gz -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.armhf.pi2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lueschem/edi-pi/4af84ad72adccf8736f5beaf3f772163d82b1c21/plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.armhf.pi2.tar.gz -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.armhf.pi3.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lueschem/edi-pi/4af84ad72adccf8736f5beaf3f772163d82b1c21/plugins/playbooks/os_setup/roles/bootloader/files/u-boot-bootloader.armhf.pi3.tar.gz -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensures edi-boot-shim config.d directory exists. 3 | file: 4 | path: /etc/edi-boot-shim/edi-boot-shim.cfg.d 5 | state: directory 6 | 7 | - name: Configure edi-boot-shim for multiboot. 8 | template: 9 | src: multiboot.cfg 10 | dest: /etc/edi-boot-shim/edi-boot-shim.cfg.d 11 | 12 | - name: Install edi-boot-shim. 13 | apt: 14 | name: edi-boot-shim 15 | install_recommends: no 16 | 17 | - name: Create boot firmware directory. 18 | file: 19 | path: "{{ bootloader_location }}" 20 | state: directory 21 | 22 | - name: Create boot firmware image directory. 23 | file: 24 | path: "{{ bootloader_image_location }}" 25 | state: directory 26 | when: ebs_bootloader_type == "raspberry-pi" 27 | 28 | - name: Setup boot configuration (u-boot). 29 | copy: 30 | src: config.txt.{{ ebs_bootloader_type }}.{{ edi_bootstrap_architecture }} 31 | dest: "{{ bootloader_location }}/config.txt" 32 | when: ebs_bootloader_type == "u-boot" 33 | 34 | - name: Setup boot configuration (raspberry-pi). 35 | template: 36 | src: config.txt.{{ ebs_bootloader_type }}.{{ edi_bootstrap_architecture }} 37 | dest: "{{ bootloader_image_location }}/config.txt" 38 | when: ebs_bootloader_type == "raspberry-pi" 39 | 40 | - name: Setup the kernel command line (u-boot). 41 | copy: 42 | src: cmdline.txt.{{ ebs_bootloader_type }} 43 | dest: "{{ bootloader_location }}/cmdline.txt" 44 | when: (mender_device_type in ["pi4", "pi4-v2", "pi4-v3", "pi5-v3"]) and ebs_bootloader_type == "u-boot" 45 | 46 | - name: Setup the kernel command line. 47 | template: 48 | src: cmdline.txt.{{ ebs_bootloader_type }} 49 | dest: "{{ bootloader_image_location }}/cmdline.txt" 50 | when: ebs_bootloader_type == "raspberry-pi" 51 | 52 | - name: Install the raspberrypi bootloader to the image location. 53 | unarchive: 54 | src: raspberrypi-bootloader.tar.gz 55 | dest: "{{ bootloader_image_location }}" 56 | owner: root 57 | group: root 58 | creates: "{{ bootloader_image_location }}/LICENCE.broadcom" 59 | when: ebs_bootloader_type == "raspberry-pi" 60 | 61 | - name: Install the raspberrypi bootloader to the final location. 62 | unarchive: 63 | src: raspberrypi-bootloader.tar.gz 64 | dest: "{{ bootloader_location }}" 65 | owner: root 66 | group: root 67 | creates: "{{ bootloader_location }}/LICENCE.broadcom" 68 | when: ebs_bootloader_type == "u-boot" 69 | 70 | - name: Install the u-boot bootloader. 71 | unarchive: 72 | src: u-boot-bootloader.{{ edi_bootstrap_architecture }}.{{ mender_device_type }}.tar.gz 73 | dest: "{{ bootloader_location }}" 74 | owner: root 75 | group: root 76 | creates: "{{ bootloader_location }}/u-boot.bin" 77 | when: ebs_bootloader_type == "u-boot" 78 | 79 | - name: Install u-boot tools. 80 | apt: 81 | name: 82 | - libubootenv-tool 83 | - u-boot-tools 84 | state: present 85 | install_recommends: no 86 | when: ebs_bootloader_type == "u-boot" 87 | 88 | - name: Copy the raw boot script to the boot folder. 89 | copy: 90 | src: boot.scr.txt 91 | dest: "{{ bootloader_location }}" 92 | when: ebs_bootloader_type == "u-boot" 93 | 94 | - name: Create boot script. 95 | command: mkimage -A arm -T script -O linux -d boot.scr.txt boot.scr 96 | args: 97 | chdir: "{{ bootloader_location }}" 98 | creates: "{{ bootloader_location }}/boot.scr" 99 | when: ebs_bootloader_type == "u-boot" 100 | 101 | - name: Create u-boot directory on data partition. 102 | file: 103 | path: /data/u-boot 104 | state: directory 105 | when: ebs_bootloader_type == "u-boot" 106 | 107 | - name: Configure u-boot-tools. 108 | template: 109 | src: fw_env.config 110 | dest: /data/u-boot 111 | when: ebs_bootloader_type == "u-boot" 112 | 113 | - name: Create symbolic link for the u-boot-tools config. 114 | file: 115 | src: "/data/u-boot/fw_env.config" 116 | dest: "/etc/fw_env.config" 117 | state: link 118 | when: ebs_bootloader_type == "u-boot" 119 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/templates/cmdline.txt.raspberry-pi: -------------------------------------------------------------------------------- 1 | dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p__ROOTFS_PARTITION__ rw rootfstype=ext4 elevator=deadline fsck.repair=yes panic=10 rootdelay=2{{ ' net.ifnames=0' if mender_device_type == 'pi3-v3' }} 2 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/templates/config.txt.raspberry-pi.arm64: -------------------------------------------------------------------------------- 1 | # For more options and information see 2 | # http://rptl.io/configtxt 3 | # Some settings may impact device functionality. See link above for details 4 | 5 | {% if mender_device_type == "pi3-v3" %} 6 | # needs to be 8.3 format and in top level folder 7 | start_file=p__ROOTFS_PARTITION__start.elf 8 | fixup_file=p__ROOTFS_PARTITION__fixup.dat 9 | {% elif mender_device_type == "pi4-v3" %} 10 | # needs to be 8.3 format and in top level folder 11 | start_file=p__ROOTFS_PARTITION__start4.elf 12 | fixup_file=p__ROOTFS_PARTITION__fixup4.dat 13 | {% endif %} 14 | 15 | # Uncomment some or all of these to enable the optional hardware interfaces 16 | #dtparam=i2c_arm=on 17 | #dtparam=i2s=on 18 | #dtparam=spi=on 19 | 20 | # Enable audio (loads snd_bcm2835) 21 | dtparam=audio=on 22 | 23 | # Enable DRM VC4 V3D driver 24 | dtoverlay=vc4-kms-v3d 25 | max_framebuffers=2 26 | 27 | # Don't have the firmware create an initial video= setting in cmdline.txt. 28 | # Use the kernel's default instead. 29 | disable_fw_kms_setup=1 30 | 31 | # Run in 64-bit mode 32 | arm_64bit=1 33 | 34 | enable_uart=1 35 | 36 | # Disable compensation for displays with overscan 37 | disable_overscan=1 38 | 39 | # Run as fast as firmware / board allows 40 | arm_boost=1 41 | 42 | kernel=vmlinuz 43 | os_prefix=p__ROOTFS_PARTITION__/ 44 | 45 | [cm4] 46 | # Enable host mode on the 2711 built-in XHCI USB controller. 47 | # This line should be removed if the legacy DWC2 controller is required 48 | # (e.g. for USB device mode) or if USB support is not required. 49 | otg_mode=1 50 | 51 | [cm5] 52 | dtoverlay=dwc2,dr_mode=host 53 | 54 | [all] 55 | 56 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/templates/fw_env.config: -------------------------------------------------------------------------------- 1 | # environment on VFAT (a redundant storage in mmc would be more robust) 2 | {{ bootloader_location }}/uboot.env 0x0000 {{ uboot_env_size }} 3 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/bootloader/templates/multiboot.cfg: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # multiboot configuration 3 | # ---------------------------------------------------------------------------- 4 | 5 | BOOTLOADER_TYPE="{{ ebs_bootloader_type }}" 6 | 7 | # Target location of the per partition boot script (boot.scr). 8 | # This location has to match the setup in the primary boot.scr. 9 | BOOTLOADER_DIRECTORY="{{ ebs_bootloader_directory }}" 10 | 11 | # This secondary boot script is on the same partition. 12 | CHECK_MOUNT=false 13 | 14 | # Use the multiboot template. 15 | BOOT_COMMAND_TEMPLATE="/etc/edi-boot-shim/{{ ebs_template }}" 16 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/essential_bare_metal_packages/files/85-systemd_networkd.preset: -------------------------------------------------------------------------------- 1 | disable systemd-networkd-wait-online.service 2 | disable systemd-networkd.service 3 | disable systemd-networkd.socket 4 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/essential_bare_metal_packages/files/95-wpa_supplicant.preset: -------------------------------------------------------------------------------- 1 | disable wpa_supplicant@.service 2 | disable wpa_supplicant-nl80211@.service 3 | disable wpa_supplicant-wired@.service 4 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/essential_bare_metal_packages/files/brcmfmac.conf: -------------------------------------------------------------------------------- 1 | options brcmfmac feature_disable=0x200000 2 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/essential_bare_metal_packages/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install packages that are essential for running on bare metal. 3 | apt: 4 | name: "{{ bare_metal_packages }}" 5 | state: present 6 | install_recommends: no 7 | 8 | - name: Install wpasupplicant on devices that have WiFi. 9 | apt: 10 | name: wpasupplicant 11 | state: present 12 | install_recommends: no 13 | when: mender_device_type != "pi2" 14 | 15 | - name: Preset unused wpa_supplicant and systemd-networkd services to disabled. 16 | copy: 17 | src: "{{ item }}" 18 | dest: /lib/systemd/system-preset/ 19 | loop: 20 | - 95-wpa_supplicant.preset 21 | - 85-systemd_networkd.preset 22 | 23 | - name: Disable persistent logging to protect the eMMC/flash. 24 | file: 25 | path: /var/log/journal 26 | state: absent 27 | 28 | - name: Disable DUMP_OBSS on brcmfmac. 29 | copy: 30 | src: brcmfmac.conf 31 | dest: /etc/modprobe.d/ 32 | 33 | - name: Create directory for edi-set-hostname customization. 34 | file: 35 | path: /etc/systemd/system/edi-set-hostname.service.d 36 | state: directory 37 | mode: 0755 38 | 39 | - name: Customize edi-set-hostname service. 40 | template: 41 | src: edi-set-hostname.override.conf 42 | dest: /etc/systemd/system/edi-set-hostname.service.d/override.conf 43 | mode: 0644 44 | 45 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/essential_bare_metal_packages/templates/edi-set-hostname.override.conf: -------------------------------------------------------------------------------- 1 | {% set network_interface = 'end0' if mender_device_type in ['pi4-v3', 'pi5-v3'] else 'eth0' %} 2 | [Unit] 3 | After=sys-subsystem-net-devices-{{ network_interface }}.device 4 | Wants=sys-subsystem-net-devices-{{ network_interface }}.device 5 | 6 | [Service] 7 | Environment="NETWORK_INTERFACE={{ network_interface }}" 8 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/essential_bare_metal_packages/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | bare_metal_packages: 3 | - edi-resize-rootfs 4 | - edi-set-hostname 5 | - firmware-brcm80211 6 | - haveged 7 | - iproute2 8 | - "{{ kernel_image }}" 9 | - kmod 10 | - network-manager 11 | - systemd-timesyncd 12 | - udev 13 | 14 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/defaults/main.yml: -------------------------------------------------------------------------------- 1 | mender_config_directory: "{{ edi_project_directory }}/configuration/mender" 2 | 3 | mender_inventory_poll_interval_seconds: 600 4 | mender_retry_poll_interval_seconds: 30 5 | mender_rootfs_part_a: /dev/mmcblk0p3 6 | mender_rootfs_part_b: /dev/mmcblk0p4 7 | mender_server_url: https://hosted.mender.io 8 | mender_tenant_token: "" 9 | mender_update_poll_interval_seconds: 60 10 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/files/05_mender_update: -------------------------------------------------------------------------------- 1 | # exclude some files we do not want to be provided by the mender-updated package 2 | path-exclude /etc/mender/artifact_info 3 | path-exclude /usr/share/mender/identity/mender-device-identity 4 | path-exclude /usr/share/mender/inventory/mender-inventory-bootloader-integration 5 | path-exclude /usr/share/mender/inventory/mender-inventory-geo 6 | path-exclude /usr/share/mender/modules/v3/rpm 7 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/files/empty.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/files/mender-io-archive-keyring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lueschem/edi-pi/4af84ad72adccf8736f5beaf3f772163d82b1c21/plugins/playbooks/os_setup/roles/mender/files/mender-io-archive-keyring.gpg -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/files/override.conf: -------------------------------------------------------------------------------- 1 | [Service] 2 | Environment="PATH=/usr/share/mender/integration:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/files/pi-uboot: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # MIT License 4 | # 5 | # Copyright (c) 2024 Matthias Lüscher 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | set -o nounset 26 | set -o errexit 27 | set -o pipefail 28 | 29 | UBOOT_ENV_OVERLAY=/var/run/uboot-env-overlay 30 | CONFIG_TXT=/boot/firmware/config.txt 31 | TRYBOOT_TXT=/boot/firmware/tryboot.txt 32 | 33 | print_and_exit() 34 | { 35 | local TYPE=$1 36 | local MESSAGE=$2 37 | if [ "${TYPE}" == "ERROR" ] ; then 38 | >&2 echo "error: ${MESSAGE}" 39 | exit 1 40 | else 41 | echo "${MESSAGE}" 42 | exit 0 43 | fi 44 | } 45 | 46 | print_environment() 47 | { 48 | echo "mender_boot_part=${mender_boot_part}" 49 | echo "mender_boot_part_hex=${mender_boot_part_hex}" 50 | echo "upgrade_available=${upgrade_available}" 51 | echo "bootcount=${bootcount}" 52 | echo "mender_uboot_separator=${mender_uboot_separator}" 53 | echo "mender_check_saveenv_canary=0" 54 | } 55 | 56 | update_environment() 57 | { 58 | local SPLIT_NEEDED 59 | local key 60 | local value 61 | SPLIT_NEEDED=$(echo "${1}" | tr -dc '=' | wc -c) 62 | 63 | if [ "${SPLIT_NEEDED}" -eq 1 ]; then 64 | key=$(echo "${1}" | cut -d '=' -f 1) 65 | value=$(echo "${1}" | cut -d '=' -f 2) 66 | else 67 | key=${1} 68 | value=${2} 69 | fi 70 | 71 | case $key in 72 | mender_boot_part) 73 | mender_boot_part=${value} 74 | MENDER_BOOT_PART_UPDATED=1 75 | ;; 76 | mender_boot_part_hex) 77 | mender_boot_part_hex=${value} 78 | ;; 79 | upgrade_available) 80 | upgrade_available=${value} 81 | UPGRADE_AVAILABLE_UPDATED=1 82 | ;; 83 | bootcount) 84 | bootcount=${value} 85 | ;; 86 | mender_uboot_separator) 87 | mender_uboot_separator=${value} 88 | ;; 89 | *) 90 | print_and_exit "ERROR" "unsupported key ${key}" 91 | ;; 92 | esac 93 | } 94 | 95 | if [[ $EUID -ne 0 ]]; then 96 | print_and_exit "ERROR" "use root user to execute this script" 97 | fi 98 | 99 | CURRENT_BOOT_DEVICE=$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p') 100 | if [ -z "${CURRENT_BOOT_DEVICE}" ] ; then 101 | print_and_exit "ERROR" "unable to detect root partition device" 102 | fi 103 | 104 | CURRENT_BOOT_PART=$(echo "${CURRENT_BOOT_DEVICE}" | grep -o '[1-9][0-9]*$') 105 | if [ -z "${CURRENT_BOOT_PART}" ] ; then 106 | print_and_exit "ERROR" "unable to extract partition number of ${CURRENT_BOOT_DEVICE}" 107 | fi 108 | 109 | COMMITTED_BOOT_PART=$(< "${CONFIG_TXT}" sed -n 's|^os_prefix=p\([[:digit:]]\)/$|\1|p') 110 | if [ -z "${COMMITTED_BOOT_PART}" ] ; then 111 | print_and_exit "ERROR" "unable to extract committed boot partition from ${CONFIG_TXT}" 112 | fi 113 | 114 | mender_boot_part=${CURRENT_BOOT_PART} 115 | mender_boot_part_hex=$(printf '%x\n' "${CURRENT_BOOT_PART}") 116 | 117 | if [[ ${CURRENT_BOOT_PART} -eq ${COMMITTED_BOOT_PART} ]] 118 | then 119 | upgrade_available=0 120 | else 121 | upgrade_available=1 122 | fi 123 | 124 | bootcount=1 125 | mender_uboot_separator="" 126 | 127 | if [[ -f "${UBOOT_ENV_OVERLAY}" ]] 128 | then 129 | source "${UBOOT_ENV_OVERLAY}" 130 | fi 131 | 132 | if [[ ${0} == *fw_printenv ]] 133 | then 134 | if [[ $# -eq 0 ]] 135 | then 136 | print_environment 137 | else 138 | for cli_arg in "$@" 139 | do 140 | print_environment | grep "^${cli_arg}=.*" 141 | done 142 | fi 143 | elif [[ ${0} == *fw_setenv ]] 144 | then 145 | MENDER_BOOT_PART_UPDATED=0 146 | UPGRADE_AVAILABLE_UPDATED=0 147 | 148 | if [[ $# -eq 0 ]] 149 | then 150 | print_and_exit "ERROR" "variable name missing" 151 | elif [[ $# -eq 1 ]] || [[ $# -eq 2 ]] 152 | then 153 | if [[ $1 == -s ]] 154 | then 155 | if [[ $# -ne 2 ]] 156 | then 157 | print_and_exit "ERROR" "missing script parameter" 158 | fi 159 | 160 | if [[ $2 == - ]] 161 | then 162 | SCRIPT=$(cat) 163 | else 164 | if [[ ! -f ${2} ]] 165 | then 166 | print_and_exit "ERROR" "file ${2} not found" 167 | fi 168 | SCRIPT=$(cat "${2}") 169 | fi 170 | 171 | while IFS= read -r line 172 | do 173 | read -r -a key_value_pair <<< "${line}" 174 | 175 | if [[ ${#key_value_pair[@]} -eq 2 ]] 176 | then 177 | update_environment "${key_value_pair[0]}" "${key_value_pair[1]}" 178 | elif [[ ${#key_value_pair[@]} -eq 1 ]] 179 | then 180 | update_environment "${key_value_pair[0]}" "" 181 | else 182 | print_and_exit "ERROR" "unsupported number of arguments in script" 183 | fi 184 | done <<< "${SCRIPT}" 185 | else 186 | if [[ $# -eq 2 ]] 187 | then 188 | update_environment "${1}" "${2}" 189 | else 190 | update_environment "${1}" "" 191 | fi 192 | fi 193 | 194 | if [[ ${MENDER_BOOT_PART_UPDATED} -eq 1 ]] && [[ ${UPGRADE_AVAILABLE_UPDATED} -eq 1 ]] && [[ ${bootcount} -eq 0 ]] && [[ ${upgrade_available} -eq 1 ]] 195 | then 196 | # mender install transaction 197 | if [[ ${CURRENT_BOOT_PART} -eq ${mender_boot_part} ]] 198 | then 199 | print_and_exit "ERROR" "invalid install transaction - new boot partition is equal to old boot partition" 200 | elif [[ ${COMMITTED_BOOT_PART} -eq ${mender_boot_part} ]] 201 | then 202 | print_and_exit "ERROR" "invalid install transaction - new boot partition is equal to committed boot partition" 203 | else 204 | : # nothing to do - boot partition will be setup by state script 205 | fi 206 | elif [[ ${MENDER_BOOT_PART_UPDATED} -eq 1 ]] && [[ ${UPGRADE_AVAILABLE_UPDATED} -eq 1 ]] && [[ ${upgrade_available} -eq 0 ]] 207 | then 208 | # mender rollback transaction 209 | # nothing to do - reboot will automatically boot into previously committed configuration 210 | : 211 | elif [[ ${MENDER_BOOT_PART_UPDATED} -eq 0 ]] && [[ ${UPGRADE_AVAILABLE_UPDATED} -eq 1 ]] && [[ ${upgrade_available} -eq 0 ]] 212 | then 213 | # mender commit transaction 214 | if [[ ${CURRENT_BOOT_PART} -eq ${COMMITTED_BOOT_PART} ]] 215 | then 216 | : # nothing to do - commit has already been done 217 | elif [[ ! -f "${TRYBOOT_TXT}" ]] 218 | then 219 | print_and_exit "ERROR" "missing file: ${TRYBOOT_TXT}" 220 | else 221 | mv ${TRYBOOT_TXT} ${CONFIG_TXT} 222 | fi 223 | fi 224 | 225 | print_environment > "${UBOOT_ENV_OVERLAY}" 226 | else 227 | print_and_exit "ERROR" "unsupported number of arguments" 228 | fi 229 | elif [[ ${0} == *reboot ]] 230 | then 231 | if [[ $# -ge 1 ]] 232 | then 233 | /usr/sbin/reboot "$@" 234 | elif [[ ${upgrade_available} -eq 1 ]] && [[ ${COMMITTED_BOOT_PART} -ne ${mender_boot_part} ]] && [[ ${bootcount} -eq 0 ]] && [[ -f "${TRYBOOT_TXT}" ]] 235 | then 236 | /usr/sbin/reboot '0 tryboot' 237 | else 238 | /usr/sbin/reboot 239 | fi 240 | fi -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create mender directories on data partition. 3 | file: 4 | path: /data/{{ item }} 5 | state: directory 6 | loop: 7 | - mender 8 | - mender-monitor 9 | 10 | - name: Create symbolic links to the data partition. 11 | file: 12 | src: /data/{{ item }} 13 | dest: /var/lib/{{ item }} 14 | state: link 15 | loop: 16 | - mender 17 | - mender-monitor 18 | 19 | - name: Create directory for mender-configure configuration. 20 | file: 21 | dest: /var/lib/mender-configure 22 | state: directory 23 | mode: 0755 24 | 25 | - name: Add an empty mender-configure configuration. 26 | copy: 27 | src: empty.json 28 | dest: /var/lib/mender-configure/device-config.json 29 | mode: 0600 30 | 31 | - name: Mask some files that shall not be provided by the mender-update Debian package. 32 | copy: 33 | src: 05_mender_update 34 | dest: /etc/dpkg/dpkg.cfg.d/ 35 | 36 | - name: Add Mender repository key. 37 | copy: 38 | src: mender-io-archive-keyring.gpg 39 | dest: /usr/share/keyrings/ 40 | mode: 0644 41 | 42 | - name: Add mender repository to sources.list.d. 43 | template: 44 | src: mender-io.list 45 | dest: /etc/apt/sources.list.d/ 46 | 47 | - name: Update apt cache. 48 | apt: 49 | update_cache: yes 50 | 51 | - name: Install mender-update, mender-flash, mender-connect, mender-configure and jq. 52 | apt: 53 | name: 54 | - mender-update 55 | - mender-flash 56 | - mender-connect 57 | - mender-configure 58 | - jq 59 | state: present 60 | install_recommends: no 61 | 62 | - name: Load project specific (customized) mender configuration. 63 | include_vars: "{{ item }}" 64 | with_first_found: 65 | - "{{ mender_config_directory }}/mender_custom.yml" 66 | - "{{ mender_config_directory }}/mender.yml" 67 | 68 | - name: Write mender main configuration. 69 | template: 70 | src: mender.conf 71 | dest: /etc/mender/ 72 | 73 | - name: Write mender-connect configuration. 74 | template: 75 | src: mender-connect.conf 76 | dest: /etc/mender/ 77 | 78 | - name: Configure the device type. 79 | template: 80 | src: device_type 81 | dest: /data/mender/device_type 82 | 83 | - name: Copy inventory scripts. 84 | copy: 85 | src: "{{ item }}" 86 | dest: /usr/share/mender/inventory/ 87 | mode: 0755 88 | with_fileglob: 89 | - "{{ mender_config_directory }}/inventory/*" 90 | 91 | - name: Copy identity scripts. 92 | template: 93 | src: "{{ item }}" 94 | dest: /usr/share/mender/identity/ 95 | mode: 0755 96 | with_fileglob: 97 | - "{{ mender_config_directory }}/identity/*" 98 | 99 | - name: Create various integration directories. 100 | file: 101 | path: "{{ item }}" 102 | state: directory 103 | with_items: 104 | - /usr/share/mender/integration 105 | - /etc/systemd/system/mender-updated.service.d 106 | when: ebs_bootloader_type == "raspberry-pi" 107 | 108 | - name: Make sure that the mender-updated service picks the modified reboot script. 109 | copy: 110 | src: override.conf 111 | dest: /etc/systemd/system/mender-updated.service.d/ 112 | when: ebs_bootloader_type == "raspberry-pi" 113 | 114 | - name: Copy the bootloader integration script. 115 | copy: 116 | src: pi-uboot 117 | dest: /usr/share/mender/integration/ 118 | mode: 0755 119 | when: ebs_bootloader_type == "raspberry-pi" 120 | 121 | - name: Create a symbolic link for the reboot command. 122 | file: 123 | src: /usr/share/mender/integration/pi-uboot 124 | dest: /usr/share/mender/integration/reboot 125 | state: link 126 | when: ebs_bootloader_type == "raspberry-pi" 127 | 128 | - name: Create symbolic links for fw_printenv and fw_setenv. 129 | file: 130 | src: /usr/share/mender/integration/pi-uboot 131 | dest: /usr/bin/{{ item }} 132 | state: link 133 | with_items: 134 | - fw_printenv 135 | - fw_setenv 136 | when: ebs_bootloader_type == "raspberry-pi" 137 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/templates/device_type: -------------------------------------------------------------------------------- 1 | device_type={{ mender_device_type }}-{{ edi_bootstrap_architecture }} 2 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/templates/mender-connect.conf: -------------------------------------------------------------------------------- 1 | { 2 | "ReconnectIntervalSeconds": 5, 3 | "SkipVerify": false, 4 | "Limits": { 5 | "Enabled": true, 6 | "FileTransfer": { 7 | "Chroot": "/home/{{ default_user_name }}", 8 | "OwnerGet": ["{{ default_user_name }}"], 9 | "GroupGet": ["{{ default_user_group_name }}"], 10 | "OwnerPut": "{{ default_user_name }}", 11 | "GroupPut": "{{ default_user_group_name }}", 12 | "MaxFileSize": 536870912, 13 | "FollowSymLinks": true, 14 | "AllowOverwrite": true, 15 | "RegularFilesOnly": true, 16 | "PreserveOwner": true, 17 | "PreserveGroup": true, 18 | "PreserveMode": true, 19 | "Counters": { 20 | "MaxBytesTxPerHour": 536870912, 21 | "MaxBytesRxPerHour": 536870912 22 | } 23 | } 24 | }, 25 | "FileTransfer": { 26 | "Disable": false 27 | }, 28 | "MenderClient": { 29 | "Disable": false 30 | }, 31 | "PortForward": { 32 | "Disable": false 33 | }, 34 | "ShellCommand": "/usr/bin/bash", 35 | "ShellArguments": [], 36 | "Sessions": { 37 | "ExpireAfterIdle": 3600, 38 | "MaxPerUser": 5, 39 | "StopExpired": false 40 | }, 41 | "Terminal": { 42 | "Disable": false, 43 | "Height": 40, 44 | "Width": 80 45 | }, 46 | "User": "{{ default_user_name }}" 47 | } 48 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/templates/mender-io.list: -------------------------------------------------------------------------------- 1 | #TODO: Readd mender repository once it is available for Debian trixie. 2 | #deb [arch={{ edi_bootstrap_architecture }} signed-by=/usr/share/keyrings/mender-io-archive-keyring.gpg] https://downloads.mender.io/repos/debian debian/{{ ansible_distribution_release }}/stable main 3 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/mender/templates/mender.conf: -------------------------------------------------------------------------------- 1 | { 2 | "InventoryPollIntervalSeconds": {{ mender_inventory_poll_interval_seconds }}, 3 | "RetryPollIntervalSeconds": {{ mender_retry_poll_interval_seconds }}, 4 | "RootfsPartA": "{{ mender_rootfs_part_a }}", 5 | "RootfsPartB": "{{ mender_rootfs_part_b }}", 6 | "ServerURL": "{{ mender_server_url }}", 7 | "TenantToken": "{{ mender_tenant_token }}", 8 | "UpdatePollIntervalSeconds": {{ mender_update_poll_interval_seconds }}, 9 | "UpdateControlMapExpirationTimeSeconds": {{ mender_update_poll_interval_seconds * 2 }}, 10 | "UpdateControlMapBootExpirationTimeSeconds": 600 11 | } 12 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/repositories/files/50-get-edi-io: -------------------------------------------------------------------------------- 1 | Package: * 2 | Pin: origin packagecloud.io 3 | Pin-Priority: 750 4 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/repositories/files/get-edi-io-archive-keyring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lueschem/edi-pi/4af84ad72adccf8736f5beaf3f772163d82b1c21/plugins/playbooks/os_setup/roles/repositories/files/get-edi-io-archive-keyring.gpg -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/repositories/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check Debian release compatibility. 3 | fail: 4 | msg: "Error: The playbooks can not be applied to the given target as the distribution release is incompatible! 5 | Only Debian {{ debian_distribution_release }} is currently supported!" 6 | when: ansible_distribution_release != debian_distribution_release 7 | 8 | - name: Install ca-certificates. 9 | apt: 10 | name: ca-certificates 11 | install_recommends: no 12 | 13 | - name: Add edi repository key. 14 | copy: 15 | src: get-edi-io-archive-keyring.gpg 16 | dest: /usr/share/keyrings/ 17 | mode: 0644 18 | 19 | - name: Add edi repository. 20 | template: 21 | src: get-edi-io.list 22 | dest: /etc/apt/sources.list.d/get-edi-io.list 23 | mode: 0644 24 | 25 | # TODO: Remove preference as soon as packages are available directly from Mender or Debian. 26 | - name: Prefer packages from get-edi-io repository. 27 | copy: 28 | src: 50-get-edi-io 29 | dest: /etc/apt/preferences.d/ 30 | 31 | - name: Update apt cache. 32 | apt: 33 | update_cache: yes 34 | 35 | -------------------------------------------------------------------------------- /plugins/playbooks/os_setup/roles/repositories/templates/get-edi-io.list: -------------------------------------------------------------------------------- 1 | deb [signed-by=/usr/share/keyrings/get-edi-io-archive-keyring.gpg] https://packagecloud.io/get-edi/debian/debian/ {{ ansible_distribution_release }} main 2 | # deb-src [signed-by=/usr/share/keyrings/get-edi-io-archive-keyring.gpg] https://packagecloud.io/get-edi/debian/debian/ {{ ansible_distribution_release }} main 3 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/container_image/buildah2image.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (C) 2024 Matthias Luescher 4 | # 5 | # Authors: 6 | # Matthias Luescher 7 | # 8 | # This file is part of the edi project configuration. 9 | # 10 | # This script is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This script is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with the edi project configuration. If not, see . 22 | 23 | set -o errexit 24 | set -o pipefail 25 | set -o nounset 26 | 27 | LOG_LEVEL="{{ edi_log_level }}" 28 | PODMAN_IMAGE="{{ pp_podman_image }}" 29 | BUILDAH_CONTAINER="{{ edi_project_container }}" 30 | PODMAN_IMAGE_MANIFEST="{{ pp_podman_image_manifest }}" 31 | DEBIAN_RELEASE="{{ debian_distribution_release }}" 32 | DEBIAN_ARCHITECTURE="{{ edi_bootstrap_architecture }}" 33 | 34 | if [ "${LOG_LEVEL}" == "DEBUG" ]; then 35 | set -x 36 | fi 37 | 38 | cat << EOF >> "${PODMAN_IMAGE_MANIFEST}" 39 | podman_image=${PODMAN_IMAGE} 40 | debian_architecture=${DEBIAN_ARCHITECTURE} 41 | debian_release=${DEBIAN_RELEASE} 42 | EOF 43 | 44 | buildah commit "${BUILDAH_CONTAINER}" "${PODMAN_IMAGE}" 45 | 46 | echo "********************************************************************************" 47 | echo " Hint: Use distrobox to launch a container." 48 | echo " Examples:" 49 | echo " distrobox create --image ${PODMAN_IMAGE} --name CONTAINER_NAME --unshare-all" 50 | echo " distrobox create --image ${PODMAN_IMAGE} --name CONTAINER_NAME --init --unshare-all --additional-packages \"systemd libpam-systemd\"" 51 | echo "********************************************************************************" 52 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/documentation/write_doc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (C) 2020 Matthias Luescher 4 | # 5 | # Authors: 6 | # Matthias Luescher 7 | # 8 | # This file is part of the edi project configuration. 9 | # 10 | # This script is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This script is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with the edi project configuration. If not, see . 22 | 23 | set -o errexit 24 | set -o pipefail 25 | set -o nounset 26 | 27 | print_usage() 28 | { 29 | cat <&2 echo -e "\033[91mError: ${MESSAGE}\033[0m" 49 | } 50 | 51 | print_error_and_exit() 52 | { 53 | local MESSAGE="${1}" 54 | print_error "${MESSAGE}" 55 | exit 1 56 | } 57 | 58 | unexpected_exit() 59 | { 60 | local TEMPDIR="${1}" 61 | print_error "Going to clean up after abnormal script termination." 62 | clean_up "${TEMPDIR}" 63 | trap - EXIT 64 | print_error_and_exit "Abnormal script termination." 65 | } 66 | 67 | clean_up() 68 | { 69 | local TEMPDIR="${1}" 70 | rm -rf "${TEMPDIR}" 71 | } 72 | 73 | if ! options=$(getopt -o p:r:a:i:o:c:hw: -l project:,release:,author:,input:,output:,config:,help,log: -- "$@") 74 | then 75 | print_usage 76 | print_error_and_exit "Invalid option." 77 | fi 78 | eval set -- "$options" 79 | 80 | PROJECT="missing-project" 81 | RELEASE="missing-release" 82 | AUTHOR="missing-author" 83 | RAW_INPUT="missing-input" 84 | RENDERED_OUTPUT="missing-output" 85 | CONFIG="missing-config" 86 | LOG_LEVEL="INFO" 87 | 88 | while true 89 | do 90 | case "${1}" in 91 | -h|--help) print_usage && exit 0;; 92 | -p|--project) PROJECT="${2}"; shift 2;; 93 | -r|--release) RELEASE="${2}"; shift 2;; 94 | -a|--author) AUTHOR="${2}"; shift 2;; 95 | -i|--input) RAW_INPUT="${2}"; shift 2;; 96 | -o|--output) RENDERED_OUTPUT="${2}"; shift 2;; 97 | -c|--config) CONFIG="${2}"; shift 2;; 98 | --log) LOG_LEVEL="${2}"; shift 2;; 99 | *) break ;; 100 | esac 101 | done 102 | 103 | if [ "${LOG_LEVEL}" == "DEBUG" ]; then 104 | set -x 105 | fi 106 | 107 | if [[ ${EUID} -eq 0 ]]; then 108 | print_error_and_exit "This script should not be run as root." 109 | fi 110 | 111 | if [ -d "${RENDERED_OUTPUT}" ]; then 112 | print_error_and_exit "The directory ${RENDERED_OUTPUT} already exists." 113 | fi 114 | 115 | mkdir -p "${RENDERED_OUTPUT}" 116 | trap 'unexpected_exit "${RENDERED_OUTPUT}"' EXIT 117 | 118 | cd "${RENDERED_OUTPUT}" 119 | sphinx-quickstart --quiet -p "${PROJECT}" -a "${AUTHOR}" -r "${RELEASE}" 120 | rm index.rst 121 | edi --log="${LOG_LEVEL}" documentation render "${RAW_INPUT}" "${RENDERED_OUTPUT}" "${CONFIG}" 122 | 123 | trap - EXIT 124 | 125 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/documentation/write_doc.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | source {{ pp_timestamp }} 7 | 8 | LOG_LEVEL="{{ edi_log_level }}" 9 | WORKDIR="{{ edi_work_directory }}" 10 | 11 | print_error() 12 | { 13 | local MESSAGE="${1}" 14 | >&2 echo -e "\033[91mError: ${MESSAGE}\033[0m" 15 | } 16 | 17 | print_error_and_exit() 18 | { 19 | local MESSAGE="${1}" 20 | print_error "${MESSAGE}" 21 | exit 1 22 | } 23 | 24 | unexpected_exit() 25 | { 26 | local TEMPDIR="${1}" 27 | print_error "Going to clean up after abnormal script termination." 28 | clean_up "${TEMPDIR}" 29 | trap - EXIT 30 | print_error_and_exit "Abnormal script termination." 31 | } 32 | 33 | clean_up() 34 | { 35 | local TEMPDIR="${1}" 36 | rm -rf "${TEMPDIR}" 37 | } 38 | 39 | if [ "${LOG_LEVEL}" == "DEBUG" ]; then 40 | set -x 41 | fi 42 | 43 | if [[ ${EUID} -eq 0 ]]; then 44 | print_error_and_exit "This script must not be run as root." 45 | fi 46 | 47 | TEMPDIR="$(mktemp -p ${WORKDIR} -d -t .tmp.XXXXXXXX)" 48 | 49 | trap "unexpected_exit ${TEMPDIR}" EXIT 50 | 51 | pushd "${TEMPDIR}" > /dev/null 52 | tar -xf "{{ pp_rootfs_archive }}" ./usr/share/doc 53 | popd > /dev/null 54 | 55 | {{ edi_current_plugin_directory }}/write_doc --project "{{ edi_configuration_name }}-{{ debian_distribution_release }}-{{ edi_bootstrap_architecture }}" --release "${BUILD_TIMESTAMP}" --author "{{ author }}" --input "${TEMPDIR}/usr/share/doc" --output "{{ pp_documentation }}" --config "{{ edi_project_directory }}/{{ edi_configuration_name }}.yml" --log "{{ edi_log_level }}" 56 | 57 | clean_up "${TEMPDIR}" 58 | 59 | trap - EXIT 60 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/fully_named_artifacts/create_full_names.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o nounset 4 | set -o errexit 5 | 6 | source {{ pp_timestamp }} 7 | 8 | mkdir -p "{{ pp_fully_named_artifacts }}" 9 | ln -f "{{ pp_mender_artifact }}" "{{ pp_fully_named_artifacts }}/${BUILD_TIMESTAMP}_{{ edi_configuration_name }}-{{ debian_distribution_release }}-{{ edi_bootstrap_architecture }}.mender" 10 | ln -f "{{ pp_image }}" "{{ pp_fully_named_artifacts }}/${BUILD_TIMESTAMP}_{{ edi_configuration_name }}-{{ debian_distribution_release }}-{{ edi_bootstrap_architecture }}.img" 11 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/genimage/exclude-patterns: -------------------------------------------------------------------------------- 1 | ./usr/share/doc/*/changelog.Debian.gz 2 | ./usr/share/doc/*/changelog.gz 3 | ./run/* 4 | ./tmp/* 5 | ./var/cache/debconf/* 6 | ./var/cache/ldconfig/aux-cache 7 | ./var/log/apt/* 8 | ./var/log/alternatives.log 9 | ./var/log/dpkg.log 10 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/genimage/fstab: -------------------------------------------------------------------------------- 1 | # Custom fstab added by lxd2rootfs script. 2 | # 3 | /dev/root / ext4 rw 0 1 4 | /dev/mmcblk0p1 /boot/firmware vfat rw 0 2 5 | /dev/mmcblk0p2 /data ext4 defaults 0 0 6 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/genimage/genimage.cfg: -------------------------------------------------------------------------------- 1 | config { 2 | mkdosfs = "/sbin/mkdosfs" 3 | mke2fs = "/sbin/mke2fs" 4 | e2fsck = "/sbin/e2fsck" 5 | } 6 | 7 | image disk-image.img { 8 | hdimage { 9 | align = "1M" 10 | partition-table-type = "mbr" 11 | fill = "true" 12 | } 13 | 14 | partition boot { 15 | offset = "1M" 16 | partition-type = 0x0c 17 | image = "boot.fat32" 18 | bootable = "true" 19 | } 20 | 21 | partition data { 22 | partition-type = 0x83 23 | image = "data.ext4" 24 | } 25 | 26 | partition root { 27 | partition-type = 0x83 28 | image = "root.ext4" 29 | } 30 | } 31 | 32 | image boot.fat32 { 33 | name = "boot" 34 | vfat { 35 | label = "boot" 36 | } 37 | size = "128M" 38 | mountpoint = "/boot/firmware" 39 | } 40 | 41 | image data.ext4 { 42 | name = "data" 43 | ext4 { 44 | label = "data" 45 | use-mke2fs = "true" 46 | } 47 | size = "256M" 48 | mountpoint = "/data" 49 | } 50 | 51 | image root.ext4 { 52 | name = "root" 53 | ext4 { 54 | label = "root" 55 | use-mke2fs = "true" 56 | } 57 | size = "125%" 58 | mountpoint = "/" 59 | } 60 | 61 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/genimage/hostname: -------------------------------------------------------------------------------- 1 | __HOSTNAME__ 2 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/genimage/hosts: -------------------------------------------------------------------------------- 1 | 127.0.0.1 localhost 2 | 127.0.1.1 __HOSTNAME__ 3 | 4 | # The following lines are desirable for IPv6 capable hosts 5 | ::1 ip6-localhost ip6-loopback 6 | fe00::0 ip6-localnet 7 | ff00::0 ip6-mcastprefix 8 | ff02::1 ip6-allnodes 9 | ff02::2 ip6-allrouters 10 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/genimage/rootfs2image.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (C) 2024 Matthias Luescher 4 | # 5 | # Authors: 6 | # Matthias Luescher 7 | # 8 | # This file is part of the edi project configuration. 9 | # 10 | # This script is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This script is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with the edi project configuration. If not, see . 22 | 23 | set -o errexit 24 | set -o pipefail 25 | set -o nounset 26 | 27 | source "{{ pp_timestamp }}" 28 | 29 | LOG_LEVEL="{{ edi_log_level }}" 30 | INPUT_ARCHIVE="{{ pp_rootfs_archive }}" 31 | PLUGIN_DIRECTORY="{{ edi_current_plugin_directory }}" 32 | DISK_IMAGE="{{ pp_image }}" 33 | PARTITION_IMAGE="{{ pp_partition_image }}" 34 | WORKDIR="{{ edi_work_directory }}" 35 | HOSTNAME="{{ hostname }}" 36 | ARTIFACT_NAME="${BUILD_TIMESTAMP}-{{ edi_configuration_name }}-{{ debian_distribution_release }}-{{ edi_bootstrap_architecture }}" 37 | MENDER_DEVICE_TYPE="{{ mender_device_type }}" 38 | 39 | print_error() 40 | { 41 | local MESSAGE="${1}" 42 | >&2 echo -e "\033[91mError: ${MESSAGE}\033[0m" 43 | } 44 | 45 | print_error_and_exit() 46 | { 47 | local MESSAGE="${1}" 48 | print_error "${MESSAGE}" 49 | exit 1 50 | } 51 | 52 | unexpected_exit() 53 | { 54 | local TEMPDIR="${1}" 55 | print_error "Going to clean up after abnormal script termination." 56 | rm -rf "${TEMPDIR}" 57 | trap - EXIT 58 | print_error_and_exit "Abnormal script termination." 59 | } 60 | 61 | if [ "${LOG_LEVEL}" == "DEBUG" ]; then 62 | set -x 63 | fi 64 | 65 | if touch /etc/edi-fakeroot-check > /dev/null 2>&1; then 66 | print_error_and_exit "This script must not be run as real root - please use fakeroot." 67 | fi 68 | 69 | if [[ ${EUID} -ne 0 ]]; then 70 | print_error_and_exit "This script must be run using fakeroot." 71 | fi 72 | 73 | TEMPDIR="$(mktemp -p "${WORKDIR}" -d -t .tmp.XXXXXXXX)" 74 | trap "unexpected_exit ${TEMPDIR}" EXIT 75 | 76 | pushd "${TEMPDIR}" > /dev/null 77 | 78 | mkdir rootfs 79 | 80 | tar --numeric-owner --exclude-from "${PLUGIN_DIRECTORY}/exclude-patterns" -C rootfs/ -axf "${INPUT_ARCHIVE}" 81 | 82 | # Copy kernel, initrd and dtbs to firmware partition 83 | if [ -d "rootfs/boot/image-kernel" ]; then 84 | cp -r -L rootfs/boot/image-kernel rootfs/boot/firmware/p3 85 | sed -i "s@^BOOTLOADER_DIRECTORY=.*@BOOTLOADER_DIRECTORY=\"/boot/firmware/p3\"@" "rootfs/etc/edi-boot-shim/edi-boot-shim.cfg.d/multiboot.cfg" 86 | fi 87 | 88 | if [ -d "rootfs/boot/image-firmware" ]; then 89 | cp rootfs/boot/image-firmware/cmdline.txt rootfs/boot/firmware/p3/cmdline.txt 90 | sed -i 's@__ROOTFS_PARTITION__@3@' rootfs/boot/firmware/p3/cmdline.txt 91 | cp rootfs/boot/image-firmware/config.txt rootfs/boot/firmware/config.txt 92 | sed -i 's@__ROOTFS_PARTITION__@3@' rootfs/boot/firmware/config.txt 93 | if [ "${MENDER_DEVICE_TYPE}" == "pi3-v3" ]; then 94 | cp rootfs/boot/image-firmware/bootcode.bin rootfs/boot/firmware/bootcode.bin 95 | cp rootfs/boot/image-firmware/start.elf rootfs/boot/firmware/p3start.elf 96 | cp rootfs/boot/image-firmware/fixup.dat rootfs/boot/firmware/p3fixup.dat 97 | elif [ "${MENDER_DEVICE_TYPE}" == "pi4-v3" ]; then 98 | cp rootfs/boot/image-firmware/start4.elf rootfs/boot/firmware/p3start4.elf 99 | cp rootfs/boot/image-firmware/fixup4.dat rootfs/boot/firmware/p3fixup4.dat 100 | fi 101 | fi 102 | 103 | # Remove /etc/machine-id and /var/lib/dbus/machine-id (it should be unique for each system). 104 | rm rootfs/etc/machine-id 105 | rm rootfs/var/lib/dbus/machine-id 106 | # Add fstab. 107 | cp "${PLUGIN_DIRECTORY}/fstab" rootfs/etc/ 108 | 109 | # Add artifact information to rootfs. 110 | mkdir -p "rootfs/etc/mender/" 111 | echo "artifact_name=${ARTIFACT_NAME}" > rootfs/etc/mender/artifact_info 112 | 113 | # Adjust hostname. 114 | cp "${PLUGIN_DIRECTORY}/hosts" rootfs/etc/ 115 | chmod 0644 rootfs/etc/hosts 116 | sed -i "s@__HOSTNAME__@${HOSTNAME}@" rootfs/etc/hosts 117 | cp "${PLUGIN_DIRECTORY}/hostname" rootfs/etc/ 118 | sed -i "s@__HOSTNAME__@${HOSTNAME}@" rootfs/etc/hostname 119 | 120 | genimage --rootpath rootfs --config "${PLUGIN_DIRECTORY}/genimage.cfg" --tmppath genimage-workdir 121 | 122 | popd > /dev/null 123 | 124 | mv "${TEMPDIR}/images/disk-image.img" "${DISK_IMAGE}" 125 | mv "${TEMPDIR}/images/root.ext4" "${PARTITION_IMAGE}" 126 | 127 | rm -rf "${TEMPDIR}" 128 | trap - EXIT 129 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/mender/ArtifactInstall_Enter_50_BootpartitionSetup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # MIT License 4 | # 5 | # Copyright (c) 2021 Matthias Lüscher 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | set -o nounset 26 | set -o errexit 27 | set -o pipefail 28 | 29 | TRYBOOT_TXT=/boot/firmware/tryboot.txt 30 | NEXT_ROOT_MNT="" 31 | source /data/mender/device_type 32 | 33 | print_and_exit() 34 | { 35 | local TYPE=$1 36 | local MESSAGE=$2 37 | trap - EXIT 38 | if [ "${TYPE}" == "ERROR" ] ; then 39 | >&2 echo "error: ${MESSAGE}" 40 | exit 1 41 | else 42 | echo "${MESSAGE}" 43 | exit 0 44 | fi 45 | } 46 | 47 | trap_exit() 48 | { 49 | trap - EXIT 50 | if [[ -n "${NEXT_ROOT_MNT}" ]] 51 | then 52 | umount "${NEXT_ROOT_MNT}" || true 53 | fi 54 | >&2 echo "Error: Script ${0} failed!" 55 | exit 1 56 | } 57 | 58 | if [[ $EUID -ne 0 ]]; then 59 | print_and_exit "ERROR" "use root user to execute this script" 60 | fi 61 | 62 | trap "trap_exit" EXIT 63 | 64 | CURRENT_BOOT_DEVICE=$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p') 65 | if [ -z "${CURRENT_BOOT_DEVICE}" ] ; then 66 | print_and_exit "ERROR" "unable to detect root partition device" 67 | fi 68 | 69 | CURRENT_BOOT_PART=$(echo "${CURRENT_BOOT_DEVICE}" | grep -o '[1-9][0-9]*$') 70 | if [ -z "${CURRENT_BOOT_PART}" ] ; then 71 | print_and_exit "ERROR" "unable to extract partition number of ${CURRENT_BOOT_DEVICE}" 72 | fi 73 | 74 | BOOT_PART_NUMBER_A=3 75 | BOOT_PART_NUMBER_B=4 76 | 77 | NEXT_BOOT_PART="" 78 | 79 | if [[ ${CURRENT_BOOT_PART} -eq ${BOOT_PART_NUMBER_A} ]] 80 | then 81 | NEXT_BOOT_PART=${BOOT_PART_NUMBER_B} 82 | elif [[ ${CURRENT_BOOT_PART} -eq ${BOOT_PART_NUMBER_B} ]] 83 | then 84 | NEXT_BOOT_PART=${BOOT_PART_NUMBER_A} 85 | else 86 | print_and_exit "ERROR" "unable to determine next boot partition number" 87 | fi 88 | 89 | NEXT_BOOT_FOLDER="/boot/firmware/p${NEXT_BOOT_PART}" 90 | NEXT_ROOT_MNT=$(mktemp -d -t next-root-XXXXXXXX --tmpdir=/tmp) 91 | 92 | mount "/dev/mmcblk0p${NEXT_BOOT_PART}" "${NEXT_ROOT_MNT}" 93 | 94 | rm -rf "${NEXT_BOOT_FOLDER}" 95 | cp -r -L "${NEXT_ROOT_MNT}/boot/image-kernel" "${NEXT_BOOT_FOLDER}" 96 | sed -i "s@^BOOTLOADER_DIRECTORY=.*@BOOTLOADER_DIRECTORY=\"/boot/firmware/p${NEXT_BOOT_PART}\"@" "${NEXT_ROOT_MNT}/etc/edi-boot-shim/edi-boot-shim.cfg.d/multiboot.cfg" 97 | 98 | cp "${NEXT_ROOT_MNT}/boot/image-firmware/cmdline.txt" "${NEXT_BOOT_FOLDER}/cmdline.txt" 99 | sed -i "s@__ROOTFS_PARTITION__@${NEXT_BOOT_PART}@" "${NEXT_BOOT_FOLDER}/cmdline.txt" 100 | 101 | if [ "${device_type}" == "pi3-v3-arm64" ] 102 | then 103 | cp "${NEXT_ROOT_MNT}/boot/image-firmware/start.elf" "/boot/firmware/p${NEXT_BOOT_PART}start.elf" 104 | cp "${NEXT_ROOT_MNT}/boot/image-firmware/fixup.dat" "/boot/firmware/p${NEXT_BOOT_PART}fixup.dat" 105 | elif [ "${device_type}" == "pi4-v3-arm64" ] 106 | then 107 | cp "${NEXT_ROOT_MNT}/boot/image-firmware/start4.elf" "/boot/firmware/p${NEXT_BOOT_PART}start4.elf" 108 | cp "${NEXT_ROOT_MNT}/boot/image-firmware/fixup4.dat" "/boot/firmware/p${NEXT_BOOT_PART}fixup4.dat" 109 | fi 110 | 111 | cp "${NEXT_ROOT_MNT}/boot/image-firmware/config.txt" "${TRYBOOT_TXT}" 112 | sed -i "s@__ROOTFS_PARTITION__@${NEXT_BOOT_PART}@" "${TRYBOOT_TXT}" 113 | 114 | umount "${NEXT_ROOT_MNT}" 115 | 116 | trap - EXIT 117 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/mender/ArtifactInstall_Leave_50_ConfigurationBackup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o nounset 4 | set -o errexit 5 | set -o pipefail 6 | 7 | copy_configuration_files() 8 | { 9 | local src_folder=${1} 10 | local dst_folder=${2} 11 | shift 2 12 | local file_list=("$@") 13 | 14 | mkdir -p ${dst_folder} 15 | 16 | for config_file in "${file_list[@]}" 17 | do 18 | config_file_path="${src_folder}/${config_file}" 19 | if [ -e ${config_file_path} ] 20 | then 21 | cp -a ${config_file_path} ${dst_folder}/ 22 | else 23 | log_message "Info: File ${config_file_path} does not exist." 24 | fi 25 | done 26 | } 27 | 28 | copy_configuration_folders() 29 | { 30 | local src_folder=${1} 31 | local dst_folder=${2} 32 | shift 2 33 | local folder_list=("$@") 34 | 35 | mkdir -p ${dst_folder} 36 | 37 | for config_folder in "${folder_list[@]}" 38 | do 39 | config_folder_path="${src_folder}/${config_folder}" 40 | if [ -e ${config_folder_path} ] 41 | then 42 | cp -a -r ${config_folder_path} ${dst_folder}/ 43 | else 44 | log_message "Info: Folder ${config_folder_path} does not exist." 45 | fi 46 | done 47 | } 48 | 49 | log_message() 50 | { 51 | local message=${1} 52 | 53 | echo "${message}" >> ${backup_log_file_path} 54 | } 55 | 56 | print_error_and_exit() 57 | { 58 | >&2 echo "Error: Script ${0} failed!" 59 | exit 1 60 | } 61 | 62 | trap "print_error_and_exit" EXIT 63 | 64 | if [[ $EUID -ne 0 ]] 65 | then 66 | >&2 echo "Error: Please run this script as root." 67 | trap - EXIT 68 | exit 1 69 | fi 70 | 71 | backup_folder="/data/backup" 72 | backup_log_file_path="${backup_folder}/log" 73 | 74 | ssh_config_folder="/etc/ssh" 75 | ssh_backup_folder="${backup_folder}/ssh" 76 | 77 | ssh_host_key_file_list=( 78 | ssh_host_dsa_key 79 | ssh_host_dsa_key.pub 80 | ssh_host_ecdsa_key 81 | ssh_host_ecdsa_key.pub 82 | ssh_host_ed25519_key 83 | ssh_host_ed25519_key.pub 84 | ssh_host_rsa_key 85 | ssh_host_rsa_key.pub 86 | ) 87 | 88 | network_manager_config_folder="/etc/NetworkManager" 89 | network_manager_backup_folder="${backup_folder}/NetworkManager" 90 | 91 | network_manager_backup_folder_list=( 92 | system-connections 93 | ) 94 | 95 | if [[ ${0} == *ConfigurationBackup* ]] 96 | then 97 | # remove any old backup 98 | rm -rf ${backup_folder} 99 | mkdir -p ${backup_folder} 100 | log_message "*** backup - start ***" 101 | 102 | source /etc/mender/artifact_info 103 | log_message "performing backup on ${artifact_name}" 104 | 105 | log_message "+++ ssh host keys +++" 106 | copy_configuration_files ${ssh_config_folder} ${ssh_backup_folder} ${ssh_host_key_file_list[@]} 107 | 108 | log_message "+++ network manager connections +++" 109 | copy_configuration_folders ${network_manager_config_folder} ${network_manager_backup_folder} ${network_manager_backup_folder_list[@]} 110 | 111 | log_message "*** backup - end ***" 112 | elif [[ ${0} == *ConfigurationRestore* ]] 113 | then 114 | # make sure that the backup folder is present for logging 115 | mkdir -p ${backup_folder} 116 | log_message "*** restore - start ***" 117 | 118 | source /etc/mender/artifact_info 119 | log_message "performing restore on ${artifact_name}" 120 | 121 | # Note: ssh host keys will be restored by dedicated service script. 122 | 123 | log_message "+++ network manager connections +++" 124 | if dpkg -s network-manager > /dev/null 2>&1 125 | then 126 | systemctl stop NetworkManager 127 | copy_configuration_folders ${network_manager_backup_folder} ${network_manager_config_folder} ${network_manager_backup_folder_list[@]} 128 | systemctl start NetworkManager 129 | fi 130 | 131 | log_message "*** restore - end ***" 132 | fi 133 | 134 | trap - EXIT 135 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/mender/ArtifactReboot_Leave_50_ConfigurationRestore: -------------------------------------------------------------------------------- 1 | ArtifactInstall_Leave_50_ConfigurationBackup -------------------------------------------------------------------------------- /plugins/postprocessing_commands/mender/image2mender: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (C) 2020 Matthias Luescher 4 | # 5 | # Authors: 6 | # Matthias Luescher 7 | # 8 | # This file is part of the edi project configuration. 9 | # 10 | # This script is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This script is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with the edi project configuration. If not, see . 22 | 23 | set -o errexit 24 | set -o pipefail 25 | set -o nounset 26 | 27 | print_usage() 28 | { 29 | cat <&2 echo -e "\033[91mError: ${MESSAGE}\033[0m" 48 | } 49 | 50 | print_error_and_exit() 51 | { 52 | local MESSAGE="${1}" 53 | print_error "${MESSAGE}" 54 | exit 1 55 | } 56 | 57 | unexpected_exit() 58 | { 59 | print_error "Going to clean up after abnormal script termination." 60 | rm -f "${MENDER_ARTIFACT}" 61 | trap - EXIT 62 | print_error_and_exit "Abnormal script termination." 63 | } 64 | 65 | if ! options=$(getopt -o hi:o:a:t:b: -l help,log:,input:,output:,artifact:,type:,bootloader: -- "$@") 66 | then 67 | print_usage 68 | print_error_and_exit "Invalid option." 69 | fi 70 | eval set -- "$options" 71 | 72 | SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 73 | INPUT_IMAGE="" 74 | MENDER_ARTIFACT="" 75 | ARTIFACT_NAME="" 76 | DEVICE_TYPE="" 77 | LOG_LEVEL="INFO" 78 | BOOTLOADER="" 79 | 80 | while true 81 | do 82 | case "${1}" in 83 | -h|--help) print_usage && exit 0;; 84 | -i|--input) INPUT_IMAGE="${2}"; shift 2;; 85 | -o|--output) MENDER_ARTIFACT="${2}"; shift 2;; 86 | -a|--artifact) ARTIFACT_NAME="${2}"; shift 2;; 87 | -t|--type) DEVICE_TYPE="${2}"; shift 2;; 88 | -b|--bootloader) BOOTLOADER="${2}"; shift 2;; 89 | --log) LOG_LEVEL="${2}"; shift 2;; 90 | *) break ;; 91 | esac 92 | done 93 | 94 | if [ "${LOG_LEVEL}" == "DEBUG" ]; then 95 | set -x 96 | fi 97 | 98 | if [ -z "${INPUT_IMAGE}" ] 99 | then 100 | print_usage 101 | print_error_and_exit "Missing input image parameter." 102 | fi 103 | 104 | if [ -z "${MENDER_ARTIFACT}" ] 105 | then 106 | print_usage 107 | print_error_and_exit "Missing output artifact parameter." 108 | fi 109 | 110 | if [ -z "${DEVICE_TYPE}" ] 111 | then 112 | print_usage 113 | print_error_and_exit "Missing device type parameter." 114 | fi 115 | 116 | if [ -z "${BOOTLOADER}" ] 117 | then 118 | print_usage 119 | print_error_and_exit "Missing bootloader parameter." 120 | fi 121 | 122 | if ! which mender-artifact > /dev/null 123 | then 124 | print_error "Missing mender-artifact executable. Mender update artifact will not be built." 125 | # Ignore this error for now since the update image might not be needed for every use case. 126 | echo "Mender update artifact not built due to missing mender-artifact executable." >> "${MENDER_ARTIFACT}" 127 | exit 0 128 | fi 129 | 130 | if [ "${DEVICE_TYPE}" == "pi2-armhf" ] 131 | then 132 | COMPATIBLE_DEVICE=( "--device-type" "rpi-armhf" ) 133 | elif [ "${DEVICE_TYPE}" == "pi3-armhf" ] 134 | then 135 | COMPATIBLE_DEVICE=( "--device-type" "rpi-armhf" ) 136 | elif [ "${DEVICE_TYPE}" == "pi3-arm64" ] 137 | then 138 | COMPATIBLE_DEVICE=( "--device-type" "rpi-arm64" ) 139 | else 140 | COMPATIBLE_DEVICE=() 141 | fi 142 | 143 | INPUT_OPTION="--file" 144 | MENDER_ARTIFACT_VERSION=$(mender-artifact --version) 145 | MENDER_ARTIFACT_MAJOR_VERSION=$(echo "${MENDER_ARTIFACT_VERSION}" | cut -d' ' -f 3 | cut -d'.' -f 1) 146 | 147 | if [[ ${MENDER_ARTIFACT_MAJOR_VERSION} -eq 2 ]] 148 | then 149 | INPUT_OPTION="--update" 150 | fi 151 | 152 | # Special treatment for the Debian buster mender-artifact package: 153 | if [[ ${MENDER_ARTIFACT_VERSION} == *"really2"* ]] 154 | then 155 | INPUT_OPTION="--update" 156 | fi 157 | 158 | BOOTPARTITION_SETUP_SCRIPT=() 159 | if [ "${BOOTLOADER}" == "raspberry-pi" ] 160 | then 161 | BOOTPARTITION_SETUP_SCRIPT=( "--script" "${SCRIPTDIR}/ArtifactInstall_Enter_50_BootpartitionSetup" ) 162 | fi 163 | 164 | mender-artifact write rootfs-image --device-type "${DEVICE_TYPE}" "${COMPATIBLE_DEVICE[@]}" \ 165 | --artifact-name "${ARTIFACT_NAME}" ${INPUT_OPTION} "${INPUT_IMAGE}" --version 3 \ 166 | --script "${SCRIPTDIR}/ArtifactInstall_Leave_50_ConfigurationBackup" \ 167 | --script "${SCRIPTDIR}/ArtifactReboot_Leave_50_ConfigurationRestore" \ 168 | "${BOOTPARTITION_SETUP_SCRIPT[@]}" \ 169 | --output-path "${MENDER_ARTIFACT}" 170 | 171 | trap - EXIT 172 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/mender/image2mender.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o nounset 4 | set -o errexit 5 | 6 | source {{ pp_timestamp }} 7 | 8 | {{ edi_current_plugin_directory }}/image2mender --input {{ pp_partition_image }} --output {{ pp_mender_artifact }} --log {{ edi_log_level }} --artifact ${BUILD_TIMESTAMP}-{{ edi_configuration_name }}-{{ debian_distribution_release }}-{{ edi_bootstrap_architecture }} --type {{ mender_device_type }}-{{ edi_bootstrap_architecture }} --bootloader {{ ebs_bootloader_type }} -------------------------------------------------------------------------------- /plugins/postprocessing_commands/rootfs/buildah2rootfs.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | WORKDIR="{{ edi_work_directory }}" 8 | CONTAINER_NAME="{{ edi_project_container }}" 9 | ROOTFS_ARCHIVE="{{ pp_rootfs_archive }}" 10 | LOG_LEVEL="{{ edi_log_level }}" 11 | 12 | print_error() 13 | { 14 | local MESSAGE="${1}" 15 | >&2 echo -e "\033[91mError: ${MESSAGE}\033[0m" 16 | } 17 | 18 | print_error_and_exit() 19 | { 20 | local MESSAGE="${1}" 21 | print_error "${MESSAGE}" 22 | exit 1 23 | } 24 | 25 | unexpected_exit() 26 | { 27 | local TEMPDIR="${1}" 28 | print_error "Going to clean up after abnormal script termination." 29 | clean_up "${TEMPDIR}" 30 | trap - EXIT 31 | print_error_and_exit "Abnormal script termination." 32 | } 33 | 34 | clean_up() 35 | { 36 | local TEMPDIR="${1}" 37 | rm -rf "${TEMPDIR}" 38 | } 39 | 40 | if [ "${LOG_LEVEL}" == "DEBUG" ]; then 41 | set -x 42 | fi 43 | 44 | if [[ ${EUID} -eq 0 ]]; then 45 | print_error_and_exit "This script must not be run as root." 46 | fi 47 | 48 | if ! buildah inspect "${CONTAINER_NAME}" > /dev/null 2>&1; then 49 | print_error_and_exit "The container ${CONTAINER_NAME} does not exist." 50 | fi 51 | 52 | TEMPDIR="$(mktemp -p ${WORKDIR} -d -t .tmp.XXXXXXXX)" 53 | 54 | trap "unexpected_exit ${TEMPDIR}" EXIT 55 | 56 | TEMP_ARCHIVE="${TEMPDIR}/archive.tar" 57 | NESTED_COMMAND="tar --numeric-owner -C "'"${container_root}"'" -acf ${TEMP_ARCHIVE} ." 58 | buildah unshare --mount container_root="${CONTAINER_NAME}" -- bash -c "${NESTED_COMMAND}" 59 | 60 | mv "${TEMP_ARCHIVE}" "${ROOTFS_ARCHIVE}" 61 | 62 | clean_up "${TEMPDIR}" 63 | 64 | trap - EXIT 65 | 66 | -------------------------------------------------------------------------------- /plugins/postprocessing_commands/timestamp/timestamp.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | echo "BUILD_TIMESTAMP=$(date +'%Y-%m-%d-%H%M')" > {{ pp_timestamp }} 7 | 8 | -------------------------------------------------------------------------------- /plugins/preprocessing_commands/bootstrap/mmdebstrap.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o nounset 4 | set -o errexit 5 | 6 | LOG_LEVEL="{{ edi_log_level }}" 7 | ROOTFS_ARCHIVE="{{ edi_bootstrapped_rootfs }}" 8 | DISTRIBUTION_RELEASE="{{ debian_distribution_release }}" 9 | DEBIAN_ARCHITECTURE="{{ edi_bootstrap_architecture }}" 10 | WORKDIR="{{ edi_work_directory }}" 11 | QEMU_EMULATED_CPU="{{ qemu_emulated_cpu }}" 12 | 13 | print_error() 14 | { 15 | local MESSAGE="${1}" 16 | >&2 echo -e "\033[91mError: ${MESSAGE}\033[0m" 17 | } 18 | 19 | print_error_and_exit() 20 | { 21 | local MESSAGE="${1}" 22 | print_error "${MESSAGE}" 23 | exit 1 24 | } 25 | 26 | unexpected_exit() 27 | { 28 | local TEMPDIR="${1}" 29 | print_error "Going to clean up after abnormal script termination." 30 | rm -rf "${TEMPDIR}" 31 | trap - EXIT 32 | print_error_and_exit "Abnormal script termination." 33 | } 34 | 35 | if [ "${LOG_LEVEL}" == "DEBUG" ]; then 36 | set -x 37 | fi 38 | 39 | TEMPDIR="$(mktemp -p "${WORKDIR}" -d -t .tmp.XXXXXXXX)" 40 | trap "unexpected_exit ${TEMPDIR}" EXIT 41 | 42 | if [ ! -z "${QEMU_EMULATED_CPU}" ]; then 43 | export QEMU_CPU="${QEMU_EMULATED_CPU}" 44 | fi 45 | 46 | TEMP_ARCHIVE="${TEMPDIR}/archive.tar" 47 | mmdebstrap --include=python3-apt,sudo,systemd,systemd-sysv --arch="${DEBIAN_ARCHITECTURE}" --variant=minbase "${DISTRIBUTION_RELEASE}" "${TEMP_ARCHIVE}" 48 | 49 | mv "${TEMP_ARCHIVE}" "${ROOTFS_ARCHIVE}" 50 | 51 | rm -rf "${TEMPDIR}" 52 | trap - EXIT 53 | -------------------------------------------------------------------------------- /plugins/preprocessing_commands/prerequisites/check_prerequisites: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o nounset 4 | set -o errexit 5 | set -o pipefail 6 | 7 | required_packages=( 8 | "ansible-core 2.14.16" 9 | "buildah 1.28.2" 10 | "mmdebstrap 1.3.5" 11 | ) 12 | 13 | is_package_installed() 14 | { 15 | local package="${1}" 16 | # shellcheck disable=SC2091 17 | dpkg -s "${package}" > /dev/null 2>&1 18 | } 19 | 20 | version_greater_equal() 21 | { 22 | local lhs_version="${1}" 23 | local rhs_version="${2}" 24 | [ "$(echo -e "${lhs_version}\n${rhs_version}" | sort --reverse --version-sort | head -n 1)" == "${lhs_version}" ] 25 | } 26 | 27 | check_passed=0 28 | 29 | for item in "${required_packages[@]}" 30 | do 31 | IFS=' ' read -r package required_version <<< "${item}" 32 | if is_package_installed "${package}" 33 | then 34 | actual_version=$(dpkg-query --showformat='${Version}' --show "${package}") 35 | if version_greater_equal "${actual_version}" "${required_version}" 36 | then 37 | echo "${package} $actual_version: OK" 38 | else 39 | echo "${package} $actual_version: NOK" 40 | >&2 echo "Error: Package ${package} does not meet the version requirements (>= ${required_version})!" 41 | check_passed=1 42 | fi 43 | else 44 | echo "${package} (missing): NOK" 45 | >&2 echo "Error: Package ${package} is not installed!" 46 | check_passed=1 47 | fi 48 | done 49 | 50 | exit "${check_passed}" 51 | -------------------------------------------------------------------------------- /plugins/preprocessing_commands/prerequisites/check_prerequisites.edi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o nounset 4 | set -o errexit 5 | set -o pipefail 6 | 7 | PLUGIN_DIRECTORY="{{ edi_current_plugin_directory }}" 8 | OUTPUT="{{ edi_prerequisites_log }}" 9 | 10 | if result=$("${PLUGIN_DIRECTORY}"/check_prerequisites) 11 | then 12 | echo "${result}" > "${OUTPUT}" 13 | exit 0 14 | else 15 | exit 1 16 | fi -------------------------------------------------------------------------------- /ssh_pub_keys/README.txt: -------------------------------------------------------------------------------- 1 | All ssh public keys within this folder will be added to the authorized_keys 2 | file (/home/pi/.ssh/authorized_keys) of the pi user of the generated target 3 | system (container or OS image). 4 | 5 | This will then allow the corresponding people to have a convenient access 6 | to the target system using ssh (e.g. ssh pi@IP_OF_TARGET_SYSTEM). 7 | 8 | This is especially useful within a company setup where one employee (or a build 9 | server) generates the images and multiple other employees want to access the 10 | systems that are running those images in a secure way without sharing a static 11 | password. 12 | 13 | This folder of course will remain empty within this repository but you can do 14 | your private fork and add public keys there. 15 | 16 | The extension of the public key files must be .pub. 17 | 18 | Examples: 19 | coworker1_id_rsa.pub 20 | coworker2_id_rsa.pub 21 | ben.pub 22 | karl_id_rsa.pub 23 | 24 | For your convenience there is also a second mechanism in place that adds the public 25 | key of the user that generates the artifacts. This is part of the "base_system" Ansible 26 | playbook plugin (you can use "authorize_current_user: False" to turn this feature off). 27 | For more details please take a look at this documentation: 28 | https://docs.get-edi.io/en/latest/config_management/plugins.html 29 | 30 | For even more information please read this blog post: 31 | https://www.get-edi.io/Secure-by-Default-ssh-Setup/ 32 | 33 | Please note that password based login via ssh is disabled by default within this 34 | edi project configuration. 35 | --------------------------------------------------------------------------------