PixeneOS is a shell
script designed to patch GrapheneOS OTA (Over The Air) images with custom modules, providing additional features. This tool relies heavily on upstream projects for its functionality.
- BCR (>= version 1.65)
- Custota (>= version 4.5)
- Magisk (>= version 27006) -- optional
- MSD
- OEMUnlockOnBoot (>= version 1.1)
Note
- This project is not affiliated with GrapheneOS or any of the mentioned projects. It is a personal project for personal use.
- Currently, the project only supports Linux due to compatibility issues with other operating systems (
libsepol
is highly Linux-specific).
To use this project, you need the following (most dependencies will be handled by the script, except for git
and python
):
- A Linux machine is recommended.
WSL
(Windows Subsystem for Linux) or aVM
(Virtual Machine) can also be used instead - Tools (must be in the path):
git
python
avbroot
afsr
custota-tool
- Modules:
BCR
Custota
Magisk
MSD
OEMUnlockOnBoot
- Dependencies:
e2fsprogs
pkg-config
tomlkit
(Python dependency)
This repository acts as a server.
- Release.yml checks if a build already exists. If only the
rootless
flavor exists and the user opts for themagisk
flavor, it builds it, and vice versa. If both flavors exist for a specific version and device, it skips the build. - The workflow calls the build script, which downloads all the requirements and patches the OTA by adding your signing key and installing the additional packages mentioned in the features section.
- The patched OTA is released and available in the releases section.
- The server branch is updated based on the selected flavor (
rootless
is the default).
Reading the AVBRoot docs is essential before proceeding with PixeneOS.
- Ensure the device has an unpatched version of GrapheneOS installed. The version must match the one from PixeneOS.
- Start with a version before the latest to ensure OTA functionality.
Important
Factory image
and OTA image
are different. This project deals with OTA images.
-
Ensure Fastboot version is
34
or newer.35
or above is recommended as older versions are known to have bugs that prevent commands likefastboot flashall
from running.fastboot --version
-
Reboot into
fastboot
mode and unlock the bootloader if not already. This will trigger a data wipe. Ensure data is backed up.fastboot flashing unlock
-
When setting PixeneOS up for the first time, the device must already be running the correct OS. Flash the original unpatched OTA or factory image if needed.
bsdtar xvf DEVICE_NAME-factory-VERSION.zip # tar on Windows and macOS ./flash-all.sh # or .bat on Windows
-
Download the OTA from the releases. Ensure the version matches the installed version.
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 \ --fastboot
To extract and flash all OS partitions, pass
--all
. -
Set the
ANDROID_PRODUCT_OUT
environment variable to the directory containing the extracted files.For
sh
/bash
/zsh
(Linux, macOS, WSL):export ANDROID_PRODUCT_OUT=extracted
For PowerShell (Windows):
$env:ANDROID_PRODUCT_OUT = "extracted"
For cmd (Windows):
set ANDROID_PRODUCT_OUT=extracted
-
Flash the partition images.
fastboot flashall --skip-reboot
Note: This only flashes the OS partitions. The bootloader and modem/radio partitions are left untouched due to fastboot limitations. If they are not already up to date or if unsure, after fastboot completes, follow the steps in the updates section to sideload the patched OTA once. Sideloading OTAs always ensures that all partitions are up to date.
Alternatively, for Pixel devices, running
flash-base.sh
from the factory image will also update the bootloader and modem. -
Set up the custom AVB public key in the bootloader after rebooting from fastbootd to bootloader.
fastboot reboot-bootloader fastboot erase avb_custom_key fastboot flash avb_custom_key /path/to/avb_pkmd.bin
-
[Optional] Before locking the bootloader, reboot into Android to confirm proper signing.
Install the Magisk or KernelSU app and run:
adb shell su -c 'dmesg | grep libfs_avb'
If AVB is working, you should see:
init: [libfs_avb]Returning avb_handle with status: Success
-
Reboot into fastboot and lock the bootloader. This will trigger a data wipe.
fastboot flashing lock
Confirm by pressing volume down and then power. Then reboot.
Caution
Do not uncheck OEM unlocking
!
- For future updates, see the updates section.
Rooting, from security point of view is not recommended. But that should not stop a power user from using it.
The version of Magisk provided by Topjohnwu does not hold good with GrapheneOS as the developers of Magisk are hostile with GrapheneOS developers and its users. See 7606.
The fork of Magisk that is maintained by @pixincreate does overcome of the limitations by making root access work on GrapheneOS while allowing Zygisk to work. It of course with its own limitations set up by developers who develop root hiding solutions which prevents the fork from supporting modules like Shamiko.
In general, using Magisk and especially the features like Zygisk with Graphene are likely to have the risk of breaking things with every new release in future..
Using the fork of Magisk that supports Zygisk is recommended over official Magisk and KernelSU as the official Magisk is completely broken on GrapheneOS including Zygisk
while getting KernelSU working on GrapheneOS is itself a tedious task as GrapheneOS enforces signature verification on Kernel and hence, building GrapheneOS with KernelSU from scratch is the only option if root is need.
KernelSU does have some parts like ksud
's sources closed which makes it inappropriate for a tool that has so much influence on the device.
Note
For Magisk preinit, see Magisk preinit
Magisk versions 25211 and newer require a writable partition for storing custom SELinux rules that need to be accessed during early boot stages. This can only be determined on a real device, so avbroot requires the partition to be explicitly specified via --magisk-preinit-device <name>
. To find the partition name:
-
Extract the boot image from the original/unpatched OTA:
avbroot ota extract \ --input /path/to/ota.zip \ --directory . \ --boot-only
-
Patch the boot image via the Magisk app on the target device.
The Magisk app will print out a line like:
- Pre-init storage partition device ID: <name>
Alternatively, run:
avbroot boot magisk-info \ --image magisk_patched-*.img
The partition name will be shown as
PREINITDEVICE=<name>
.Now that the partition name is known, it can be passed to avbroot when patching via
--magisk-preinit-device <name>
. The partition name should be saved somewhere for future reference since it's unlikely to change across Magisk updates.If the device is unbootable, patch and flash the OTA once using
--ignore-magisk-warnings
, then repatch and reflash the OTA with--magisk-preinit-device <name>
.
Updates can be done by patching (or re-patching) the OTA using adb sideload
:
- Reboot to recovery mode. If stuck at
No command
, press Volume up while holding Power button. - Sideload the patched OTA with
adb sideload
by using volume buttons to toggle toApply update from ADB
which can be confirmed by pressing the power button
PixeneOS leverages Custota:
- Disable the system updater app.
- Open Custota and set the OTA server URL to:
https://pixincreate.github.io/PixeneOS/<rootless/magisk>
For more info, refer to the server branch.
PixeneOS can be run on your local machine. A Linux based machine is preferred.
-
Clone or fork the repository
-
Modify
env.toml
to set environment variables (your device model, AVBRoot architecture, GrapheneOS update channel and etc.,)
Important
Make sure that env.toml
file exist in root of the project.
-
Run the program end-to-end:
. src/main.sh
Note
Running the program end-to-end will only generate the patched OTA package locally and will not push it to the server (server branch that contains the json file which is read by the Custota).
INTERACTIVE_MODE
, by default is set to true
that calls check_toml_env
function to check the existence of env.toml
. If the file exist, it will read the env.toml
file and set the environment variables accordingly. If the env.toml
is non-existent, ignored. If it exist, and the format is wrong, the script exits with an error.
To make the patched OTA available to the device, it needs to be hosted on the server. PixeneOS uses GitHub for pushing updates, handled by release.yml.
To set up automated release, add the following variables in GitHub secrets:
EMAIL
: Email address associated with the GitHub account.- Base64 encoded keys:
AVB_KEY
CERT_OTA
OTA_KEY
- Passphrases used to generate the keys:
PASSPHRASE_AVB
PASSPHRASE_OTA
- To remove root, set the following URL in Custota: https://pixincreate.github.io/PixeneOS/rootless/
- To add root, set the following URL in Custota: https://pixincreate.github.io/PixeneOS/magisk/
-
To see the list of available commands:
. src/util_functions.sh && help
help
command will display the help message. -
To see the list of supported tools:
. src/util_functions.sh && supported_tools
supported_tools
command will display the list of tools that are supported. -
To generate AVB keys:
. src/util_functions.sh && generate_keys
This command will generate the AVB keys and store them in
.keys
directory.
Warning
For security reasons, .keys
directory will not be pushed to your GitHub repository.> Execute setup_hooks.sh
to install a pre-commit hook that will prevent .keys
directory from being pushed.
-
To create and make the release:
. src/util_functions.sh && create_and_make_release
-
To call individual functions/commands:
. src/<file>.sh && <function_name>
To revert to stock GrapheneOS or firmware:
-
Reboot into fastboot mode and unlock the bootloader. This will trigger a data wipe. Ensure data is backed up.
-
Erase the custom AVB public key:
fastboot erase avb_custom_key
-
Flash the stock firmware.
To know more about the projects used in this repository, refer to the following links:
This project is licensed under the MIT
. For more information, please refer to the LICENSE file.
Dependencies are downloaded from their respective repositories and are licensed under their respective licenses. Refer to the respective repositories for more information.
- GrapheneOS -- for the OS
- Chenxiaolong -- for additional features and tools
- Rooted-Graphene -- for motivation and inspiration
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.