Pmbootstrap

pmbootstrap (git) is the central command-line application for postmarketOS development. Among other things, it allows building packages, creating installation images and flashing them to your phone. If you only want to install postmarketOS, make sure to read the installation article first since you might not need to install pmbootstrap depending on the method.
== Installation ==
pmbootstrap runs on pretty much any Linux distribution with python3, openssl and git installed. It uses Alpine Linux chroots internally to avoid installing software on the host machine. If you don't run Linux on your PC, see #Other operating systems.
=== On Linux ===
==== From git ====
Follow this section if your Linux distribution doesn't have pmbootstrap packaged, or its version of pmbootstrap is too old, or you would like to change the code. Run the following to clone and install pmbootstrap from git.
$ git clone https://gitlab.postmarketos.org/postmarketOS/pmbootstrap.git
$ cd pmbootstrap
$ mkdir -p ~/.local/bin
$ ln -s "$PWD/pmbootstrap.py" ~/.local/bin/pmbootstrap
$ pmbootstrap --version
2.2.1
If you get ModuleNotFoundError: No module named 'tomllib', then you are running python 3 <= 3.10 and need to install the python3 library tomli with your linux distribution's package manager. The package is probably called python3-tomli.
If this returns something like pmbootstrap: command not found instead of a version number, ensure that ~/.local/bin is in your PATH. For example by adding the following to your ~/.profile (zsh: ~/.zprofile) followed by source ~/.profile to update your environment 
PATH="$HOME/.local/bin:$PATH"
If you ran the source command with the file you modified it should work. Otherwise, try a new terminal window.
Continue reading at #Using pmbootstrap.
==== From package manager ====
Use the package manager of your distribution to install pmbootstrap:
Alpine Linux, postmarketOS:
# apk add pmbootstrap
Arch Linux:
# pacman -S pmbootstrap
Debian:
# apt install pmbootstrap
Fedora:
# dnf install pmbootstrap
Void Linux:
# xbps-install -S pmbootstrap
Gentoo:
# emerge -va app-eselect/eselect-repository
# eselect repository enable guru
# emaint -r guru sync
# emerge -va dev-util/pmbootstrap
Nix/NixOS
# nix run nixpkgs#pmbootstrap
Continue reading at #Using pmbootstrap.
=== Other operating systems ===
Running pmbootstrap on other operating systems than Linux is not supported. If you run another OS, consider setting up a virtual machine with Linux. Some people also made it work with WSL, see the Windows FAQ. But again, it's not officially supported - we recommend getting some sort of Linux install instead and running it there.
== Using pmbootstrap ==
Frequent users may want to set up tab completion at this point, to be able to automatically complete your pmbootstrap commands and arguments with the tab key while writing them.
=== Initialization ===
Before pmbootstrap can be used, a number of configuration questions need to be answered. The sections below go into detail for the various questions.
$ pmbootstrap init
If you already ran this before, run the following to update your local clone of pmaports.git instead, before moving straight onto the installation step:
$ pmbootstrap pull
==== Work path ====
Make sure that the location has a few GB of space available, and that it is a relatively standard Linux filesystem (one that supports device nodes and symbolic links). Notably unsupported are: eCryptFS, encfs, fat, ntfs, nfs shares, tmpfs, and VirtualBox shared folders. pmbootstrap will automatically clone pmaports.git into a subdirectory of the work path.
Location of the 'work' path. Multiple chroots (native, device arch, device rootfs) will be created in there.
Work path [/home/user/.local/var/pmbootstrap]: 
Setting up the native chroot and cloning the package build recipes (pmaports)...
Clone git repository: https://gitlab.postmarketos.org/postmarketOS/pmaports.git
Cloning into '/home/user/.local/var/pmbootstrap/cache_git/pmaports'...
NOTE: pmaports path: /home/user/.local/var/pmbootstrap/cache_git/pmaports
==== Channel ====
Unless your device is in the community or main category of devices, you need to choose edge here. Otherwise you can consider using the latest release. See the releases article for more information about the difference between the release channels.
Choose the postmarketOS release channel.
Available (10):
* edge: Rolling release / Most devices / Occasional breakage: https://postmarketos.org/edge
* v24.06: Latest release / Recommended for best stability
* v23.12: Old release (supported until 2024-07-16)
Channel [edge]: 
==== Device ====
Type in the vendor and code-name of your device at the prompt. If you're unsure, find your device in the list of devices.
In case you do not wish to install to a real device, you can create a VM image for a QEMU device such as qemu-amd64. Run it afterwards with pmbootstrap qemu, as described in the related wiki pages.
==== User interface ====
Choose the user interface you would like to install. Check your device's wiki page, it may have more information on which interfaces are known to be working with your device. Weston and XFCE4 are usable on devices which do not have hardware 3D acceleration, the others are notably slowed down. If you are unsure, read :Category:Interface for information.
Available user interfaces (20): 
* none: Bare minimum OS image for testing and manual customization. The "console" UI should be selected if a graphical UI is not desired.
* asteroid: (Wayland) Smartwatch UI from AsteroidOS
* console: Console environment, with no graphical/touch UI
* fbkeyboard: Plain framebuffer console with touchscreen keyboard support
* framebufferphone: Minimalist framebuffer menu/keyboard UI accessible via touch/volume keys & compatible scripts
* gnome: (Wayland) Gnome Shell
* gnome-mobile: (Wayland) Gnome Shell patched to adapt better to phones (Experimental)
* i3wm: (X11) Tiling WM (keyboard required)
* kodi: (GBM) 10-foot UI useful on TV's
* lxqt: (X11) Lightweight Qt Desktop Environment (stylus recommended)
* mate: (X11) MATE Desktop Environment, fork of GNOME2 (stylus recommended)
* phosh: (Wayland) Mobile UI developed for the Librem 5
* plasma-bigscreen: (Wayland) 10-feet variant of Plasma, made for big screen TVs
* plasma-desktop: (X11/Wayland) KDE Desktop Environment (works well with tablets)
* plasma-mobile: (Wayland) Mobile variant of KDE Plasma (does not run without hardware acceleration)
* shelli: Plain console with touchscreen gesture support
* sway: (Wayland) Tiling WM, drop-in replacement for i3wm (DOES NOT RUN WITHOUT HW ACCELERATION!)
* sxmo-de-dwm: Simple Mobile: Mobile environment based on SXMO and running on dwm
* sxmo-de-sway: Simple Mobile: Mobile environment based on SXMO and running on sway
* weston: (Wayland) Reference compositor (demo, not a phone interface)
* xfce4: (X11) Lightweight desktop (stylus recommended)
User interface [phosh]:
==== More questions ====
Unless you know that you want to change something, it's fine to answer with the defaults here by just pressing the return key.
Additional options: extra free space: 0 MB, boot partition size: 256 MB, parallel jobs: 3, ccache per arch: 5G, sudo timer: False, mirror: http://mirror.postmarketos.org/postmarketos/
Change them? (y/n) [n]: 
Additional packages that will be installed to rootfs. Specify them in a comma separated list (e.g.: vim,file) or "none"
Extra packages [none]: 
Your host timezone: Europe/Berlin
Use this timezone instead of GMT? (y/n) [y]: 
Available locales (14): C.UTF-8, ch_DE.UTF-8, de_CH.UTF-8, de_DE.UTF-8, en_GB.UTF-8, en_US.UTF-8, es_ES.UTF-8, fr_FR.UTF-8, it_IT.UTF-8, nb_NO.UTF-8, nl_NL.UTF-8, pt_BR.UTF-8, ru_RU.UTF-8, sv_SE.UTF-8
Choose default locale for installation [C.UTF-8]: 
Device hostname (short form, e.g. 'foo') [pine64-pinephone]: 
After pmaports are changed, the binary packages may be outdated. If you want to install postmarketOS without changes, reply 'n' for a faster installation.
Build outdated packages during 'pmbootstrap install'? (y/n) [y]: 
WARNING: The chroots and git repositories in the work dir do not get updated automatically.
Run 'pmbootstrap status' once a day before working with pmbootstrap to make sure that everything is up-to-date.
DONE!
=== Installing postmarketOS ===
Depending on the device, the installation instructions may be quite different. You might need to unlock or flash a bootloader before continuing here, or you may need to use a specific install command. Make sure you read the installation section of your device's wiki page first.
All device ports have in common that they run some form of the pmbootstrap install command at one point. It will build a chroot with the full installation as it will be placed on the device, copy it to an image file or write it directly to an SD card and ask you for the user and encryption password. Below are the most commonly used pmbootstrap install commands.
All examples have --fde added to enable Full Disk Encryption. Omit it if you don't want to encrypt your device or if your device port isn't able to show the FDE prompt yet (see FDE column of the all devices table).
Find all available arguments (such as ones for choosing different filesystems etc.) with pmbootstrap install --help.
==== pmbootstrap install ====
===== SD card =====
Devices like the PinePhone, Samsung Galaxy S II, Nokia N900, various laptops etc. boot from an SD card, USB stick or other external storage. Find the name with lsblk first and make sure it is the right one as you will overwrite everything on it. Use a path without partition number at the end, such as /dev/mmcblk0.
$ pmbootstrap install --sdcard=/dev/mmcblk... --fde
If your device is able to boot from SD card without flashing anything (such as the PinePhone), you should now be able to insert it into your device and boot it up. You are done with installing postmarketOS, congratulations!
To make Androids like the Samsung Galaxy S II boot from SD card, you will need to flash a boot.img file to the internal storage. Read on at #flash_kernel.
===== Encrypted Image file =====
Most Androids, the Librem 5 and other devices need to have an image file generated, that will then be flashed to the device while it is in a special flashing mode. To generate such an image, run:
$ pmbootstrap install --fde
Then read on at #pmbootstrap flasher.
===== Android recovery zip =====
A less reliable, but for some devices required method is using the Android recovery zip. The Installation from recovery mode article explains how to generate the zip file and how to flash it.
==== pmbootstrap flasher ====
This action wraps various flash programs (e.g. fastboot and heimdall) with a common syntax, and automatically fills out the paths to the files generated earlier during pmbootstrap install. Bring your phone into the flashing mode, typically by holding a special button combination such as + while booting up. This should be described in your device's wiki page.
If you specify partition names below, note that they are case sensitive. If flashing onto a Samsung device, you can use heimdall print-pit to verify the names.
===== flash_rootfs =====
Flash the rootfs to internal storage. You will need to do this, unless you plan to boot the rootfs from elsewhere, such as from SD card. Beware that this will overwrite the existing installation/data on your phone!
$ pmbootstrap flasher flash_rootfs
For Androids, we don't change the partition layout. If the default partition (typically "system") is too small for the generated image, it is possible to flash to another partition. Just be sure to erase any previous installations of postmarketOS in other partitions, because the init script will start with the first one that it encounters. (To delete a previous version either use fastboot format system for fastboot compatible devices, or simply install the known working OS, e.g. Android, on it. And if you really know what you are doing, you might consider using dd). Using multiple partitions with LVM is planned ().
$ pmbootstrap flasher flash_rootfs --partition userdata
===== flash_kernel =====
For Androids, you will also need to flash a boot.img (kernel + initramfs). Instruct pmbootstrap to do so with:
$ pmbootstrap flasher flash_kernel
Afterwards you should be able to restart your phone and postmarketOS should boot up. You are done with installing postmarketOS, congratulations!
==== Inspecting generated files ====
If you want to conveniently access the files generated by pmbootstrap install, let pmbootstrap create a bunch of symlinks with export.
$ pmbootstrap export
(rootfs_lg-mako) install device-lg-mako
(rootfs_lg-mako) install postmarketos-mkinitfs
(rootfs_lg-mako) mkinitfs lg-mako
Export symlinks to: /tmp/postmarketOS-export
 * boot.img (Fastboot compatible boot.img file, contains initramfs and kernel)
 * initramfs (Initramfs)
 * initramfs-extra (Extra initramfs files in /boot)
 * vmlinuz (Linux kernel)
 * lg-mako.img (Rootfs with partitions for /boot and /)
Run the following to extract the generated initramfs:
$ pmbootstrap initfs extract
=== Development actions ===
==== Building packages ====
Build any package from pmaports.git, for example main/hello-world. pmbootstrap will automatically pick one of the architectures that the APKBUILD can be built for, preferably the native architecture of the PC running pmbootstrap, or if that's not possible, the device's architecture. You can explicitly specify an architecture with --arch.
pmbootstrap uses cross compilers as described in detail in the cross compiling article.
$ pmbootstrap build hello-world
$ pmbootstrap build --arch=armv7 hello-world
If you edited the sources of an APKBUILD, update its checksums:
$ pmbootstrap checksum hello-world
To find out where your local APKBUILD copies are saved (for instance, in order to modify them), run:
$ pmbootstrap config aports
If you modify anything in there, you will need to update its checksums and then re-build as above.
To build a package from Alpine, it needs to be forked from Alpine's aports.git first:
$ pmbootstrap aportgen --fork-alpine megapixels
Generate aport: megapixels
Checkout aports.git branch: master
*** pmaport generated: /home/user/.local/var/pmbootstrap/cache_git/pmaports/temp/megapixels
NOTE: chroot is still active (use 'pmbootstrap shutdown' as necessary)
DONE!
$ pmbootstrap build megapixels
It is also possible to specify a local source tree for building a package.
$ git clone https://gitlab.postmarketos.org/postmarketOS/megapixels/
$ pmbootstrap build megapixels --src=megapixels
Generate a template for a new package:
$ pmbootstrap newapkbuild "https://gitlab.postmarketos.org/postmarketOS/osk-sdl/-/archive/0.52/osk-sdl-0.52.tar.bz2"
==== Entering chroots ====
Enter the armv7 building chroot:
$ pmbootstrap chroot -b armv7
Run a command inside a chroot:
$ pmbootstrap chroot -- echo test
Safely delete all chroots:
$ pmbootstrap zap
==== Running CI scripts locally ====
Before a patch with modifications to pmaports (or other postmarketOS projects, such as pmbootstrap itself) gets accepted, it needs to pass the CI scripts. These run automatically when you submit the patch, but of course it makes sense to run it beforehand on your machine locally. That way you can fix up your patches until it passes and you have a shorter test iteration time than you would have with pushing it to the server every time.
Navigate to the git repository that you have modified and run the ci action.
$ pmbootstrap ci
Available CI scripts (15):
* flake8: lint CI related python scripts/tests
* apkbuild-lint: run apkbuild-lint on modified APKBUILDs
* wiki: verify devices are documented in the wiki
* ec: editorconfig-checker: lint for trailing whitespaces etc.
* pytest: lint with various python tests
* commits: check pkgver/pkgrel bumps, amount of changed pkgs etc
* kconfig: check all kernel configs with 'pmbootstrap kconfig check'
* grep: check various bad patterns with grep
* shellcheck: lint all shell scripts
* build-riscv64: build modified packages for this architecture (slow)
* build-x86: build modified packages for this architecture (slow)
* build-armhf: build modified packages for this architecture (slow)
* build-aarch64: build modified packages for this architecture (slow)
* build-x86_64: build modified packages for this architecture (slow)
* build-armv7: build modified packages for this architecture (slow)
Which script? [all]: 
*** (1/15) RUNNING CI SCRIPT: .ci/flake8.sh [pmbootstrap chroot] ***
...
See the pmbootstrap CI article for more information on this feature.
==== Device porting assistance ====
Analyze Android boot.img files (also works with recovery OS images like TWRP):
$ pmbootstrap bootimg_analyze ~/Downloads/twrp-3.7.0_9-0-FP2.img 
NOTE: You will be prompted for your sudo/doas password, so we can set up a chroot to extract and analyze your boot.img file
(native) install file unpackbootimg
Put these variables in the deviceinfo file of your device:
deviceinfo_kernel_cmdline="console=ttyHSL0,115200,n8 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x3b7 ehci-hcd.park=3 androidboot.bootdevice=msm_sdcc.1"
deviceinfo_generate_bootimg="true"
deviceinfo_bootimg_qcdt="true"
deviceinfo_bootimg_mtk_mkimage="false"
deviceinfo_bootimg_dtb_second="false"
deviceinfo_flash_pagesize="2048"
deviceinfo_flash_offset_base="0x00000000"
deviceinfo_flash_offset_kernel="0x00008000"
deviceinfo_flash_offset_ramdisk="0x02000000"
deviceinfo_flash_offset_second="0x00f00000"
deviceinfo_flash_offset_tags="0x01e00000"
NOTE: chroot is still active (use 'pmbootstrap shutdown' as necessary)
DONE!
Check kernel configs:
$ pmbootstrap kconfig check
Edit a kernel config:
$ pmbootstrap kconfig edit --arch=aarch64 linux-postmarketos-allwinner
==== Repository maintenance ====
Generate cross-compiler aports based on the latest version from Alpine's aports:
$ cd "$(pmbootstrap config work)"/cache_git/pmaports/cross
$ pmbootstrap aportgen binutils-* gcc-*
Manually rebuild package index:
$ pmbootstrap index
List pmaports that don't have a binary package:
$ pmbootstrap repo_missing --arch=armhf --overview
Increase the pkgrel for each aport where the binary package has outdated dependencies (e.g. after soname bumps):
$ pmbootstrap pkgrel_bump --auto
==== Logging ====
pmbootstrap writes all log output, and each shell command it runs to log.txt inside the work dir. Use the following command to follow the log in a second terminal:
$ pmbootstrap log
Use -v on any action to get verbose logging:
$ pmbootstrap -v build hello-world
Parse a single deviceinfo and return it as JSON:
$ pmbootstrap deviceinfo_parse pine64-pinephone
Parse a single APKBUILD and return it as JSON:
$ pmbootstrap apkbuild_parse hello-world
Parse a package from an APKINDEX and return it as JSON:
$ pmbootstrap apkindex_parse $WORK/cache_apk_x86_64/APKINDEX.8b865e19.tar.gz hello-world
== Clean up ==
The zap action is used to clean up files generated while using pmbootstrap:
Remove all chroots:
$ pmbootstrap zap
Remove all chroots and built packages:
$ pmbootstrap zap -p
See all options:
$ pmbootstrap zap --help
Removing and recreating chroots is relatively fast, as the Alpine packages that get installed into the chroots are still cached. Sometimes users ask how to completely remove everything related to pmbootstrap (all caches and the config file), this would be done as follows. You can do this if your pmbootstrap install is completely broken for some reason, and then cleanly re-install it as described in this article.
$ pmbootstrap shutdown
$ export WORK=$(pmbootstrap config work)
# rm -rf "$WORK"
$ rm -f ~/.config/pmbootstrap_v3.cfg
$ rm -f ~/.local/bin/pmbootstrap
== See also ==
=== Internal pages ===
=== External Links ===
* Pmbootstrap Doc
* git repository
* issue tracker
* pmbootstrap: the Swiss Army knife of postmarketOS development — Video Presentation at AlpineConf 2021
* Installation
* Alternatives to regular flashing
* Porting to a new device
* On-device installer
* Troubleshooting
Category:Guide