fix(build.func): stop a modified conffile from aborting the whole update - #16438
Open
MarcvsTvllivs wants to merge 1 commit into
Open
fix(build.func): stop a modified conffile from aborting the whole update#16438MarcvsTvllivs wants to merge 1 commit into
MarcvsTvllivs wants to merge 1 commit into
Conversation
update_script() runs with no tty. If an update pulls a package whose conffile the operator edited, and the new version also ships a changed copy, dpkg raises its "modified since installation" prompt, finds nothing to read it, and exits with "end of file on stdin at conffile prompt". The package is then left half configured (iU) and apt returns 100, which aborts every other pending package on that container, not just the one being updated. The error surfaced is "APT: Package manager error (broken packages / dependency problems)", which does not mention conffiles. The dpkg --configure -a recovery paths run without --force-conf* and hit the same prompt, so they cannot clear it either. 87 of 583 ct scripts run an apt upgrade inside update_script() and none pass Dpkg::Options, so this hooks the single dispatch in start() that all of them already funnel through, beside the existing check_container_os_guard. The guard is scoped to the update run and removed afterwards, so an operator's own later apt calls are unaffected. It also reports any newly appearing .dpkg-dist / .dpkg-new files, so keeping the local version stays visible instead of silently diverging from upstream. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
✍️ Description
update_script()runs with no tty. When an update pulls a package whose conffile the operator hasedited, and the new version also ships a changed copy of that file,
dpkgraises its "modifiedsince installation" prompt, finds nothing to read it, and fails.
The consequence is larger than the one package:
dpkgexits withend of file on stdin at conffile promptiUaptreturns 100, so every other pending package on that container also stops updatingAPT: Package manager error (broken packages / dependency problems),which never mentions conffiles and points at the wrong thing
dpkg --configure -aatmisc/build.funcandmisc/tools.func, runswithout
--force-conf*and so hits the identical prompt and cannot clear itPoint 3 is the reason this is worth fixing rather than documenting. The container keeps reporting
itself as a normal install while silently accumulating unpatched packages. I found it during a
sweep of 39 containers: one edited conffile had frozen an entire container's package set, and
nothing surfaced it.
Real example, ntfy (installed from
archive.ntfy.sh/apt/, where/etc/ntfy/server.ymlis aregistered conffile). Edit it to enable auth, then update once 2.27.0 ships its own change to it:
Why this is fixed centrally rather than per script
87 of 583
ct/*.shrun an apt upgrade insideupdate_script(), and none of them pass anyDpkg::Options. Rather than edit 87 files and leave every future script free to reintroduce it,this hooks the single dispatch in
start()that all of them already funnel through, next to theexisting
check_container_os_guardpre-flight. Three call sites, one function block.Count reproducible with:
Only
.debpackaged apps can actually hit this, since apps unpacked into/opthave no conffiles,so the real exposure is a subset of the 87.
What the change does
apt_conffile_guard_beginwrites/etc/apt/apt.conf.d/99-community-scripts-conffilewith--force-confdef --force-confold, andapt_conffile_guard_endremoves it again.Two deliberate choices worth flagging for review:
It is scoped to the update run, not permanent. The drop-in is deleted afterwards, so an
operator's own later
aptcalls behave exactly as before. This seemed better than changing apt'sbehaviour for the life of the container.
It reports divergence rather than only silencing it. Suppressing the prompt alone would trade a
loud failure for a silent one, which is the fair objection to this change. So the guard records
which
.dpkg-dist/.dpkg-newfiles existed before, and afterwards warns about any that arenew:
Pre-existing ones are not re-reported on every subsequent update.
--force-confoldis the right default here: silently overwriting an operator's configuration wouldbe worse than the current failure. The cost is that a container keeps its old file when upstream
adds a genuinely new option, which is exactly what the warning above exists to surface. This is the
same tradeoff Debian's own
unattended-upgradesmakes.Note for maintainers
If you would rather have an explicit opt-in helper (an
apt_upgrade_safe()beside the existingapt_update_safe()inmisc/core.func) than a config drop-in, I am happy to rework it that way.That route is more explicit but needs 87 call site edits and leaves future scripts able to
reintroduce the bug, which is why I went central first. Your call.
Testing
bash -non the patchedmisc/build.funcpasses on bash 5.2. (Note it does not parse on bash 3.2either before or after this change, because of the pre-existing
[[ -v NEW["$k"] ]]at line 1719.)Functional test of both guards, run inside real containers on a Proxmox 9.2 node:
_beginapt-config dumpshows--force-confdef/--force-confoldin effect.dpkg-dist.dpkg-distis reported_endapt-config dumpback to noDpkg::Options🔗 Related Issue
No existing issue. Searched open and closed issues for "force-confold", "confold" and "conffile"
and found no match, so this is filed directly as a PR. Happy to open an issue first instead if you
prefer that order.
✅ Prerequisites (X in brackets)
🤖 AI Assistance (X in brackets)
AI was used – written with Claude Opus 5 (max reasoning effort), then reviewed and tested
by me on a live Proxmox 9.2 node before submitting.
One clarification in the interest of not ticking a box loosely:
AGENTS.mdandpve-script-creator.agent.mdare guidance for authoring ct/install scripts, and this PRtouches neither. It is a change to
misc/build.func, so those documents did not apply. Flaggingit rather than claiming conformance I did not have to meet.
🛠️ Type of Change (X in brackets)
README,AppName.md,CONTRIBUTING.md, or other docs.