An automated provisioning run installing Debian packages with apt-get hangs indefinitely on a full-screen configuration dialog with nobody at the keyboard. Which part of the Debian packaging system produced that prompt, and how do you make such installs run unattended without just accepting whatever defaults you get?
answer
- a script runs before anything is unpacked
- the package asks through a middle layer
- frontend choice, not the package, blocks
- silencing it is not the same as answering it
- the conffile prompt has a different owner
basics
~20 sThe prompt comes from debconf, driven by the package's config maintainer script. Set DEBIAN_FRONTEND=noninteractive to stop it asking, and preseed the answers you actually want with debconf-set-selections before the install so defaults are not silently chosen for you.
solid answer
~50 sThat dialog is **debconf**. A Debian package can ship a `config` maintainer script and a `templates` file; before the package is configured, dpkg runs that script, which asks debconf for answers to its templates and gets them from an interactive frontend if they are not already known. The default frontend is a full-screen dialog, which blocks forever on a machine with no operator. Setting `DEBIAN_FRONTEND=noninteractive` for the install switches to a frontend that never asks and takes each template's default — combine it with `apt-get install -y`. That alone is only half the fix, because the defaults may not be the configuration you want. The complete answer is to *preseed*: feed the answers into the debconf database with `debconf-set-selections` before installing, so the config script finds them already answered. Note that dpkg's own prompt about a locally modified configuration file is separate from debconf and is controlled by `--force-confold` or `--force-confdef`.
code
bash · 13 lines#!/bin/sh
set -eu
# Answer the questions before the package can ask them
debconf-set-selections <<'EOF'
postfix postfix/main_mailer_type select Internet Site
postfix postfix/mailname string mail.example.com
EOF
# Scope the frontend to this command only, and keep local conffiles
DEBIAN_FRONTEND=noninteractive apt-get install -y \
-o Dpkg::Options::=--force-confold \
postfixgo deeper
Know that some Debian packages ask configuration questions during install, that this is debconf, and that unattended installs need DEBIAN_FRONTEND=noninteractive together with apt-get -y.
Explain the mechanics: a config script plus a templates file, questions stored in a debconf database with a priority, and a selectable frontend. Be able to say why dpkg-reconfigure can change an answer after the fact.
Show that silencing prompts is not configuring them — preseed with debconf-set-selections so defaults are never silently accepted — and separate dpkg's conffile prompt from debconf when diagnosing an automated run.
Own the position that maintainer scripts run arbitrary root code on your fleet, and be ready to discuss how you validate, pin and stage third-party packages, and how preseed files are reviewed and version-controlled as configuration rather than pasted into ad-hoc scripts.
## What actually runs when a Debian package is installed Installing a `.deb` is not just unpacking an archive. dpkg runs the package's **maintainer scripts** as root at defined points in the lifecycle: - `preinst` — before the package's files are unpacked - `postinst` — after unpacking, to configure the package (the common case is `postinst configure`) - `prerm` / `postrm` — around removal and purge Those scripts are ordinary executables, usually shell, and they can do arbitrary work: create a system user, generate a key, register a service, migrate a database schema. This is the mechanism that makes `apt-get install` produce a *working* service rather than a directory of files, and it is also why an install can hang, fail halfway, or start a daemon you did not expect. ## debconf: asking the questions before they are needed A package that needs configuration input does not prompt from `postinst`. Debian policy routes it through **debconf**, which exists specifically so that all questions can be asked up front rather than scattered through a long install: - The package ships a **`templates`** file declaring each question — its name (e.g. `some-package/some-question`), its type (`string`, `boolean`, `select`, `password`, `note`), a default, and its **priority** (`low`, `medium`, `high`, `critical`). - It ships a **`config`** script, which dpkg runs *before* unpacking. That script asks debconf for the answers it needs. - debconf consults its own database of previously stored answers. If the answer is already known, it is used silently. If not, and the question's priority is at or above the configured threshold, debconf asks the user through the current **frontend**. The answers persist, which is why reinstalling a package usually does not ask again, and why `dpkg-reconfigure <package>` exists — it re-runs the config script at a chosen priority so you can change an answer later. ## Frontends, and why the automation hangs debconf renders questions through a frontend, selected by the `DEBIAN_FRONTEND` environment variable (or a stored debconf setting). The interesting ones are `dialog` (the full-screen interface, and the default on a normal terminal), `readline` (plain line-by-line prompts), and `noninteractive` (asks nothing at all; every question takes its default, and notes are mailed rather than displayed). `DEBIAN_PRIORITY` sets the threshold, so `DEBIAN_PRIORITY=critical` suppresses everything except the questions the maintainer marked as unskippable. A provisioning run that hangs is almost always the dialog frontend waiting on a keystroke that will never come. Setting `DEBIAN_FRONTEND=noninteractive` for the duration of the install fixes the hang — and, importantly, is a property of *that install command*, not something you want to bake permanently into a machine's environment, because a later interactive administrator would then silently get defaults instead of being asked. ## Preseeding: the part people forget `noninteractive` does not mean "configure it correctly"; it means "take the default". If the default mail configuration, database host or licence acceptance is wrong for you, you have just installed a wrongly configured package silently — which is worse than the hang, because nothing failed. The complete answer is to answer the questions *before* they are asked, by loading them into the debconf database: ```sh debconf-set-selections <<'EOF' some-package some-package/some-question boolean true EOF ``` The line format is `<owner-package> <template-name> <type> <value>`. When the config script runs, debconf already has the answer and never asks. Finding the template names is the practical work: `debconf-show <package>` lists what a package has stored on a machine where it is already installed, which is the usual way to capture a known-good configuration for automation. ## The other prompt, which is not debconf If you have edited a package's configuration file under `/etc` and the package later ships a changed version of that same *conffile*, dpkg itself asks what to do — keep yours, take the maintainer's, show a diff. That prompt comes from **dpkg**, not debconf, so `DEBIAN_FRONTEND` does not govern it. It is controlled with dpkg's force options, typically `--force-confold` (keep the local file) or `--force-confdef` (take the maintainer's default action), passed through apt as a dpkg option. Knowing that these are two different prompting systems is exactly the kind of detail that separates someone who has automated Debian installs from someone who has read a blog post about it. ## When a maintainer script fails If `postinst` exits non-zero, dpkg leaves the package half-configured and apt refuses to proceed cleanly on the next run. The recovery is to fix the underlying cause and run `dpkg --configure -a` to finish configuring everything left pending. A related surprise for automation and image builds: on Debian, installing a service package normally starts the service. The supported way to suppress that is a `policy-rc.d` helper that returns a refusal exit status, not killing the daemon afterwards.
- Why is exporting DEBIAN_FRONTEND=noninteractive permanently in a machine's environment considered a mistake?It is meant to scope a single unattended install. Left set globally, every future install on that machine silently takes template defaults, including ones a human administrator would have wanted to answer — and notes that should have been displayed are suppressed. You get misconfigured packages with no error anywhere. Set it for the command, not for the shell profile or the machine.
- How do you discover which debconf questions a package will ask so you can preseed them?Install it once interactively on a scratch machine, configure it the way you want, then read back what debconf stored with `debconf-show <package>`. That gives you the exact template names, types and values to write into a `debconf-set-selections` file. The package's `templates` file, shipped in its control data, is the other source and documents each question's default and priority.
- An apt run fails partway through and leaves packages half-configured. What do you do?Read the failing maintainer script's output — it is the actual error, and apt's summary usually just says configuration failed. Fix the underlying cause: a missing dependency of the script, a port already bound, a user that cannot be created. Then run `dpkg --configure -a` to complete configuration of everything still pending, and re-run the apt operation.
saying these in an interview costs you the question
- Thinks apt itself generates the configuration dialogs
- Believes noninteractive answers the questions rather than defaulting them
- Expects DEBIAN_FRONTEND to suppress dpkg's modified-conffile prompt
- Pipes yes into apt-get instead of preseeding answers
- Assumes maintainer scripts only copy files into place