How Debian Handles Modified Configuration Files

The Debian operating system ensures system stability and configuration integrity during updates through a built-in mechanism managed primarily by its core package tool, dpkg, alongside helper utilities like ucf. When an updated package provides a new version of a configuration file that the system administrator has locally modified, Debian does not blindly overwrite the changes. Instead, it compares cryptographic hashes across past and present package versions against the on-disk file, prompting the administrator with interactive options or creating staged fallback files to prevent unintended data loss or service disruption.

The Conffile Mechanism

Debian packages designate configuration files located in /etc as conffiles inside their package control metadata. When a package is installed for the first time, dpkg records the MD5 checksum of every shipped conffile into its database at /var/lib/dpkg/status (or internal database files).

During subsequent upgrades, dpkg evaluates three distinct states of the file:

  1. The original state: The MD5 checksum of the file shipped in the previously installed version of the package.
  2. The current state: The MD5 checksum of the file as it currently exists on the disk.
  3. The target state: The MD5 checksum of the file included in the incoming package update.

Decision Logic and Conflict Resolution

By cross-referencing these three states, dpkg determines whether an action requires administrative intervention:

  • Unmodified by user, updated upstream: If the on-disk checksum matches the previous package's checksum, the user has not edited the file. dpkg silently upgrades the file to the new version provided by the package.
  • Modified by user, untouched upstream: If the on-disk checksum does not match the previous package's checksum, but the new package has the exact same checksum as the old package, Debian leaves the local modifications untouched.
  • Both modified by user and updated upstream: If the on-disk file differs from the original package, and the incoming package also introduces changes, a conflict occurs.

When a conflict arises during an interactive update, dpkg suspends the process and presents the user with an interactive prompt. The user is offered several options:

  • Keep the current version: Preserves local changes and saves the new package maintainer's version alongside it with a .dpkg-dist extension.
  • Install the package maintainer's version: Overwrites the file with the incoming upstream version, while archiving the user's modified version alongside it with a .dpkg-old extension.
  • Examine the differences: Displays a side-by-side or unified diff between the running configuration and the proposed new configuration.
  • Spawn a subshell: Allows the administrator to manually edit, inspect, or merge the files before completing the package installation.

Dynamic Configurations via UCF

Standard dpkg conffile tracking works strictly with static files hardcoded into the package archive. However, many packages generate configuration files dynamically via installation scripts (maintainer scripts).

To preserve the integrity of dynamically generated files, Debian employs ucf (Universal Configuration File manager). Working much like dpkg, ucf maintains a dedicated hash registry in /var/lib/ucf/hashfile. Before modifying a dynamically assembled configuration, maintainer scripts invoke ucf to verify whether the file was altered by a user, providing the same interactive conflict-resolution dialogues and backup file creation (.ucf-dist, .ucf-old) as standard conffiles.

Non-Interactive Automation

In automated deployments and headless server environments where interactive prompts are not possible, configuration handling behavior is managed using debconf presets or dpkg force flags. Options such as --force-confold (always keep the old version) or --force-confnew (always install the new version) can be combined with DEBIAN_FRONTEND=noninteractive to enforce deterministic, non-blocking upgrade paths while still generating .dpkg-dist or .dpkg-old artifacts for later review.