GrapheneOS over the air updates (OTAs) patched with Magisk using avbroot allowing for AVB and locked bootloader and root access. Provides its own OTA server for Custota magisk module.
- Make sure the versions of the unpatched version initially installed and the one taken from this repo match.
- You might want to start with the version before the latest to try if OTA is working before initializing your device.
- Don't mix up factory image and OTA
- The following steps are basically the ones described at avbroot using the
avb_pkmd.bin
from this repo.
Download factory image and follow the official instructions to install GrapheneOS.
TLDR:
-
Enable OEM unlocking
-
Obtain latest
fastboot
-
Unlock Bootloader: Enable usb debugging and execute
adb reboot bootloader
, or >The easiest approach is to reboot the device and begin holding the volume down button until it boots up into the bootloader interface.fastboot flashing unlock
-
flash factory image
tar xvf DEVICE_NAME-factory-VERSION.zip ./flash-all.sh # or .bat on windows
-
Stop after that and reboot (leave bootloader unlocked)
- Download the OTA from releases with the same version that you just installed.
- Extract the partition images from the patched OTA that are different from the original.
avbroot ota extract \ --input /path/to/ota.zip.patched \ --directory extracted
- Flash the partition images that were extracted.
For each partition insideextracted/
, except forsystem
, run:fastboot flash <partition> extracted/<partition>.img
- Then, reboot into recovery's fastbootd mode and flash
system
:fastboot reboot fastboot fastboot flash system extracted/system.img
- Set up the custom AVB public key in the bootloader.
fastboot reboot-bootloader fastboot erase avb_custom_key curl -s https://raw.githubusercontent.com/schnatterer/rooted-graphene/main/avb_pkmd.bin > avb_pkmd.bin fastboot flash avb_custom_key avb_pkmd.bin
- [Optional] Before locking the bootloader, reboot into Android once to confirm that everything is properly signed.
Install the Magisk or KernelSU app and run the following command:If AVB is working properly, the following message should be printed out:adb shell su -c 'dmesg | grep libfs_avb'
init: [libfs_avb]Returning avb_handle with status: Success
- Reboot back into fastboot and lock the bootloader. This will trigger a data wipe again.
fastboot flashing lock
- Confirm by pressing volume down and then power. Then reboot.
- Remember: Do not uncheck
OEM unlocking
!
- Disable system updater app.
- You could either do updates manually using
adb sideload
(see here), - or use the Custota magisk module.
- To do so, download and install the Custota module in magsik and reboot.
- Open Custota and set the OTA server URL to point to this OTA server: https://schnatterer.github.io/rooted-graphene/magisk
You can use the script in this repo to create your own OTAs and run your own OTA server.
# Generate keys
bash -c 'source rooted-ota.sh && generateKeys'
# Enter passphrases interactively
DEVICE_ID=oriole MAGISK_PREINIT_DEVICE='metadata' bash -c '. rooted-ota.sh && createRootedOta'
# Enter passphrases via env (e.g. on CI)
export PASSPHRASE_AVB=1
export PASSPHRASE_OTA=1
DEVICE_ID=oriole MAGISK_PREINIT_DEVICE='metadata' bash -c '. rooted-ota.sh && createRootedOta'
For IDs see grapheneos.org/releases. For Magisk preinit see,e.g. here.
See GitHub action for automating this.
GITHUB_TOKEN=gh... \
GITHUB_REPO=schnatterer/rooted-ota \
DEVICE_ID=oriole \
MAGISK_PREINIT_DEVICE=metadata \
bash -c '. rooted-ota.sh && createAndReleaseRootedOta'
# DEBUG some parts of the script interactively
DEBUG=1 bash --init-file rooted-ota.sh
# Test loading secrets from env
PASSPHRASE_AVB=1 PASSPHRASE_OTA=1 bash -c '. rooted-ota.sh && key2base64 && KEY_AVB=doesnotexist createAndReleaseRootedOta'
# Avoid having to download OTA all over again: SKIP_CLEANUP=true or:
mkdir -p .tmp && ln -s $PWD/shiba-ota_update-2023121200.zip .tmp/shiba-ota_update-2023121200.zip
# Test only releasing
GITHUB_TOKEN=gh... \
RELEASE_ID='' \
ASSET_EXISTS=false \
POTENTIAL_RELEASE_NAME=test \
POTENTIAL_ASSET_NAME=test.zip \
GITHUB_REPO=schnatterer/rooted-ota \
bash -c '. rooted-ota.sh && releaseOta'
# Test only GH pages deployment
GITHUB_REPO=schnatterer/rooted-ota \
DEVICE_ID=oriole \
MAGISK_PREINIT_DEVICE=metadata \
bash -c '. rooted-ota.sh && findLatestVersion && checkBuildNecessary && createOtaServerData && uploadOtaServerData'
# e2e test
GITHUB_TOKEN=gh... \
GITHUB_REPO=schnatterer/rooted-ota \
DEVICE_ID=oriole \
MAGISK_PREINIT_DEVICE=metadata \
SKIP_CLEANUP=true \
DEBUG=1 \
bash -c '. rooted-ota.sh && createAndReleaseRootedOta'
preinit["cheetah"]="persist" # Pixel Pro 7 https://xdaforums.com/t/guide-to-lock-bootloader-while-using-rooted-otaos-magisk-root.4510295/page-5#post-88499289)
preinit["oriole"]="=metadata" # Pixel 6
preinit["shiba"]="=sda10" # Pixel 8
How to extract:
- Get boot.img either from factory image or from OTA via
avbroot ota extract \ --input /path/to/ota.zip \ --directory . \ --boot-only
- Install magisk, patch boot.img, look for this string in the output:
Pre-init storage partition device ID: <name>
- Alternatively extract from the pachted boot.img:
avbroot boot magisk-info \ --image magisk_patched-*.img
- See also: https://github.com/chenxiaolong/avbroot/blob/master/README.md#magisk-preinit-device
https://github.com/MuratovAS/grapheneos-magisk/blob/main/docker/Dockerfile
https://xdaforums.com/t/guide-to-lock-bootloader-while-using-rooted-otaos-magisk-root.4510295/