Skip to content

Instantly share code, notes, and snippets.

@imthenachoman
Last active August 5, 2026 11:50
Show Gist options
  • Select an option

  • Save imthenachoman/f722f6d08dfb404fed2a3b2d83263118 to your computer and use it in GitHub Desktop.

Select an option

Save imthenachoman/f722f6d08dfb404fed2a3b2d83263118 to your computer and use it in GitHub Desktop.
Debian snapper apt script to include full apt command including arguments as snapshot description

This gist includes an enhancement to Debian's snapper package.

The current (as of 2023-07-23) snapper package includes an apt configuration that will automatically take snapper snapshots when you use apt to install/remove/etc. It will add use "apt" as the description of the pre/post snapshot.

With the below changes to the /etc/apt/apt.conf.d/80snapper file and associated dpkg-pre-post-snapper.sh file, snapper will include the full apt command, including the arguments, in the snapshot description.

For example:

$ sudo apt install funky
...

$ snapper list
...
525  | pre    |       | Sat 22 Jul 2023 11:32:47 PM EDT | root | number   | apt; apt install funky  |
526  | post   |   525 | Sat 22 Jul 2023 11:32:48 PM EDT | root | number   | apt; apt install funky  |
# https://gist.github.com/imthenachoman/f722f6d08dfb404fed2a3b2d83263118
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=770938
DPkg::Pre-Invoke { "/path/to/dpkg-pre-post-snapper.sh pre"; };
DPkg::Post-Invoke { "/path/to/dpkg-pre-post-snapper.sh post"; };
#!/bin/bash
# this script is an enhancement of https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=770938
# we need to work up the process tree to find the apt command that triggered the call to this script
# get the initial PID
PID=$$
# find the apt command by working up the process tree
# loop until
# - PID is empty
# - PID is 1
# - or PID command is apt
while [[ -n "$PID" && "$PID" != "1" && "$(ps -ho comm "${PID}")" != "apt" ]] ; do
# the current PID is not the apt command so go up one by getting the parent PID of hte current PID
PID=$(ps -ho ppid "$PID" | xargs)
done
SNAPPER_DESCRIPTION="apt"
# assuming we found the apt command, get the full args
if [[ "$(ps -ho comm "${PID}")" = "apt" ]] ; then
SNAPPER_DESCRIPTION="$(ps -ho args "${PID}")"
fi
# main event
# source /etc/default/snapper if it exists
if [ -e /etc/default/snapper ] ; then
. /etc/default/snapper
fi
# what action are we taking
if [ "$1" = "pre" ] ; then
# pre, so take a pre snapshot
# if snapper is installed
# and if snapper snapshots are not being disabled using the DISABLE_APT_SNAPSHOT variable
# and if /etc/snapper/configs/root exists
if [ -x /usr/bin/snapper ] && [ ! x$DISABLE_APT_SNAPSHOT = 'xyes' ] && [ -e /etc/snapper/configs/root ] ; then
# delete any lingering temp files
rm -f /var/tmp/snapper-apt || true
# create a snapshot
# and save the snapshot number for reference later
snapper create -d "${SNAPPER_DESCRIPTION}" -c number -t pre -p > /var/tmp/snapper-apt || true
# clean up snapper
snapper cleanup number || true
fi
elif [ "$1" = "post" ] ; then
# post, so take a post snapshot
# if snapper is installed
# and if snapper snapshots are not being disabled using the DISABLE_APT_SNAPSHOT variable
# and if the temp file with the snapshot number from the pre snapshot exists
if [ -x /usr/bin/snapper ] && [ ! x$DISABLE_APT_SNAPSHOT = 'xyes' ] && [ -e /var/tmp/snapper-apt ]
then
# take a post snapshot and link it to the # of the pre snapshot
snapper create -d "${SNAPPER_DESCRIPTION}" -c number -t post --pre-number=`cat /var/tmp/snapper-apt` || true
# clean up snapper
snapper cleanup number || true
fi
fi
@mcsgeek

mcsgeek commented Jul 29, 2026

Copy link
Copy Markdown

Hi @imthenachoman,

Thank you for the clarification and for confirming the licensing. That answers exactly what I needed to know.

I really appreciate the work you put into this. Your idea of moving Debian's inline 80snapper hook into a standalone script and adding process-tree detection provided a much stronger foundation to build on.

My version has grown quite a bit beyond the original gist with additional package manager detection, improved snapshot descriptions, locking, duplicate snapshot prevention, and various reliability improvements, but your work was the starting point that made it possible.

I'll make sure the project documentation properly credits Debian's original 80snapper hook, Debian Bug #770938, and your contributions so the project's history is preserved accurately.

Regarding your question about the license, your confirmation here is exactly what I was hoping to document. If you ever decide to add a GPL-2 license notice to the gist itself, it would certainly make the licensing explicit for future readers, but I don't think it's necessary for my project. Your response here gives me the clarification I was looking for.

I also saw your previous Salsa merge request. That's unfortunate that it never gained any traction. My immediate goal is to get the standalone repository cleaned up, documented, and well tested. If it proves useful, I'd certainly like to see the improvements make their way back into Debian one day.

Thanks again for taking the time to respond and for sharing the original work with the community. I hope you'll take a look at the finished repository once it's published.

@Pugglewuggle

Pugglewuggle commented Jul 29, 2026

Copy link
Copy Markdown

That’s a real shame about the Salsa submission. I looked a while back didn’t and see any activity in that area for Snapper. I suspect it was that - just that there aren’t enough humans to pay attention to it. I’d say once this is tested it’s worth trying again. It’s a major improvement in functionality.

@mcsgeek

mcsgeek commented Aug 3, 2026

Copy link
Copy Markdown

Hi @imthenachoman,

Thanks again for taking the time to answer my questions and clarify the project's origins and licensing. It was a huge help.

I've now published the standalone project:

https://github.com/mcsgeek/dpkg-pre-post-snapper

I've done my best to preserve the project's history and properly acknowledge Debian Bug #770938, Debian's 80snapper implementation, and your work that moved the hook into an external script and introduced process-tree detection.

Thanks again for your original work and for helping me get the attribution and licensing right.

@imthenachoman

Copy link
Copy Markdown
Author

This is great! Thank you. And great job. It’s a lot more useful now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment