aptmatic 0.1.6

A TUI for managing apt updates across debian / ubuntu hosts
aptmatic-0.1.6 is not a library.

aptmatic ๐Ÿค–๐Ÿ“ฆ

Because SSHing into 40 servers one by one to run apt-get upgrade is a cry for help.

CI

A snappy terminal UI for wrangling apt across a fleet of Debian/Ubuntu hosts โ€” written in Rust, because I don't know how to code in OCaml.

โ•ญโ”€ aptmatic โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ Hosts          โ”‚Detail                                          โ”‚
โ”‚ โ–ธ webservers   โ”‚web1.example.com                                โ”‚
โ”‚    โ— web1  [2] โ”‚user: ubuntu  port: 22  sudo: true              โ”‚
โ”‚    โ— web2      โ”‚                                                โ”‚
โ”‚ โ–ธ databases    โ”‚Status: 2 upgrade(s) available (1 security)     โ”‚
โ”‚    โ ผ db1       โ”‚                                                โ”‚
โ”‚    โ— db2       โ”‚Kernel                                          โ”‚
โ”‚                โ”‚Running: 6.1.0-28-amd64                         โ”‚
โ”‚                โ”‚Latest:  linux-image-6.1.0-32-amd64 โ† reboot    โ”‚
โ”‚                โ”‚                                                โ”‚
โ”‚                โ”‚Upgradable                                      โ”‚
โ”‚                โ”‚[sec] curl (7.88.1-10 โ†’ 7.88.1-10+deb12u8)      โ”‚
โ”‚                โ”‚      libcurl4 (7.88.1-10 โ†’ 7.88.1-10+deb12u8)  โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
 r:update+refresh  R:refresh all  u:upgrade  U:upgrade all
 f:full-upgrade  F:full-upgrade all  s:sec-upgrade  S:sec-upgrade all
 a:autoremove  A:autoremove all  p:purge-rc  c:config files  b:reboot
 t:task output  z:zoom  /:search  q:quit

Features

  • ๐Ÿ–ฅ๏ธ Multi-host dashboard โ€” see every host's status at a glance
  • ๐Ÿ‘ฅ Groups โ€” organise hosts and trigger actions on a whole group at once
  • ๐Ÿ”‘ SSH native โ€” talks directly to each host over SSH, no agents or daemons required
  • ๐ŸŒ€ Live task output โ€” watch apt-get upgrade scroll by in real time
  • ๐Ÿง Kernel tracking โ€” know which hosts are silently waiting for a reboot
  • ๐Ÿ“ฆ Held/kept-back packages โ€” spot the stragglers and why they're stuck
  • ๐Ÿ›ก๏ธ Security-update badge โ€” upgradable packages from a security suite are called out separately, with a key to upgrade just those
  • ๐Ÿ” Sidebar search โ€” / to filter hosts/groups by name in a big fleet
  • ๐Ÿ’พ Cached last-known state โ€” the dashboard isn't blank on startup while it reconnects
  • ๐Ÿšฆ Bounded connection concurrency โ€” "all hosts" actions queue instead of opening a connection per host at once
  • ๐Ÿงน RC package purging โ€” one key to purge all those half-removed ghosts
  • ๐Ÿ“ Pending config files โ€” upgrades never stop to ask about a changed conffile; the new version is counted per host and reviewed later, with a diff, on your schedule
  • โฌ†๏ธ Full-upgrade & autoremove โ€” apt-get full-upgrade and apt-get autoremove --purge, on selected hosts or the whole fleet
  • ๐Ÿ” Confirmed reboot โ€” type the hostname to confirm before a host goes down
  • ๐Ÿ–ฑ๏ธ Draggable divider โ€” because you deserve to customise your own TUI
  • ๐Ÿฆ€ Written in Rust โ€” guaranteed* to have no bugs

* guarantee void where prohibited by logic

Installation

cargo install aptmatic

Or build from source:

cargo build --release
# binary at ./target/release/aptmatic

Configuration

aptmatic looks for its config at ~/.config/aptmatic.toml by default. Pass -c /path/to/config.toml to override.

[defaults]
user = "ubuntu"
port = 22
use_sudo = true

[[groups]]
name = "webservers"

[[groups.hosts]]
hostname = "web1.example.com"

[[groups.hosts]]
hostname = "web2.example.com"
user = "admin"   # override per-host

[[groups]]
name = "databases"

[[groups.hosts]]
hostname = "db1.example.com"

Keybindings

Key Action
โ†‘ / k Move up
โ†“ / j Move down
/ Search/filter the sidebar by hostname or group name
r apt-get update + refresh on selected
R apt-get update + refresh on all hosts
u apt-get upgrade on selected
U apt-get upgrade on all hosts
f apt-get full-upgrade on selected
F apt-get full-upgrade on all hosts
s Upgrade security-only packages on selected
S Upgrade security-only packages on all hosts
a apt-get autoremove --purge on selected
A apt-get autoremove --purge on all hosts
p Purge RC packages on selected
c Review pending config files on the selected host
b Reboot the selected host (type the hostname to confirm)
t / Enter View live task output
z Zoom โ€” hide sidebar for clean copy/paste
q / Esc Quit

The sidebar divider is also mouse-draggable if you're feeling fancy.

Pending config files

Upgrades run with --force-confdef --force-confold, so dpkg never stops to ask what to do about a config file you've edited โ€” it keeps yours and drops the maintainer's version next to it as .dpkg-dist. Hosts carrying unresolved files show a [n cfg] badge in the sidebar; c opens a review pane listing them with a diff against the live file. Mark each file with a decision, then execute the whole batch in one go:

Key Action
โ†‘ / โ†“ Select a file
PgUp / PgDn Scroll the diff
d Mark: discard the new version, keeping your current config
a Mark: install the new version, backing your current one up to .dpkg-old
u / Space Unmark
Enter Execute all marked decisions (asks for confirmation first)
Esc Close without touching anything

Marking is free โ€” nothing happens on the host until you confirm with Enter then y. Unmarked files are left pending for a later review, and a failure on one file doesn't stop the rest of the batch. Applying a config file does not restart anything โ€” restart the affected service yourself once you're happy with it.

While searching, type to filter, โ†‘/โ†“ to jump between matches, Enter/Esc to stop editing (the filter stays applied โ€” clear it by backspacing to empty).

Actions on a whole group or "all hosts" are queued through a small connection pool (8 at a time) rather than opening an SSH connection per host simultaneously.

Development

just build   # build
just fmt     # format
just lint    # fmt check + clippy

Why?

Managing a modest fleet of Linux boxes with apt should not require an orchestration platform, a PhD in Ansible, or accepting a cookie banner. aptmatic is a single binary, a TOML file, and a spare SSH key away from a good time.