Skip to content

Commit

Permalink
make rauc updates possible
Browse files Browse the repository at this point in the history
fix self-signing and upload rauc bundle
  • Loading branch information
honsma235 authored and citruz committed Nov 9, 2024
1 parent bdbfad2 commit 0b320b4
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 12 deletions.
39 changes: 36 additions & 3 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,21 @@ jobs:
run: |
sed -i -E "s/(^VERSION_SUFFIX=\").*(\"$)/\1${VERSION_DEV}\2/" buildroot-external/meta
- name: 'Add release PKI certs'
if: ${{ needs.prepare.outputs.self_signed_cert != 'true' }}
env:
RAUC_CERTIFICATE: ${{ secrets.RAUC_CERTIFICATE }}
RAUC_PRIVATE_KEY: ${{ secrets.RAUC_PRIVATE_KEY }}
run: |
echo -e "-----BEGIN CERTIFICATE-----\n${RAUC_CERTIFICATE}\n-----END CERTIFICATE-----" > cert.pem
echo -e "-----BEGIN PRIVATE KEY-----\n${RAUC_PRIVATE_KEY}\n-----END PRIVATE KEY-----" > key.pem
- name: Get self-signed certificate from the prepare job
if: ${{ needs.prepare.outputs.self_signed_cert == 'true' }}
uses: actions/download-artifact@v4
with:
name: signing-key

- name: Build
run: |
BUILDER_UID="$(id -u)"
Expand All @@ -224,8 +239,26 @@ jobs:
BR2_CHECK_DOTCONFIG_OPTS="--github-format --strip-path-prefix=/build/" linux-check-dotconfig
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: haos-image
path: output/images/haos_*.img.xz
name: haos-image-${{ matrix.board.id }}
path: |
output/images/haos_*.img.xz
output/images/haos_*.raucb
if-no-files-found: error

- name: Generate build summary
run: |
echo "# ${{ matrix.board.id }} build summary" >> $GITHUB_STEP_SUMMARY
echo "## Artifacts" >> $GITHUB_STEP_SUMMARY
echo "| File | Size (bytes) | Size (formatted) |" >> $GITHUB_STEP_SUMMARY
echo "|:-|:-|:-|" >> $GITHUB_STEP_SUMMARY
for f in output/images/haos_*; do
echo "| $(basename $f) | $(du -b $f | cut -f1) | $(du -bh $f | cut -f1) |" >> $GITHUB_STEP_SUMMARY
done
echo "## Partitions" >> $GITHUB_STEP_SUMMARY
echo "| File | Size (bytes) | Size (formatted) |" >> $GITHUB_STEP_SUMMARY
echo "|:-|:-|:-|" >> $GITHUB_STEP_SUMMARY
for f in boot.vfat kernel.img rootfs.erofs overlay.ext4 data.ext4; do
echo "| ${f} | $(du -b output/images/$f | cut -f1) | $(du -bh output/images/$f | cut -f1) |" >> $GITHUB_STEP_SUMMARY
done
50 changes: 47 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,55 @@ With this setup you always need to have an SD card inserted from which the board
1. Insert SD card into board and boot
1. There might be some error messages like `find_valid_gpt: *** ERROR: Invalid GPT ***`. These are expected because U-Boot will attempt to find the boot partition on SD card first (it's not there). It should then recognize the NVMe SSD and boot from it.

## Automatic updates
## Upgrading

Since this is an unofficial fork of Homeassistant OS, the OS image cannot be updated over the air (supervisor, core and all other components can be updated just fine). You will need to reflash for each release.
Since this is an unofficial fork of Homeassistant OS, the OS image cannot be updated from the UI (supervisor, core and all other components can be updated just fine). Instead, the update process is triggered via SSH from the command line.

**Always create a full backup before upgrading to avoid data loss.**

Use the [HassOS SSH port Configurator](https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109) to enable ssh root access on port 22222 (the "Terminal & SSH" Add-on will not work as it only exposes a limited shell in a container).

Connect to the device and run the following command. Replace the URL with the appropriate link from the Releases page for your device. Make sure to copy the `.raucb` URL, not the `.img.xz`.

```
rauc install https://github.com/citruz/haos-rockpi/releases/download/<release>/haos_<device>-<release>.raucb
```

The file will be downloaded to a temporary location in `/mnt/data/tmp/` so make sure that there is enough space on the data partition left.

```
# rauc install https://github.com/citruz/haos-rockpi/releases/download/ota-test/haos_rockpi-4b-plus-12.2.dev20240502.raucb
installing
0% Installing
0% Determining slot states
10% Determining slot states done.
10% Checking bundle
10% Verifying signature
20% Verifying signature done.
20% Checking bundle done.
20% Checking manifest contents
30% Checking manifest contents done.
30% Determining target install group
40% Determining target install group done.
40% Updating slots
40% Checking slot boot.0
41% Checking slot boot.0 done.
41% Copying image to boot.0
...
99% Copying image to spl.0 done.
99% Updating slots done.
100% Installing done.
Installing `https://github.com/citruz/haos-rockpi/releases/download/ota-test/haos_rockpi-4b-plus-12.2.dev20240502.raucb` succeeded
```

Now reboot the device to switch to the new OS version.

This process also updates the bootloader. If it detects that the system is booted from an SSD it will update the bootloader on the eMMC or SD card.

If there is an error during installation, run `journalctl -u rauc.service` to get an extended output log.

**Note:** The OTA update functionality was added in 12.3. To upgrade from an earlier version to 12.3 or later a few extra steps are required. Please refer to the the 12.3 release notes for detailed instructions.

However, HA's built-in backup and restore functionality works great so there should be no dataloss. Make sure to create a "Full Backup" and download it before flashing a new image.

## Hardware support

Expand Down
19 changes: 19 additions & 0 deletions buildroot-external/ota/rauc-hook
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ install_spl() {
dd if="${RAUC_IMAGE_NAME}" of="${DEVICE_ROOT}boot0" conv=notrunc ${FLAGS} bs=512 skip=1 count=2047
echo 1 > /sys/block/"$(basename "${DEVICE_ROOT}boot0")"/force_ro
fi

# Rock Pi: Check if we are booting from SSD and flash bootloader to eMMC/SD
if case "${DEVICE_ROOT}" in "/dev/nvme"*) true;; *) false;; esac; then
# make sure there are no partitions for the device we're writing to.
# if there are any, this is not the expected configuration so rather
# error out than overwrite something unrelated.
if [ -b "/dev/mmcblk0" ] && ! [ -b "/dev/mmcblk0p1" ]; then
echo "Updating bootloader in eMMC/SD mmcblk0"
dd if="${RAUC_IMAGE_NAME}" of="/dev/mmcblk0" conv=notrunc ${FLAGS} bs=512 seek=64 skip=64
elif [ -b "/dev/mmcblk1" ] && ! [ -b "/dev/mmcblk1p1" ]; then
echo "Updating bootloader in eMMC/SD mmcblk1"
dd if="${RAUC_IMAGE_NAME}" of="/dev/mmcblk1" conv=notrunc ${FLAGS} bs=512 seek=64 skip=64
else
echo "Boot from SSD detected but got unexpected device configuration."
echo "Please open an issue on Github with the following output:"
lsblk
exit 1
fi
fi
}

check_grubenv() {
Expand Down
95 changes: 95 additions & 0 deletions buildroot-external/ota/rockpi-ca.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
37:51:55:9e:0a:d3:6b:d7:5e:c0:5a:13:2c:58:8b:ba:a5:18:34:24
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = HassOS RockPi CA Root
Validity
Not Before: Apr 28 17:20:10 2024 GMT
Not After : Apr 26 17:20:10 2034 GMT
Subject: CN = HassOS RockPi CA Root
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:b2:20:99:2c:65:eb:40:0c:8c:bd:2b:4b:ca:9e:
6e:b9:b4:ef:84:83:a4:d3:f1:e6:d0:fd:70:d0:ce:
5b:a2:96:e6:58:06:4c:bf:7b:17:ad:fb:5d:f3:45:
60:04:58:40:5d:11:72:f1:9e:34:dc:ac:03:4b:d2:
dc:be:64:b6:05:4d:dc:33:dc:28:e4:2f:3f:75:ce:
d9:c3:da:bd:34:69:06:44:4a:b2:f1:7c:e2:7e:e3:
bf:71:9a:d1:23:94:8f:39:96:e7:7e:9b:30:68:11:
88:fe:27:07:f7:81:73:65:a5:ab:82:07:bc:98:d3:
36:b7:cf:a5:82:e5:91:4f:9d:57:bc:fc:68:fe:5b:
a8:b9:8b:0a:00:7f:da:3f:30:83:e9:01:70:50:66:
1f:32:8d:32:92:6e:e5:1a:81:42:56:75:b6:e5:87:
32:45:53:52:a7:25:c2:9c:59:29:dd:80:b7:0e:fd:
eb:01:dd:b1:d9:25:a8:2f:09:13:41:30:8b:d2:b9:
cc:07:9f:82:bd:8d:d8:d9:ce:45:dd:38:05:4b:c5:
79:35:ce:c0:4a:27:97:c9:b4:87:7a:4a:be:42:ab:
07:09:c1:27:cd:2d:51:c3:24:ac:50:be:3e:da:3a:
4b:7b:ba:67:77:dc:79:e5:4c:70:0c:02:b1:bd:de:
a5:89
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
E1:19:4C:24:5A:ED:0A:BB:FE:9D:B3:88:A7:11:A0:92:47:AD:8B:FD
X509v3 Authority Key Identifier:
keyid:E1:19:4C:24:5A:ED:0A:BB:FE:9D:B3:88:A7:11:A0:92:47:AD:8B:FD
DirName:/CN=HassOS RockPi CA Root
serial:37:51:55:9E:0A:D3:6B:D7:5E:C0:5A:13:2C:58:8B:BA:A5:18:34:24
X509v3 Basic Constraints:
CA:TRUE
X509v3 Key Usage:
Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
7e:94:20:ab:02:8f:32:90:af:57:63:1f:e3:ef:25:28:88:73:
67:f6:bb:a9:95:56:78:30:40:51:77:c1:35:ec:11:a0:f1:51:
e1:2b:66:02:80:3e:73:20:3a:bc:17:fe:cc:a2:a0:33:0f:9c:
5f:90:29:fc:43:ff:c6:ff:29:3c:35:6a:19:9d:cc:10:40:f0:
b1:db:08:3f:54:c6:ec:71:d2:2c:95:88:a4:76:b3:df:87:0d:
27:cb:51:39:7d:a9:69:17:75:8f:96:db:0f:dc:b4:27:1a:0b:
24:5b:c0:7a:98:88:c5:e5:ac:21:a8:9a:f5:f5:f5:b2:e7:6d:
17:fa:cf:1f:6f:c3:c9:2f:76:4e:55:07:96:03:34:6e:68:ec:
7f:e0:71:3b:e7:a3:a7:f7:94:e7:49:8f:51:9a:3b:54:ef:d0:
dd:29:2d:40:ce:4d:45:04:f7:83:1b:ce:22:ea:e7:dc:de:36:
39:7c:4f:1f:69:a6:63:3d:87:a6:85:f0:e9:e7:32:ae:e1:0e:
28:23:57:f3:3d:5a:51:8c:d4:6c:64:6c:14:18:04:ef:24:5b:
df:4b:1c:40:39:75:c2:a6:5a:d1:2f:0b:c5:40:1b:7a:1a:14:
db:1d:ad:8b:67:14:cc:cb:b3:5f:4d:85:5c:f6:e1:60:57:50:
e7:de:7b:14
-----BEGIN CERTIFICATE-----
MIIDaTCCAlGgAwIBAgIUN1FVngrTa9dewFoTLFiLuqUYNCQwDQYJKoZIhvcNAQEL
BQAwIDEeMBwGA1UEAwwVSGFzc09TIFJvY2tQaSBDQSBSb290MB4XDTI0MDQyODE3
MjAxMFoXDTM0MDQyNjE3MjAxMFowIDEeMBwGA1UEAwwVSGFzc09TIFJvY2tQaSBD
QSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiCZLGXrQAyM
vStLyp5uubTvhIOk0/Hm0P1w0M5bopbmWAZMv3sXrftd80VgBFhAXRFy8Z403KwD
S9LcvmS2BU3cM9wo5C8/dc7Zw9q9NGkGREqy8XzifuO/cZrRI5SPOZbnfpswaBGI
/icH94FzZaWrgge8mNM2t8+lguWRT51XvPxo/luouYsKAH/aPzCD6QFwUGYfMo0y
km7lGoFCVnW25YcyRVNSpyXCnFkp3YC3Dv3rAd2x2SWoLwkTQTCL0rnMB5+CvY3Y
2c5F3TgFS8V5Nc7ASieXybSHekq+QqsHCcEnzS1RwySsUL4+2jpLe7pnd9x55Uxw
DAKxvd6liQIDAQABo4GaMIGXMB0GA1UdDgQWBBThGUwkWu0Ku/6ds4inEaCSR62L
/TBbBgNVHSMEVDBSgBThGUwkWu0Ku/6ds4inEaCSR62L/aEkpCIwIDEeMBwGA1UE
AwwVSGFzc09TIFJvY2tQaSBDQSBSb290ghQ3UVWeCtNr117AWhMsWIu6pRg0JDAM
BgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAfpQg
qwKPMpCvV2Mf4+8lKIhzZ/a7qZVWeDBAUXfBNewRoPFR4StmAoA+cyA6vBf+zKKg
Mw+cX5Ap/EP/xv8pPDVqGZ3MEEDwsdsIP1TG7HHSLJWIpHaz34cNJ8tROX2paRd1
j5bbD9y0JxoLJFvAepiIxeWsIaia9fX1sudtF/rPH2/DyS92TlUHlgM0bmjsf+Bx
O+ejp/eU50mPUZo7VO/Q3SktQM5NRQT3gxvOIurn3N42OXxPH2mmYz2HpoXw6ecy
ruEOKCNX8z1aUYzUbGRsFBgE7yRb30scQDl1wqZa0S8LxUAbehoU2x2ti2cUzMuz
X02FXPbhYFdQ5957FA==
-----END CERTIFICATE-----
-----BEGIN X509 CRL-----
MIIByjCBswIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVIYXNzT1MgUm9j
a1BpIENBIFJvb3QXDTI0MDQyODE3NTE1MloXDTI0MTAyNTE3NTE1MlqgXzBdMFsG
A1UdIwRUMFKAFOEZTCRa7Qq7/p2ziKcRoJJHrYv9oSSkIjAgMR4wHAYDVQQDDBVI
YXNzT1MgUm9ja1BpIENBIFJvb3SCFDdRVZ4K02vXXsBaEyxYi7qlGDQkMA0GCSqG
SIb3DQEBCwUAA4IBAQABV99wPJlXWfK6VQ+sN1701FJZLcr9HPrM3CO1jqtF1e+i
iBDwhOjl2HATDbUJkmCz7647HHNQ0NTRZkI69LEyzjhURsyvG8Kn1VBzFV21Jca2
ni/IWqS6UgvwLNqMWob13aHwF4OZezPVafq1/oDhlCy2dCkmqN0brIzknc4Zh0M7
WaEOLKQtxJRPZl0B6n+2pLXaRO7ZvwPgwcel9aFjAvN8LuZsxQ/fZ2NV7lXPkb6v
7LzYtpY51mhHGj5YOHuHeHF1iYFUnPgECyEsGgvuHXLtKF31GUdSiRv4AwG8tLj8
5VUEKzrdKNhgL48xIWXjiwWGv925czhvH5ZnkaDb
-----END X509 CRL-----
1 change: 1 addition & 0 deletions buildroot-external/ota/system.conf.gtpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
compatible={{ env "ota_compatible" }}
mountprefix=/run/rauc
statusfile=/mnt/data/rauc.db
max-bundle-download-size=314572800
{{- if eq (env "BOOTLOADER") "tryboot" }}
bootloader=custom
{{- else }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# change tmp dir to allow download of large bundles
[Unit]
RequiresMountsFor=/mnt/data

[Service]
Environment=TMPDIR=/mnt/data/tmp
ExecStartPre=/usr/bin/mkdir -p /mnt/data/tmp
7 changes: 1 addition & 6 deletions buildroot-external/scripts/rauc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,7 @@ function write_rauc_config() {
function install_rauc_certs() {
local cert="/build/cert.pem"

if [ "${DEPLOYMENT}" == "development" ]; then
# Contains development and release certificate
cp "${BR2_EXTERNAL_HASSOS_PATH}/ota/dev-ca.pem" "${TARGET_DIR}/etc/rauc/keyring.pem"
else
cp "${BR2_EXTERNAL_HASSOS_PATH}/ota/rel-ca.pem" "${TARGET_DIR}/etc/rauc/keyring.pem"
fi
cp "${BR2_EXTERNAL_HASSOS_PATH}/ota/rockpi-ca.pem" "${TARGET_DIR}/etc/rauc/keyring.pem"

# Add local self-signed certificate (if not trusted by the dev or release
# certificate it is a self-signed certificate, dev-ca.pem contains both)
Expand Down

0 comments on commit 0b320b4

Please sign in to comment.