Tracking packages installed

To help with restores or migration to another piece of hardware I find it useful to keep track of which packages are installed on my Linux systems. This isn’t very difficult, but it has taken a bit of experimenting to come up with with something that works fairly well and is automated.

Create in /etc/systemd/system/status-email-root@.service. This is a helper service for sending emails on service failures.

[Unit]
Description=status email for %i to Jon

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/systemd-email.sh root %i

/usr/local/sbin/systemd-email.sh looks like this

#!/bin/sh

debug() { ! "${log_debug-false}" || log "DEBUG: $*" >&2; }
log() { printf '%s\n' "$*"; }
warn() { log "WARNING: $*" >&2; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$*"; exit 1; }
try() { "$@" || fatal "'$@' failed"; }

mydir=$(cd "$(dirname "$0")" && pwd -L) || fatal "Unable to determine script directory"


/usr/sbin/sendmail -t <<ERRMAIL
To: $1
From: systemd <root@$HOSTNAME>
Subject: $2
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset=UTF-8

$(systemctl status --full "$2")
ERRMAIL

Create in /etc/systemd/system/track-installed-packages.service with the content. Note the “showmanual” argument to “apt-mark”. This makes sure to only output the packages that were manually installed and not include those that were installed as dependencies. This keeps the list short and if dependencies change later keeps from installed unneeded packages later.

[Unit]
Description=track installed packages
OnFailure=status-email-root@%n.service

[Service]
Type=oneshot
ExecStart=/usr/bin/apt-mark showmanual
StandardOutput=file:/home/installed-packages.txt

Now create /etc/systemd/system/track-installed-packages.timer

[Unit]
Description=track installed packages daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Now enable the timer with

systemctl daemon-reload
systemctl enable track-installed-packages.timer
systemctl start track-installed-packages.timer

Now if you backup /home, you’ll always have the most recent list of installed packages.

I have a similar pair of systemd files for snaps that calls “snap list” and outputs to “/home/snap-packages.txt”. Snap doesn’t appear to have an option to specify only manually installed snaps. This may also error out if there are no snaps installed.