Repository navigation
apt proxies: index files are revalidated against the InRelease served with them - #893
Merged
Merged
Conversation
schmitch
force-pushed
the
claude/798-apt-proxy-index-consistency
branch
2 times, most recently
from
November 3, 2026 23:26
74b554d to
4306c74
Compare
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Nov 4, 2026
An apt proxy kept each file under dists/<distribution>/ on its own re-validation clock. With an upstream that has no Acquire-By-Hash, apt fetches Packages at its own path and re-validates only InRelease while its lists are current, so the cached InRelease and Packages drifted apart after an upstream publish and apt-get update failed with "Hash Sum mismatch" for up to the metadata TTL. A format now names the files a cached file is published together with (FormatPlugin::file_releases: apt's InRelease and Release) and reads the size and SHA-256 they list for it (file_listed). The file proxy serves a cached file consistent with them: - it is due once one of them was replaced after it was last checked (Release.gpg drifting from Release included); - it is due when the one served lists it with another size or digest and was checked after it; - when it was stored after the one served was last checked and they disagree, that one is re-validated first. Upstreams with by-hash indexes (Debian, Ubuntu) are served as before. Fixes #798 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012e6DJYtnmoYtz7o9Mp5FTy
schmitch
force-pushed
the
claude/798-apt-proxy-index-consistency
branch
from
November 4, 2026 06:31
4306c74 to
84ad26c
Compare
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.
Fixes #798
What changed
An apt proxy revalidated each file under
dists/<distribution>/on its own clock. If the upstream has noAcquire-By-Hash(reprepro, aptly, packagecloud, many vendor repos), apt fetchesPackagesat its own path, and while its lists are current it revalidates onlyInRelease. After an upstream publish, the proxy could then serve anInReleaseand aPackagesfrom two different publishes, andapt-get updatefailed with "Hash Sum mismatch".Plugin API (
crates/plugin-api): two newFormatPluginmethods, both defaulting to none.file_releases(path)names the files a cached file is published with and listed in.file_listed(release_path, release, path)reads the size and SHA-256 that one of those files lists for it (new typeListedFile).apt (
crates/formats/apt/src/proxy.rs): every non-by-hash file underdists/<distribution>/returnsInRelease, thenRelease.InReleaseandReleaseeach return the other. The listing comes from the existingcleartextandRelease::parse. Pool and by-hash paths are not touched.File proxy (
crates/server/src/files/proxy.rs,fresh_file): besides the TTL (is_due), a cached file is now due when:updated_at) after the file was last checked. This also coversRelease.gpgdrifting fromRelease.The other direction is also handled: if a file was stored after the served release was last checked and the two disagree, the release is revalidated first. This runs after a fresh fetch or a replacement too. Each check is throttled by timestamps, so an upstream that is itself inconsistent costs at most one conditional GET per change, not one per request.
The release listing is read once per release content and cached locally. Reading it and revalidating the release both run in their own task (as
fetch_stored_apartdoes), so request futures don't overflow the stack.Upstreams with by-hash indexes (Debian, Ubuntu) behave as before: apt fetches their indexes by hash, and those copies are immutable.
Docs:
docs/apt.md(proxy section) anddocs/format-plugins.md(the two new methods).No admin API changes, so no web UI screen is needed.
Tests
proxies_serve_indexes_consistent_with_the_release(crates/server/tests/apt.rs) against the mock mirror, with a metadata TTL of one hour:InRelease,Release,Release.gpgandPackages.gz.InReleaseis made due.Packages.gzserved then matches what the newInReleaselists, and thatReleaseandRelease.gpgfollow.Packages.gzis made due, and theInReleaseserved afterwards lists the new one.Packages.gzis479498e8…, 102 bytes, while theInReleaselistsf79dff3d…, 104 bytes.releasesandlisted_inin the apt crate.cargo fmt --all --checkcargo clippy -p forge-server -p forge-plugin-api -p forge-format-apt -p forge-plugin --all-targets -- -D warningscargo test -p forge-plugin-api -p forge-format-apt -p forge-plugincargo test -p forge-server --libcargo test -p forge-server --test apt --test raw --test proxy_cache --test group_proxy --test apt_importcargo xtask changelog --checkChangelog
docs/changes/2.2.0/798.fixed.mdGenerated by Claude Code