Packages, repositories, and proving nothing changed
Domain 1 names package management and the two families answer every question differently. This guide installs the same tool on both, asks each what it installed and where it came from, verifies the files against the package record - including a deliberately tampered binary - and removes it, showing why Debian has two removal verbs and the RPM family has one.
System Management Guide 16 of 28 Beginner
- PlatformsUbuntu 26.04 LTS + AlmaLinux 10.2
- Mandatory access controlAppArmor on Ubuntu, SELinux enforcing on Alma
- Firewallufw / nftables 1.1.6
- TimeAbout 24 min
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| LPLUS-A01 | 192.168.0.73 | Ubuntu 26.04 LTS | Debian-family host - apt, ufw, netplan, AppArmor | 2 Core | 4 GB | 50 GB |
| LPLUS-B01 | 192.168.0.74 | AlmaLinux 10.2 | RPM-family host - dnf, firewalld, NetworkManager, SELinux | 2 Core | 4 GB | 50 GB |
This guide includes
Use this when you need to know what a machine has installed, where a file came from, or whether a binary has been altered. This matters because rpm -V turns "has this been tampered with" into a one-command answer, and because removing a package on Debian without purge leaves its configuration behind.
- counting what is installed and reading which repositories a machine trusts
- finding the package for a command you do not have yet, on both families
- installing, then asking which files arrived and which package owns one
- verifying every file against the package record, and reading
S.5....T. - removing with and without purge, and seeing the
rcstate Debian leaves behind
Before you start
- the-lab-and-the-two-package-families
-
What is installed, and where it came from
An inventory, and the repositories behind it.
bash Example session dpkg -l | grep -c "^ii"; echo "packages installed"; apt-cache policy | head -6765packages installedPackage files: 100 /var/lib/dpkg/status release a=now 500 http://security.ubuntu.com/ubuntu resolute-security/multiverse amd64 Packages release v=26.04,o=Ubuntu,a=resolute-security,n=resolute,l=Ubuntu,c=multiverse,b=amd64 origin security.ubuntu.comrpm -qa | wc -l; echo "packages installed"; dnf repolist | head -61266packages installedrepo id repo nameappstream AlmaLinux 10 - AppStreambaseos AlmaLinux 10 - BaseOScrb AlmaLinux 10 - CRBepel Extra Packages for Enterprise Linux 10 - x86_64extras AlmaLinux 10 - ExtrasExpected result764 packages on the Debian host with
apt-cache policyshowing the archives and their priorities - and 1267 on the RPM host, withbaseos,appstream,crb,epelandextras.Success conditionYou can say what a machine has and which sources it trusts.
-
Finding a package you do not have yet
The query that searches the repository rather than the installed set.
bash Example session sudo dnf provides '*/bin/tree' 2>/dev/null | grep -E "^(tree|Repo|Provide)" | head -5tree-2.1.0-8.el10.x86_64 : File system tree viewerRepo : baseosapt-cache search --names-only '^tree$'; apt-cache policy tree | head -4tree - displays an indented directory tree, in colortree: Installed: (none) Candidate: 2.3.1-1 Version table:Expected result
tree-2.1.0-8.el10.x86_64 : File system tree viewerfromdnf provides, withRepo : baseos- and on Debian, the package description plusInstalled: (none)andCandidate: 2.3.1-1.Success conditionYou can find which package provides a command before installing anything.
-
Installing, and what came with it
One package, then the files and the ownership question.
bash Example session sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tree > /tmp/apt.log 2>&1; grep -E "newly installed|upgraded" /tmp/apt.log | tail -1; dpkg -l tree | tail -1 | awk '{print $1, $2, $3}'0 upgraded, 1 newly installed, 0 to remove and 54 not upgraded.ii tree 2.3.1-1sudo dnf install -y tree > /tmp/dnf.log 2>&1; grep -cE "^Installing|^ tree" /tmp/dnf.log; rpm -q tree2tree-2.1.0-8.el10.x86_64dpkg -L tree | grep -E "bin/|man" | head -4; dpkg -S $(command -v tree)/usr/bin/tree/usr/share/man/usr/share/man/man1/usr/share/man/man1/tree.1.gztree: /usr/bin/treerpm -ql tree | grep -E "bin/|man" | head -4; rpm -qf $(command -v tree)/usr/bin/tree/usr/share/man/man1/tree.1.gztree-2.1.0-8.el10.x86_64Expected result
0 upgraded, 1 newly installedandii tree 2.3.1-1on Debian;tree-2.1.0-8.el10.x86_64on the RPM host - then the binary and man page from each, anddpkg -S/rpm -qfnaming the owning package.Success conditionYou can list what a package installed and find the package behind any file.
-
What a package says about itself
Metadata, and the field one family keeps that the other does not.
bash Example session dpkg -s tree | grep -E "^(Package|Version|Depends|Description)" | head -4Package: treeVersion: 2.3.1-1Depends: libc6 (>= 2.38)Description: displays an indented directory tree, in colorrpm -qi tree | grep -E "^(Name|Version|License|Source RPM)" | head -4; rpm -q --changelog tree | head -2Name : treeVersion : 2.1.0License : GPL-2.0-or-later AND LGPL-2.1-or-laterSource RPM : tree-pkg-2.1.0-8.el10.src.rpm* Mon Nov 04 2024 Vincent Mihalkovic <vmihalko@redhat.com> - 2.1.0-8- fix programming mistakes detected by static analysisExpected result
Package: tree,Version: 2.3.1-1,Depends: libc6 (>= 2.38)on Debian - and on the RPM side the name, version,License: GPL-2.0-or-later, theSource RPM, and a changelog entry from Red Hat dated November 2024.Success conditionYou can read a package's metadata without unpacking it.
-
Proving nothing has been tampered with
A verified package, one byte removed, and the repair.
bash Example session sudo rpm -V tree; echo "--- exit $? : silence means every file matches the package"--- exit 0 : silence means every file matches the packagesudo truncate -s -1 /usr/bin/tree && sudo rpm -V tree; echo "--- exit $? : S size, 5 checksum, T mtime"S.5....T. /usr/bin/tree--- exit 1 : S size, 5 checksum, T mtimesudo dnf reinstall -y tree > /dev/null 2>&1; sudo rpm -V tree; echo "--- exit $? : reinstall restores the package's own copy, and the check is silent again"--- exit 0 : reinstall restores the package's own copy, and the check is silent againExpected resultSilence and exit 0 first - then after one byte is removed,
S.5....T. /usr/bin/treeand exit 1 - and after a reinstall, silence and exit 0 again.Success conditionYou can prove a file still matches the package that shipped it.
-
Removing it, and what each family leaves
Two verbs on one family, one on the other.
bash Example session sudo DEBIAN_FRONTEND=noninteractive apt-get install -y vsftpd > /dev/null 2>&1; dpkg -l vsftpd | tail -1 | awk '{print $1, $2, $3}'; head -2 /var/lib/dpkg/info/vsftpd.conffiles; echo "--- the conffiles, which decide what a remove leaves behind"ii vsftpd 3.0.5-0.4/etc/ftpusers/etc/init.d/vsftpd--- the conffiles, which decide what a remove leaves behindsudo DEBIAN_FRONTEND=noninteractive apt-get remove -y vsftpd > /dev/null 2>&1; dpkg -l vsftpd | tail -1 | awk '{print $1, $2}'; ls -l /etc/vsftpd.conf | awk '{print $5, $9}'; echo "--- rc: removed, configuration kept"rc vsftpd5850 /etc/vsftpd.conf--- rc: removed, configuration keptsudo DEBIAN_FRONTEND=noninteractive apt-get purge -y vsftpd > /dev/null 2>&1; dpkg -l vsftpd 2>&1 | tail -1; ls /etc/vsftpd.conf 2>&1 | tail -1; echo "--- and purge takes the configuration with it"dpkg-query: no packages found matching vsftpdls: cannot access '/etc/vsftpd.conf': No such file or directory--- and purge takes the configuration with itsudo dnf remove -y tree > /dev/null 2>&1; rpm -q tree; echo "--- exit $? : one verb, and no purge distinction to make"package tree is not installed--- exit 1 : one verb, and no purge distinction to makeExpected resultvsftpd installed with conffiles
/etc/ftpusersand/etc/init.d/vsftpd- then after remove, state rc with/etc/vsftpd.confstill on disk at 5,850 bytes - after purge, no package and no file - and on the RPM host,package tree is not installedfrom a single verb.Success conditionYou can remove a package completely, and know when you have not.
Troubleshooting
A binary behaves oddly and you need to know whether it has been altered.
Why: Nothing announces a modified file; the package database has the original size, checksum and timestamp.
Fix:
rpm -V <package>- silence means unchanged. Read the flags:Ssize,5checksum,Tmtime. Repair withdnf reinstall <package>, which restores the package's own copy and its metadata. On Debian,dpkg -Vanddebsums.A removed package's configuration is still in
/etc.Why:
apt removekeeps conffiles and leaves the package in staterc.Fix:
apt purge <pkg>removes them.dpkg -l | grep '^rc'lists every package in that state, which is how you find years of leftovers.You need the package for a command that is not installed.
Why:
dpkg -Sandrpm -qfonly know about installed files.Fix:
dnf provides '*/bin/<command>'searches repository metadata. On Debian installapt-file, runapt-file update, thenapt-file search bin/<command>.A package cannot be found although it exists in the repository.
Why: The local metadata cache is stale, or the repository is not enabled on this machine.
Fix:
sudo apt updateorsudo dnf makecache, then check the source list:apt-cache policyanddnf repolist. A third-party repository such as EPEL may simply not be present.