The mobynit utility mounts a container union filesystem and pivot roots a running system into it. It is used as an init replacement in the initramfs to boot into a hostapp container.
Mobynit uses the hostapp package, a module that discovers container overlay filesystems by reading overlay2 metadata directly.
# Build the mobynit binary (statically linked)
make mobynit
# Build with Docker (includes tests)
./build-docker.shMobynit is designed to run as PID 1 in an initramfs. It:
- Mounts the hostapp container (identified by a
currentsymlink) - Optionally overlays OS block containers (label:
io.balena.image.class=overlay) - Moves existing mounts into the new root
- Calls
pivot_rootto switch the system root - Execs
/sbin/init
mobynit -sysroot=/path # Mount sysroot and print path (for updates)
mobynit -dataFstype=ext4 # Data partition filesystem type (default: ext4)
OS block containers (labelled io.balena.image.class=overlay) are layered as
overlayfs lowerdirs alongside the hostapp. Their position relative to the
hostapp determines whether they can replace hostapp files or only add new ones.
In overlayfs, lowerdir=A:B:C means A has highest lookup priority: a file
in A shadows the same path in B and C.
There are two types of OS blocks:
Normal extensions (no io.balena.image.override label) mount to the
right of the hostapp. They can add new files but cannot replace files that
already exist in the hostapp.
Override extensions (io.balena.image.override=N) mount to the left of
the hostapp. They can replace hostapp files. N is the priority — lower
values get higher overlayfs precedence. Equal priorities are ordered by
container name for deterministic boot behaviour.
Given a hostapp and three OS blocks:
| Container | Label | Type |
|---|---|---|
| hostapp | — | base |
| networking | io.balena.image.override=10 |
override |
| security | io.balena.image.override=20 |
override |
| extras | (none) | normal |
The resulting overlayfs mount is:
lowerdir=networking:security:hostapp:extras
^^^^^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^
overrides (sorted) base normals
higher priority ──────────────────> lower priority
networkingcan replace files in all other layerssecuritycan replace hostapp and extras files, but not networkinghostappcan shadow extras filesextrascan only contribute files not present in any layer above it
The kernel limits mount options to PAGE_SIZE - 1 bytes. If extensions would
exceed this limit, they are dropped (with a log warning) in reverse order of
importance: normal paths first, then lowest-priority overrides. The hostapp is
never dropped.
emergency- Skip OS blocks overlay mountingmobynit.no_overlays- Skip OS blocks overlay mounting
- overlay2 storage driver (aufs not supported)
- Go 1.22+