Full Removal of Linux Packages
“Fully removed” and “the package manager’s remove command finished successfully” are not always the same thing. This chapter is the direct answer to that gap — what a purge/erase genuinely cleans up automatically, what it deliberately leaves behind on purpose, what it can leave behind by accident or bad maintainer-script design, and a real hands-on hunt through an intentionally imperfect example.
What Removal Actually Guarantees
Both apt purge and rpm -e (or dnf remove) are reliable about one thing: every file recorded in the package database — exactly the list dpkg -L or rpm -ql would have shown you — genuinely gets removed. That guarantee is real, and it’s the entire point of the database-driven model from the first chapter of this section.
What it does not guarantee is that nothing related to that package remains anywhere on the system — because plenty of things a package’s presence causes to exist were never recorded as files the package itself owns in the first place.
Category 1: Files The Running Program Created Itself
A package’s file list records what it installed — not what the program went on to generate while it ran. A log directory the package created (/var/log/hello-tool/, say) is owned by the package and will be removed. The actual log file inside it, written by the running program during normal operation, generally was not part of the original package and may well survive, especially if the directory removal fails simply because it isn’t empty of files the package doesn’t recognize.
Category 2: Application Data, Left Deliberately
Anything under /var/lib/<name>/ holding genuine user or application data — a database’s actual records, for instance — is very often left behind on purpose, following the exact same reasoning that protects modified configuration files: a package manager destroying real data without being asked is a far worse outcome than leaving it for you to deal with deliberately.
Category 3: Administrator-Created Overrides
Recall from the Services & Boot section: /etc/systemd/system/ is where administrator customization lives, distinct from the package-owned /lib/systemd/system/. If you (or a previous administrator) created an override or a custom unit referencing the now-removed package, that file was never owned by the package to begin with — removal won’t touch it, and it’ll sit there referencing a program that no longer exists until someone notices and removes it manually.
Category 4: A Leftover Dedicated Service Account
This is exactly where a maintainer-script bug — or a script that only handles the “happy path” — can leave a genuine trace. If postinst/%pre creates a system account but postrm/%postun never gets around to removing it (or has a logic error, or was never written at all), that account persists indefinitely, invisible to any package-list-based check, since user accounts live in /etc/passwd, entirely outside the package database.
A Hands-On Hunt: Deliberately Leaving A Trace
Extend the hello-tool .deb from earlier in this section to actually demonstrate this, rather than just describing it abstractly. Add to DEBIAN/postinst:
#!/bin/bash
useradd -r -s /usr/sbin/nologin hello-svc 2>/dev/null
mkdir -p /var/log/hello-tool
echo "service started" >> /var/log/hello-tool/activity.log
exit 0And, deliberately incompletely, DEBIAN/postrm — cleaning up the log directory on purge, but forgetting the user account, exactly the kind of realistic gap this hunt is meant to catch:
#!/bin/bash
if [ "$1" = "purge" ]; then
rm -rf /var/log/hello-tool
fi
exit 0Rebuild, install, and purge exactly as covered in the earlier build chapter:
dpkg-deb --build ~/build/hello-pkg hello-tool_1.0.0_amd64.deb
sudo dpkg -i hello-tool_1.0.0_amd64.deb
sudo dpkg -P hello-toolNow hunt for what’s actually left, using tools already covered across this course:
id hello-svcuid=997(hello-svc) gid=997(hello-svc) groups=997(hello-svc)There it is — a genuine leftover, confirmed directly, invisible to dpkg -l entirely since the package itself shows no trace at all. Clean it up manually, the same way the missing postrm step should have:
sudo userdel hello-svcThe Critical Habit: Capture The File List Before You Remove
This is worth internalizing as a standing practice, not just a one-off tip: once a package is purged, dpkg -L/rpm -ql can no longer tell you what it used to own — that information is gone along with the package’s database entry. If you ever anticipate needing to audit a removal thoroughly, save the list first:
dpkg -L somepackage > /tmp/somepackage-files-before-removal.txtA Practical Post-Removal Checklist
# Any leftover account or group with the service's name?
id hello-svc 2>/dev/null
# Any files still owned by a UID/GID that no longer resolves to a name?
find /etc /var -nouser -o -nogroup 2>/dev/null
# Any RPM-side .rpmsave / .rpmnew files left from a previous install?
find /etc -name '*.rpmsave' -o -name '*.rpmnew'
# Any orphaned dependencies still installed?
sudo apt autoremove --dry-run
sudo dnf autoremove --assumeno
# Any systemd unit files or enabled symlinks still referencing the package?
systemctl list-unit-files | grep hello-toolThat find /etc /var -nouser -o -nogroup line is worth understanding specifically: -nouser/-nogroup find files whose owner no longer corresponds to any real account — exactly the state files would end up in if a service account was deleted while it still owned files, or, as demonstrated above, the reverse situation where the account survives but everything it touched is otherwise gone.
Avoid reaching for a blind, system-wide find / -iname "*hello-tool*" as your first move — it’s slow on a large filesystem, and it produces enough false positives (documentation mentioning the name, unrelated matches) to be more noise than signal. The targeted checks above, built directly from the location map in the previous chapter, are a far more reliable way to actually confirm a clean removal.
A Note On Logs In journalctl/syslog
One thing genuinely worth not chasing as “leftover trace”: historical entries in the systemd journal or /var/log/syslog referencing a service that’s since been removed. This is expected, normal behavior — logs are a historical record, and a package manager scrubbing your log history as part of removal would be a genuinely surprising, unwelcome side effect for anyone doing after-the-fact troubleshooting or auditing. Log rotation, covered back in the Services & Boot section, is the correct mechanism for that data eventually aging out — not something a package removal should ever be responsible for.
What’s Next
You can now confidently answer “is this really, completely gone” rather than just trusting a purge command’s exit code. The next chapter shifts to permissions and trust specifically — the security dimension of everything covered so far in this section, and how to pin a package’s version deliberately when you need to.