awesome-o-image is the command-line equivalent of the Cockpit Firmware Image page. Everything the GUI does — check for new firmware, download and stage, apply on next boot, roll back to a previous image or to factory, list what's installed, remove an old version — has a CLI subcommand here. The Cockpit module under the hood drives this binary; you can drive it yourself for scripted/headless deployments or when working at a console without a browser.
Where to run it: Open the Cockpit admin interface and click Tools → Terminal.
awesome-o-imageis on the$PATH. SSH and the HDMI console work too.
awesome-o-image <subcommand> [flags]
awesome-o-image needs root for any subcommand that touches firmware state on /boot. The metadata-only check, status, list, and versions subcommands work as a regular user.
For the GUI workflow this powers, see Firmware Update.
Metadata-only poll. Fetches latest.txt and the small companion files (version.txt, bootsystem-current.sha256, filesystem-current.sha256) from the firmware server, decides whether an update is available, and updates the device's state.json. Nothing on /boot is touched.
check is the same code path the device's weekly systemd timer runs on its own. You can run it manually if you want to know right now whether an update is available.
Usage:
awesome-o-image check
Example:
$ sudo awesome-o-image check
[check] fetching latest.txt … ok
[check] running: trixie-current-6.18.18-2026.04.10
[check] server: trixie-current-6.18.20-2026.06.01
[check] result: kernel-update-available
Result values you'll see:
| Value | Meaning |
|---|---|
up-to-date |
Running version matches server. Nothing to do. |
kernel-update-available |
New kernel version on server. |
rootfs-only-update-available |
Same kernel, different rootfs sha256. |
codename-mismatch |
Server image is for a different Debian codename — refused. |
error |
Network or parse failure. See journal. |
Print the device's current firmware state — what's running, what's the default boot label, what (if anything) is staged, and the latest check result.
Usage:
awesome-o-image status [--json]
Example:
$ awesome-o-image status
Running: trixie-current-6.18.18-2026.04.10
Default: trixie-current-6.18.18-2026.04.10
Staged: trixie-current-6.18.20-2026.06.01
Last check: 2026-05-16T03:00:14Z
Last result: kernel-update-available
Available: trixie-current-6.18.20-2026.06.01
Factory: Defend-O-Tron Factory (always available as rollback)
With --json, the same information is returned as a structured object — used by the Cockpit page and convenient for scripts.
Download a new firmware image, verify its SHA-256 against the server's sidecar, and lay it out under /boot/images/<id>/. Updates state.json and adds the new image as a boot option in extlinux.conf. Does not flip the default boot label — the device still boots the current image on reboot.
By default, stage downloads the image identified by the most recent check (whatever's in state.available). Pass --version to stage a specific image instead.
Usage:
awesome-o-image stage [--version ID] [--quiet]
| Flag | Effect |
|---|---|
--version <id> |
Stage a specific version-id from the server instead of the one check flagged. |
--quiet |
Suppress the progress bar. Useful when output is being captured. |
Example:
$ sudo awesome-o-image stage
[stage] acquiring update lock … ok
[stage] codename gate: trixie == trixie … ok
[stage] disk space: /boot has 5.4 GB free (need ≥ 1.65 GB) … ok
[stage] /boot remount rw … ok
[stage] downloading bootsystem-current.squashfs
████████████████████████████████████████ 742 MB / 742 MB 18.2 MB/s
[stage] sha256 verify … ok (a3f2…b7e1)
[stage] unsquashfs → /boot/images/trixie-current-6.18.20-2026.06.01/ … ok
[stage] extlinux.conf: appending LABEL pair … ok
[stage] state.json: staged set, image registered … ok
OK Success: image staged
next: 'awesome-o-image apply' to switch the default boot label
Flip the default boot label in extlinux.conf so the device boots the staged image on next reboot. Does not download anything (so it's fast) and does not reboot the device unless you ask it to with --reboot.
The previous default label is kept in extlinux.conf as a rollback option — you can switch back to it with awesome-o-image rollback if anything goes wrong.
Usage:
awesome-o-image apply [--reboot]
| Flag | Effect |
|---|---|
--reboot |
After flipping the default label, immediately systemctl reboot. |
Example:
$ sudo awesome-o-image apply
[apply] previous default: trixie-current-6.18.18-2026.04.10
[apply] new default: trixie-current-6.18.20-2026.06.01
[apply] extlinux.conf written atomically … ok
[apply] state.json updated … ok
OK Success: default boot label switched
reboot to activate, or run with '--reboot' next time
Switch the default boot label back to a previous, specified, or factory image. Pure label flip — no downloads, no file deletion.
rollback picks its target in this order:
--factory flag → the always-available Defend-O-Tron Factory label.--version <id> → the named image, if installed.state.images.state.images is empty or doesn't include the current default).Usage:
awesome-o-image rollback [--version ID] [--factory] [--reboot]
| Flag | Effect |
|---|---|
--factory |
Roll back to the original factory image. Always available, even if every other image has been removed. |
--version <id> |
Roll back to a specific image. |
--reboot |
Reboot after rolling back. |
Example — roll back to factory:
$ sudo awesome-o-image rollback --factory
[rollback] target: Defend-O-Tron Factory
[rollback] extlinux.conf default flipped … ok
[rollback] state.json updated … ok
OK Success: rolled back to factory image
reboot to activate
Print a table of installed (non-factory) images. The factory image is always available regardless and isn't listed here.
Usage:
awesome-o-image list [--json]
Example:
$ awesome-o-image list
ID Kernel Installed Flags
trixie-current-6.18.18-2026.04.10 6.18.18 2026-04-12T11:02:08Z (default, running)
trixie-current-6.18.16-2026.03.07 6.18.16 2026-03-10T08:42:15Z
trixie-current-6.18.20-2026.06.01 6.18.20 2026-05-16T11:03:47Z (staged)
With --json, the same data is returned as an array of objects.
Delete a non-default, non-running image — its files under /boot/images/<id>/ and its boot-label entries in extlinux.conf.
remove refuses to delete:
state.images (it's already not installed).The factory image cannot be removed.
Usage:
awesome-o-image remove <ID>
Example:
$ sudo awesome-o-image remove trixie-current-6.18.16-2026.03.07
[remove] verifying target is safe to delete … ok
[remove] /boot/images/trixie-current-6.18.16-2026.03.07/ → unlinked
[remove] extlinux.conf: LABEL pair removed … ok
[remove] state.json: image entry dropped … ok
OK Success: image removed
List the version-ids the firmware server currently has on offer. Useful for picking a specific version for stage --version.
Usage:
awesome-o-image versions
Example:
$ awesome-o-image versions
trixie-current-6.18.20-2026.06.01 (latest)
trixie-current-6.18.18-2026.04.10
trixie-current-6.18.16-2026.03.07
trixie-current-6.18.14-2026.02.04
Print the awesome-o-image binary version.
Usage:
awesome-o-image version
awesome-o-image --version
awesome-o-image -v
Example:
$ awesome-o-image version
1.0.25
Print the usage summary (the same content shown at the top of this page).
Usage:
awesome-o-image help
awesome-o-image --help
awesome-o-image -h
Routine update from the CLI:
sudo awesome-o-image check
sudo awesome-o-image stage
sudo awesome-o-image apply --reboot
Stage a specific older version:
sudo awesome-o-image versions
sudo awesome-o-image stage --version trixie-current-6.18.16-2026.03.07
Quick rollback if a fresh apply went wrong:
sudo awesome-o-image rollback --reboot
Wipe non-essential history to free space:
awesome-o-image list
sudo awesome-o-image remove <old-version-id>
awesome-o-image uses a layered configuration model — one shipped defaults file plus an operator drop-in directory:
| Path | Edited by | Purpose |
|---|---|---|
/etc/awesome-o/image-updater.conf |
Package only — do not edit | Canonical defaults shipped with the deb. This is a dpkg conffile; when the package ships revised defaults, dpkg silently replaces this file (because you haven't touched it), so new defaults flow through with no merge prompt. |
/etc/awesome-o/image-updater.conf.d/*.conf |
You | Overrides. Files in this directory are layered on top of the main conf in lexicographic order. Only set the keys you actually want to change; everything else falls through. |
/etc/awesome-o/image-updater-credentials |
You (only when the firmware server requires HTTP Basic Auth) | Username + password for the firmware server. Not a dpkg conffile. Mode must be 0600 owned by root:root. |
To override a setting, copy the sample and edit the copy:
sudo cp /usr/share/doc/awesome-o-image-updater/examples/local.conf.sample \
/etc/awesome-o/image-updater.conf.d/local.conf
sudo $EDITOR /etc/awesome-o/image-updater.conf.d/local.conf
The sample is heavily commented and lists every overridable key. You can also split overrides across multiple *.conf files for tidier ops (e.g. one file for the firmware server URL, another for retention).
| Section | What it controls |
|---|---|
[server] |
Firmware server endpoint — base_url (root of the image tree), latest_pointer (filename listing the current latest), available_pointer (optional full list), per-version-id filenames (version_file, bootsystem_artifact, the two *_sha256_file companions), trusted_ca_path (extra CA bundle if your server uses a private PKI), auth_file (path to the optional credentials file below). |
[boot] |
Local boot-disk layout — mount_point (/boot), extlinux_conf, images_dir (/boot/images), staging_dir, run_dir, state_path. Matches the Armbian + live-boot layout the device ships with. Rarely needs changing. |
[network] |
HTTP client — timeout_seconds, user_agent. |
[retention] |
Image retention — keep_installed (how many per-image directories to keep under /boot/images/; the factory image is never counted or removed), auto_apply (always false in v1 — the updater never auto-flips the default boot label). |
If your firmware server requires Basic Auth (private/staging/internal infrastructure deployments), create the credentials file separately from the conffile so package upgrades don't touch your secret:
sudo cp /usr/share/doc/awesome-o-image-updater/examples/credentials.sample \
/etc/awesome-o/image-updater-credentials
sudo $EDITOR /etc/awesome-o/image-updater-credentials
sudo chmod 0600 /etc/awesome-o/image-updater-credentials
sudo chown root:root /etc/awesome-o/image-updater-credentials
Then in your drop-in /etc/awesome-o/image-updater.conf.d/local.conf, point at it:
[server]
auth_file = /etc/awesome-o/image-updater-credentials
Leave auth_file empty (the default) when the server is public.
Run awesome-o-image check to confirm the configuration parses and the new server endpoint is reachable. A clean check (no error, plausible running: / server: lines) is the strongest signal that your drop-in is correct.
/var/lib/awesome-o-image/state.json — runtime state (current/default/staged/images/last_check_result)./run/awesome-o-image/notify.json — transient one-shot record of the most recent meaningful transition; Cockpit reads this for the banner./var/lib/awesome-o-image/update.lock — exclusive flock; only one mutating operation (stage/apply/rollback/remove) runs at a time. The lock is released automatically on process exit.awesome-o-image lives./etc/awesome-o/; the two tools share that config tree.