Study guide
13.3 Maintainer Scripts and Conffiles
Kali Linux Certified Professional KLCP
Track your progress as you read
Finished sections get a check mark.
1 Introduction & Exam Overview
1.1 Current Exam Facts 1.2 How to Use This Guide & Study Strategy 1.3 PEN-103 Syllabus & Study Path
2 About Kali Linux
2.1 A Bit of History: From BackTrack to Kali 2.2 Kali's Relationship with Debian 2.3 Purpose and Use Cases 2.4 Main Features and Design Policies
3 Getting Started with Kali Linux
3.1 Downloading and Verifying a Kali ISO 3.2 Booting Kali in Live Mode 3.3 Installation Options Overview 3.4 Troubleshooting Installations
4 Linux Fundamentals
4.1 What Linux Is and What It Does 4.2 The Command Line 4.3 The Filesystem Hierarchy Standard 4.4 Useful Commands: Files, Search, Environment
5 Permissions and Process Management
5.1 File Permissions and Ownership 5.2 Managing Processes 5.3 Shells, Variables, and the Environment
6 Installing Kali Linux
6.1 Minimal Installation Requirements 6.2 Step-by-Step Installation on a Hard Drive 6.3 Unattended Installations with Preseeding 6.4 ARM Installations
7 Configuring the Network, Users, and SSH
7.1 Configuring the Network 7.2 Managing Unix Users and Groups 7.3 Configuring SSH
8 Configuring Services
8.1 Apache Web Server 8.2 PostgreSQL Database 8.3 Managing Services with systemd
9 Helping Yourself and Getting Help
9.1 Documentation Sources 9.2 Kali Linux Communities 9.3 Filing Good Bug Reports
10 Security Policy and Network Services
10.1 Defining a Security Policy 10.2 Possible Security Measures 10.3 Securing Network Services
11 Firewalling and Monitoring
11.1 Netfilter and iptables Behavior 11.2 Writing iptables Rules and NAT 11.3 Monitoring and Logging
12 Debian Package Management: APT
12.1 Introduction to APT 12.2 The sources.list File 12.3 Kali Repositories 12.4 Basic Package Interaction with apt
13 dpkg and Advanced Package Management
13.1 dpkg Fundamentals 13.2 Inspecting .deb Files and Package State 13.3 Maintainer Scripts and Conffiles 13.4 APT Pinning and Package Authenticity
14 Advanced Usage
14.1 Modifying and Rebuilding Kali Packages 14.2 Recompiling the Kernel 14.3 Building Custom Kali Live ISO Images 14.4 USB Persistence with LUKS Encryption
15 Kali Linux in the Enterprise
15.1 Network Installation with PXE Boot 15.2 Configuration Management with SaltStack 15.3 Metapackages and Custom Repositories 15.4 Configuration Packages and Forking
16 Introduction to Security Assessments
16.1 Kali Linux in an Assessment 16.2 Types of Assessments 16.3 Types of Attacks 16.4 Formalization and the Road Ahead
13.3 Maintainer Scripts and Conffiles
Key Takeaways Explain This Topic AI
Packages can ship four maintainer scripts — preinst, postinst, prerm, postrm — executed by dpkg at specific points in the install, upgrade, and removal lifecycle
On a fresh install the order is preinst, unpack, postinst configure; on removal the order is prerm remove, delete files, postrm remove, and purge additionally runs postrm purge
Maintainer scripts receive arguments like install, configure, upgrade, remove, purge, and abort-* so a single script can handle every code path
Conffiles are dpkg-tracked configuration files that survive dpkg -r but are deleted by dpkg -P; when you have modified one, upgrades trigger the conffile prompt
--force-confold keeps your version and --force-confnew installs the maintainer's version without prompting; ucf manages config files that are not dpkg conffiles
Last updated: July 2026
The Four Maintainer Scripts
A Debian package is not just files — it can also carry maintainer scripts , shell scripts stored in the control.tar member of the .deb that dpkg executes as root at defined lifecycle points. There are exactly four:
preinst — runs before the package's files are unpacked. Used to stop services, check for conflicting state, or back up data the upgrade will touch.
postinst — runs after unpacking, to finish configuration : create users, set permissions, run update-alternatives , enable systemd units, and generate initial config.
prerm — runs before the package's files are deleted, typically to stop the daemon cleanly.
postrm — runs after deletion, to clean up leftovers; on a purge dpkg first deletes the conffiles itself and then calls postrm purge so the script can remove any remaining state the package created.
Each script receives arguments describing what is happening, so one script handles every code path with a case "$1" in ... esac block. The common arguments are install , upgrade (with the old version as $2 ), configure (with the previously configured version as $2 ), remove , purge , failed-upgrade , and the error-recovery forms abort-install , abort-upgrade , and abort-remove . When a script exits non-zero, dpkg aborts the operation and runs the corresponding rollback script — for example, if a preinst upgrade fails, dpkg runs postrm abort-upgrade to unwind. This argument-and-rollback convention is heavily tested because it explains why packages can fail halfway and still leave the system consistent.
Lifecycle Order: Install, Upgrade, Remove, Purge
The exact sequencing is the most memorization-heavy part of this topic, so lay it out as a table:
- Operation Script sequence
- Fresh install preinst install → unpack files → postinst configure
Upgrade 1.0 → 2.0 old prerm upgrade 2.0 → new preinst upgrade 1.0 → unpack new files → old postrm upgrade 2.0 → new postinst configure 1.0
- Remove prerm remove → delete package files (conffiles stay) → postrm remove
- Purge everything from Remove, then conffiles and .dpkg-* backups deleted by dpkg → postrm purge
Two details trip people up. First, during an upgrade the old package's prerm and postrm run , not the new one's — the new package only contributes its preinst and postinst, because the old scripts are the ones that know how the old version must be shut down. Second, postinst configure is the step skipped when a package is left in the iU (unpacked, unconfigured) state — which is why dpkg --configure -a , covered in Section 13.1, repairs it by simply running the pending postinst scripts.
Conffiles: Configuration Files dpkg Protects
A conffile is a configuration file — typically under /etc — that the package declares in its conffiles control file. dpkg records each conffile's original MD5 checksum at install time (visible in dpkg -s package output) and treats these files differently from ordinary package files:
dpkg -r package removes the package but keeps conffiles , producing the rc status from Section 13.1.
dpkg -P package (purge) deletes conffiles too: dpkg removes them itself and then runs postrm purge .
The rationale: conffiles contain your edits, so removal should not destroy your work, while purge is an explicit "leave nothing behind" decision.
The Conffile Prompt on Upgrade
Trouble arrives when both you and the package maintainer have changed a conffile since the last install. On upgrade, dpkg detects that the on-disk file's checksum differs from the original and stops to ask: Configuration file '/etc/ssh/sshd_config'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ? Your options are:
- Y or I : install the package maintainer's version
- N or O : keep your currently-installed version
- D : show the differences between the versions
- Z : start a shell to examine the situation
The default action is to keep your current version.
*** sshd_config (Y/I/N/O/D/Z) [default=N] ?
Read this prompt precisely for the exam: the default (Enter, N, or O) keeps your version ; Y or I installs the maintainer's version (your file is preserved with a .dpkg-old suffix); choosing to keep yours leaves the new version on disk as .dpkg-dist for comparison. If dpkg finds no local modifications, it silently replaces the file with the new one.
Non-Interactive Control: --force-confold and --force-confnew
Interactive prompts break automation, so dpkg offers force options you will see in unattended Kali upgrade scripts: $ sudo apt -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-confdef" dist-upgrade
--force-confold — always keep the installed version , never prompt.
--force-confnew — always install the maintainer's version , never prompt.
--force-confdef — let dpkg choose the default action without prompting when one exists; if there is no default it still asks, unless --force-confold or --force-confnew is also given, in which case that option decides (which is why the two are normally paired).
--force-confmiss — reinstall a conffile the administrator deleted.
ucf: Config Files Outside dpkg's Tracking
Some packages cannot ship their config as a conffile — for example when the file is generated at install time from a template plus debconf answers, so no fixed checksum exists to declare. Those packages use ucf (Update Configuration File) , a helper that keeps its own checksum registry in /var/lib/ucf/hashfile and presents a similar three-way keep/replace prompt for files dpkg itself does not track. The exam distinction is sharp: conffiles are declared in the package and tracked by dpkg; ucf-managed files are generated post-installation and tracked by ucf. This is also the final answer to "why do files under /etc survive a remove?" — dpkg deliberately never touches user-modified configuration until you say purge , and even generated configs get a managed second chance through ucf rather than blind deletion.
What Purge Does Not Remove
A purge is thorough but not total, and the boundary is exam-worthy. postrm purge deletes the package's conffiles and whatever state the maintainer scripted away, but dpkg still will not touch:
Runtime data — databases in /var/lib/<package>/ , logs in /var/log/ , spool files.
User accounts and groups created by postinst (a leftover postgres system user is normal after purging PostgreSQL).
Files you created inside package-owned directories.
Also keep the file-suffix vocabulary straight, because questions present it as output you must interpret: .dpkg-old is your modified conffile, saved when you accepted the maintainer's version; .dpkg-dist is the maintainer's new version, saved when you kept yours; .dpkg-new is an incoming file temporarily present during the unpack phase. Finally, remember that ucf has its own cleanup path: purging a package whose config is ucf-managed removes the file from ucf's registry, and you can force the question again manually with sudo ucf --purge /etc/somefile.conf followed by reinstalling — a detail that separates ucf-managed files from true conffiles one last time.