https://github.com/eth-p/openwrt-abpp
OpenWrt A/B Partition Project (for x86_64 Systems)
https://github.com/eth-p/openwrt-abpp
openwrt openwrt-configuration
Last synced: 8 months ago
JSON representation
OpenWrt A/B Partition Project (for x86_64 Systems)
- Host: GitHub
- URL: https://github.com/eth-p/openwrt-abpp
- Owner: eth-p
- License: mit
- Created: 2024-02-24T11:15:41.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2024-05-16T01:37:38.000Z (about 2 years ago)
- Last Synced: 2025-02-09T00:31:40.593Z (over 1 year ago)
- Topics: openwrt, openwrt-configuration
- Language: Shell
- Homepage:
- Size: 28.3 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# OpenWrt A/B Partition Project
This is a project that enables [OpenWrt](https://openwrt.org/) to be installed using an A/B partition scheme.
>[!caution]
> The OpenWrt A/B Partition Project is designed for x86_64 systems.
> It will *probably not work* for other architectures without modification.
## Requirements
* A Linux live USB stick with `wget`/`curl`, along with both `parted` and `fdisk`.
* A computer to install OpenWrt to, with at least 8 GiB of storage.
## Installation
The initial setup for OpenWrt A/B partitioning is entirely manual.
Please follow these instructions carefully.
### Base OpenWrt Installation
(Start by booting up your device with the Linux live USB stick.)
First, you will need to download (or copy) both the `generic-squashfs-combined-efi` and
`generic-squashfs-rootfs` images.
```bash
wget "https://archive.openwrt.org/releases/23.05.1/targets/x86/64/openwrt-23.05.1-x86-64-generic-squashfs-combined-efi.img.gz"
wget "https://archive.openwrt.org/releases/23.05.1/targets/x86/64/openwrt-23.05.1-x86-64-generic-squashfs-rootfs.img.gz"
```
The next step is to identify the internal storage device to install OpenWrt on:
```bash
lsblk
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
# loop0 7:0 0 766.5M 1 loop /run/archiso/airootfs
# sda 8:0 0 29.8G 0 disk
# ├─sda1 8:1 0 16M 0 part
# └─sda2 8:2 0 29.7G 0 part
# sdb 8:16 0 1.9G 0 disk
# ├─sdb1 8:17 0 917M 0 part
# └─sdb2 8:18 0 15G 0 part
```
If you are not sure which device is what, `ls -l /dev/disk/by-id` may help:
```bash
ls -l /dev/disk/by-id
# total 0
# lrwxrwxrwx 1 root root 9 Feb 27 13:00 ata-DEVICE_NAME_DEVICE_SERIAL -> ../../sda
# lrwxrwxrwx 1 root root 9 Feb 27 13:00 ata-DEVICE_NAME_DEVICE_SERIAL-part1 -> ../../sda1
# lrwxrwxrwx 1 root root 9 Feb 27 13:00 ata-DEVICE_NAME_DEVICE_SERIAL-part2 -> ../../sda2
# lrwxrwxrwx 1 root root 9 Feb 27 13:00 usb-USBSTICK_NAME_DEVICE_SERIAL -> ../../sdb
# lrwxrwxrwx 1 root root 9 Feb 27 13:00 usb-USBSTICK_NAME_DEVICE_SERIAL-part1 -> ../../sdb1
# lrwxrwxrwx 1 root root 9 Feb 27 13:00 usb-USBSTICK_NAME_DEVICE_SERIAL-part2 -> ../../sdb2
```
Once you determine which disk to install to, flash the uncompressed `-combined-efi` image to it:
```bash
gunzip -c *-combined-efi.img.gz | dd of=/dev/sda status=progress
```
### A/B OpenWrt Modification
With the base installation complete, you will need to modify it to support an A/B partition scheme.
First, you will need to update the partition table using `fdisk`.
Remove partition 2 and replace it with the following three partitions:
| Partition ID | Size | Filesystem Type |
|:--|:--|:--|
| 2 | 200+ MiB | Microsoft basic data (type 11) |
| 10 | 50% remaining space | Linux filesystem (type 20) |
| 11 | 50% remaining space | Linux filesystem (type 20) |
Next, use `parted` to rename each of the partitions:
| Partition ID | Name |
|:--|:--|
| 2 | Persistent |
| 10 | OpenWrt-A |
| 11 | OpenWrt-B |
>[!important]
> Partition `10` and `11` **must** be named `OpenWrt-A` and `OpenWrt-B` respectively.
> The partition name is used by `abupgrade` to detect which partition to flash.
You will need the partition UUIDs for `OpenWrt-A` later, so make sure to
find it using `blkid` and write it down:
```bash
blkid | grep 'OpenWrt-A'
# ...
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
# /dev/sda10: BLOCK_SIZE="262144" TYPE="squashfs" PARTLABEL="OpenWrt-A" PARTUUID="38fe120b-f6d5-4921-888d-1ffa0b1bc370"
```
Now you will need to re-flash the root filesystem to partition 10:
```bash
gunzip -c *-rootfs.img.gz | dd of=/dev/sda10 status=progress
```
After this, you will want to create a filesystem on partition 2 using `mkfs.vfat`.
This will be where you store `openwrt-abpp`.
#### GRUB Changes
Finally, you will need to rename the kernel image and update the GRUB configuration.
The `grub.cfg` file is located on partition 1.
```bash
mkdir -p /mnt/efi
mount -t vfat /dev/sda1 /mnt/efi
mv /mnt/efi/boot/vmlinuz /mnt/efi/boot/vmlinuz-a
nano /mnt/efi/boot/grub/grub.cfg
```
The original GRUB config will like something like this:
```perl
serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 --rtscts=off
terminal_input console serial; terminal_output console serial
set default="0"
set timeout="5"
search -l kernel -s root
menuentry "OpenWrt" {
linux /boot/vmlinuz root=PARTUUID=abcdef01-2345-6789-abcd-ef0123456789 rootwait console=ttyS0,115200n8 noinitrd
}
menuentry "OpenWrt (failsafe)" {
linux /boot/vmlinuz failsafe=true root=PARTUUID=abcdef01-2345-6789-abcd-ef0123456789 rootwait console=ttyS0,115200n8 noinitrd
}
```
>[!tip]
> If your device does not have a serial interface, [you will want to comment out the `serial` and `terminal_input`lines](https://forum.openwrt.org/t/solved-boot-hangs-on-lede-item-in-grub-menu-on-x86-no-grub-timeout/24741/10).
You will need to convert this into a template.
1. Copy the first non-failsafe `menuentry` to the end of the file.
2. Prepend a `#` to the beginning of each line of the original `menuentry` blocks.
3. Surround the original menuentry blocks with:
```
###----- BEGIN ABPP TEMPLATE -----###
###----- END ABPP TEMPLATE -----###
```
This will now be the template section.
4. In the template section:
* Append `-${LETTER}` after `/boot/vmlinuz`.
* Append ` ${VERSION}` after `"OpenWrt"`.
* Replace `root=PARTUUID=...` with `root=${PARTITION}`
5. Surround the copied menuentry with:
```
###----- BEGIN ABPP GENERATED -----###
###----- END ABPP GENERATED -----###
```
This will be the generated section.
6. In the generated section:
* Update the `PARTUUID` to the UUID recorded earlier.
* Append `-a` after `/boot/vmlinuz`.
>[!caution]
> It is **critical** that the section markers have the exact spacing and number of `#` and `-` characters.
>
> The section markers are used to update the GRUB configuration after upgrades, and it will not be possible to do
> automatically unless those exact strings are found in the file.
After you are finished, it should look similar to this:
```perl
# serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 --rtscts=off
# terminal_input console serial; terminal_output console serial
set default="0"
set timeout="5"
search -l kernel -s root
###----- BEGIN ABPP TEMPLATE -----###
# menuentry "OpenWrt ${VERSION}" {
# linux /boot/vmlinuz-${LETTER} root=${PARTITION} rootwait console=ttyS0,115200n8 noinitrd
# }
#
# menuentry "OpenWrt ${VERSION} (failsafe)" {
# linux /boot/vmlinuz failsafe=true root=${PARTITION} rootwait console=ttyS0,115200n8 noinitrd
# }
###----- END ABPP TEMPLATE -----###
###----- BEGIN ABPP GENERATED -----###
menuentry "OpenWrt" {
linux /boot/vmlinuz-a root=PARTUUID=38fe120b-f6d5-4921-888d-1ffa0b1bc370 rootwait console=ttyS0,115200n8 noinitrd
}
###----- END ABPP GENERATED -----###
```
You may now reboot into OpenWrt.
### Changes within OpenWrt
Once you have booted into OpenWrt and have internet connectivity, you will need to
install the following packages using `opkg`:
* `blkid`
* `block-mount`
* `dumb-init`
* `kmod-fs-squashfs`
* `kmod-fs-vfat`
* `losetup`
* `nsenter`
* `parted`
* `squashfs-tools-unsquashfs`
* `unshare`
After installing the packages, configure partition 2
[to be mounted on startup](https://openwrt.org/docs/guide-user/storage/fstab).
Finally, download [a tarball of this repo](https://github.com/eth-p/openwrt-abpp/archive/refs/heads/master.tar.gz) and
extract somewhere within partition 2.
You are now done! 🚀
## Usage
To flash a version of OpenWrt to the inactive partition, run the downloaded `/path/to/openwrt-abpp/bin/abupgrade`
script. It will:
* Let you select a version to flash.
* Download the rootfs.
* Flash the rootfs to the alternate partition.
* Copy your configuration (using `sysupgrade -b`) to the alternate partition.
* Download your currently-installed packages to the alternate partition.
* Update GRUB to automatically select the newly-flashed partition.
Once you reboot into the newly-flashed partition, openwrt-abpp will restore your configuration, install your packages,
and trigger a reboot to finalize everything.
## How it Works
Essentially, it flashes a new OpenWrt installation and copies/downloads your changes to it.
Behind the scenes, it involves:
* Re-implementing OpenWrt's overlay filesystem initialization code using shell scripts.
* Creating an extremely lightweight Linux container using `unshare`, `nsenter`, and `dumb-init`.
* Using the container to run `opkg` within the newly-flashed installation.