Installation from recovery mode

Most Android devices have a "recovery" partition, on which a second kernel and initramfs can be installed. The recovery systems installed there allow overwriting the main OS with a special zip file, and it is possible to generate such a file for postmarketOS.
Preparation
- Install pmbootstrap
- Install TWRP (or another recovery system) on your phone
Create the recovery zip image
Follow the pmbootstrap article to build your own image, but add --android-recovery-zip to the install action.
If your device supports full disk encryption (see the FDE column in Devices), you can add the
--fde argument.
Currently the initramfs does not support FDE. (See here)
$ pmbootstrap init
$ pmbootstrap install --android-recovery-zip
By default, this will install to the system partition of your Android device. If you want to install to a different partition (e.g. because your system partition is too small), use the --recovery-install-partition parameter. For example, to install to the data partition:
$ pmbootstrap install --android-recovery-zip --recovery-install-partition=data
Modifying for A/B devices
As of 2026-02-21, this doesn't work correctly on devices using an A/B partitioning scheme. To check if you are on a A/B device:
- Boot to TWRP in recovery (
fastboot reboot recovery) -> tap on Reboot -> see if there is an option to select Slot A/B on the bottom - Try flashing it and get one of the two following errors during partition modification:
in /tmp/postmarketos/pmos.log: findfs: unable to resolve 'PARTLABEL=boot' findfs: unable to resolve 'PARTLABEL=system'
(TODO: Create or find an issue to fix this properly and link here.) In the meantime, you can manually edit the generated zip to work correctly.
First, go back to TWRP -> Reboot or the bootloader and find out if you're using slot A or B:
- TWRP shows it above the two options for Slot A/B
- Bootloader:
fastboot getvar current-slot
Next, run pmbootstrap export and
extract the created zip into the created directory:
mkdir extracted
unzip -d extracted /tmp/postmarketOS-export/pmos-*.zip
Now inside that, you need to edit 2 files, and change "boot" to "boot_a" or "boot_b" and "system" to "system_a" or "system_b" (whichever you got above).
In chroot/bin/pmos_install_functions
dev=$(findfs PARTLABEL="boot") || \
dev=$(readlink -fn "$(get_fstab_device "$fstab_recovery" boot)")And in chroot/install_options
KERNEL_PARTLABEL='boot'
INSTALL_PARTITION='system'Then rezip (run this inside the extracted directory to not create an extra directory inside the zip)
zip -r ../pmos-patched.zip ./
and proceed to adb sideload ../pmos-patched.zip (Advanced -> Sideload in TWRP) using this zip. If all went good you can boot into postmarketOS now and ignore #Sideload.
Sideload
This allows downloading the zip file on the fly directly from your computer. If you don't want to sideload, you can also copy the generated zip file to an SD card.
- Boot the recovery system
- Unmount the partitions (Click on "Mount", then deselect all checkboxes)
- Click on "Advanced / ADB Sideload", then "Swipe to start sideload"
- Connect your phone to your PC
- Start the sideloading process from your PC:
$ pmbootstrap flasher --method=adb sideload
Sideload without pmbootstrap
If sideloading with pmbootstrap fails (it was broken in #1638), you can do it without pmbootstrap as a workaround.
Install adb on your host Linux distribution (usually the android-tools package via apt install or similar), then run the following commands. (output should be similar)
$ pmbootstrap export
[19:57:59] Update package index for aarch64 (4 file(s))
[19:58:09] (rootfs_vendor-codename) install postmarketos-mkinitfs
[19:58:10] Register qemu binfmt (aarch64)
[19:58:13] (rootfs_vendor-codename) mkinitfs
[19:58:28] Export symlinks to: /tmp/postmarketOS-export
[19:58:28] * boot.img (Fastboot compatible boot.img file, contains initramfs with bootimg header <=2 and kernel)
[19:58:28] * vendor_boot.img (Fastboot compatible vendor_boot.img file, contains cmdline, initramfs and dtb. Only with bootimg header >= v3)
[19:58:28] * uInitrd (Initramfs, legacy u-boot image format)
[19:58:28] * uImage (Kernel, legacy u-boot image format)
[19:58:28] * dtbo.img (Fastboot compatible dtbo image)
[19:58:28] * vendor-codename.img (Rootfs with partitions for /boot and /)
[19:58:28] * vendor-codename-boot.img (Boot partition image)
[19:58:28] * vendor-codename-root.img (Root partition image)
[19:58:28] * pmos-vendor-codename.zip (Android recovery flashable zip)
[19:58:28] * lk2nd.img (Secondary Android bootloader)
[19:58:28] * initramfs (Initramfs)
[19:58:28] * vmlinuz (Linux kernel)
[19:58:28] * dtbs/ (Device tree blobs)
[19:58:28] DONE!
$ pmos_zip=$(find /tmp/postmarketOS-export/pmos-*.zip)
$ adb sideload $pmos_zip
loading: 'pmos-vendor-codename.zip'...
connecting...
Total xfer: 1.00x
You should now be able to boot into postmarketOS!
If you have run into any problems you can refer to the troubleshooting page or the community/contact page.
Photos
-
postmarketos-android-recovery-installer 1.0.1 running in TWRP on Google Nexus 4 (lg-mako)
See also
- 100 days of postmarketOS: Interoperability
- Source code for the recovery installer
- Android Recovery: general tips and tricks for postmarketOS and the recovery system