Release notes
What changed in each release of pkgproxy, newest first.
0.9.0
Upgrading from 0.8.0:
- Re-run
pkgproxyctl setup lxdorsetup snapcraft, whichever you used (and usesetup rockcraftorsetup charmcraftfor those tools, new in this release). The new LXD profile pointssnap downloadin the containers at pkgproxy, uses pkgproxy's real port and the bridge LXD manages, and keeps apt in the containers from hanging while pkgproxy is offline. - pkgproxy's own API moved from/v1/...to/pkgproxy/v1/...(gitlab.com/zygoon/pkgproxy#75). The old paths answer 404, so a script that reads the stats API (docs/statsapi.md) or calls the admin API needs the new paths, and a setup script saved from an olderpkgproxyctlmust be printed again. - On Linux pkgproxy now goes offline by itself while the machine has no network. To keep the old behaviour, runsnap set pkgproxy auto-offline=off(or start pkgproxy with-auto-offline off). - The statistics file is converted on the first start, with nothing to do. Downloads saved now count packages, modules, images and blobs only, and only the bytes really sent, so the totals shown bypkgproxyctl statsand the cache page come out lower than before. - On a machine logged in to the Snap Store, install or refresh each snap once online with this version before relying on it offline. - Cachedsnap infoanswers are fetched again once after the upgrade. - Commands that take no arguments,pkgproxyincluded, now refuse stray ones instead of ignoring them. - Edge builds briefly had a snap optionoffline. If you set it, runsudo snap unset pkgproxy offlineand useoffline-mode=offlineinstead.Work offline, or leave an overloaded store alone (gitlab.com/zygoon/pkgproxy#54, gitlab.com/zygoon/pkgproxy#57, gitlab.com/zygoon/pkgproxy#61).
The offline mode
offlineserves only what is cached and contacts no mirror, store or registry; what is not cached fails at once, without making apt or snapd retry. The modestore-overloadedstays online but leaves an upstream that fails, times out or answers 429 alone for a while, serving from the cache. The default,never, goes online as needed. In the snap,snap set pkgproxy offline-mode=...andpkgproxyctl offline on|off|modechange the same setting, which survives a restart; without the snap,-offline-mode(orPKGPROXY_OFFLINE_MODE) sets it andpkgproxyctl offlinechanges it until a restart.A change of mode, by hand or with the machine's network, makes pkgproxy ask every upstream again at once, rather than serve cached copies stale for another minute because an upstream failed before.
Go offline with the machine (gitlab.com/zygoon/pkgproxy#55, gitlab.com/zygoon/pkgproxy#77).
On Linux pkgproxy goes offline by itself while the machine has no network, airplane mode included, and comes back when it does. This is the default,
auto-offline=network;auto-offline=airplane-modefollows airplane mode alone, andauto-offline=offturns it off. An explicitpkgproxyctl offline offholds until the machine next goes offline.Install and refresh snaps offline (gitlab.com/zygoon/pkgproxy#58, gitlab.com/zygoon/pkgproxy#78).
snap install,snap downloadandsnap refreshof a snap that was once installed through pkgproxy now work offline, answered from what the store said then, as long as the snap and its assertions are cached. When pkgproxy records an install or refresh, it also fetches the assertions of the snap that it lacks, so an install that snapd half-satisfied from its own copies is still installable offline. This now works on a machine logged in to the Snap Store too: pkgproxy keeps the store's answers to a logged-in snapd (installs, refreshes,snap info,snap find, assertions) when they show only public snaps, and never one that shows a private snap.Cache
snap find, so a search made online is found again offline.Searches are kept for as long as the store says, and an expired answer is served when the store cannot answer. Offline, a search never made online fails at once with pkgproxy's message.
Show when pkgproxy is offline (gitlab.com/zygoon/pkgproxy#66).
pkgproxyctl offlinesays whether and why pkgproxy is offline, andpkgproxyctl statsand the setup page say so too./pkgproxy/v1/infoon the stats socket reports the mode, why it applies, and instore-overloadedmode which upstreams pkgproxy is leaving alone.Add
pkgproxyctl setup rockcraftandsetup charmcraft(gitlab.com/zygoon/pkgproxy#83).They do for rockcraft and charmcraft what
setup snapcraftdoes for snapcraft: point the LXD build containers ofrockcraft packandcharmcraft packat pkgproxy. They work before the tool's first build, creating its LXD project as the tool would; so doessetup lxd -projectfor any other project. A charm's Python packages and charm libraries still bypass pkgproxy.Show visitors how to use pkgproxy from their own machine (gitlab.com/zygoon/pkgproxy#50).
Opening
http://<host>:3142/in a browser, or fetching it withcurl, shows the commands that point apt, snapd, Go, Docker and LXD image remotes at this pkgproxy, so machines without pkgproxy can be set up withcurl -fsSL http://<host>:3142/setup/apt | sudo sh. The page uses the address the visitor reached pkgproxy at, or-public-urlwhen set, and-setup-page=falseturns it off; both are also snap options.Open the setup page from the applications menu (gitlab.com/zygoon/pkgproxy#69).
The snap, now titled PkgProxy, has a desktop entry of that name that opens the setup page in your browser.
pkgproxyctl open(in the snap,pkgproxy.open) does the same from a terminal, and says why when it cannot.Show what fills the cache (gitlab.com/zygoon/pkgproxy#68).
Opened on the machine that runs pkgproxy, the setup page says how much space the cache takes and how much is left on its disk, and links to a new page,
/pkgproxy/cache, with the downloading the cache has saved, the space each kind of download takes, and a map of the archives, snaps, Go modules, LXD images and Docker repositories in it. The sizes are measured in the background while someone looks, at most once a minute, and the page says how old they are. Visitors from other machines see none of this.Publish the documentation at https://zygoon.pl/pkgproxy/ (gitlab.com/zygoon/pkgproxy#74), with a new troubleshooting guide.
docs/troubleshooting.md says where the log is, what the errors that apt, snapd, Go, Docker and LXD print mean, why Docker falls back to Docker Hub without saying so, and how to tell whether a tool really uses pkgproxy.
Add
pkgproxyctl version.It shows the version of pkgproxyctl, of the running pkgproxy and, in the snap, of the snap, and says when the running pkgproxy is another build.
/pkgproxy/v1/inforeportsversion, and the setup page shows it at the bottom. Snap builds no longer carry a spurious+dirtyin their version.Support more of what snapd asks the store (gitlab.com/zygoon/pkgproxy#53).
pkgproxy now caches the store's older v1 API (sections, names, search, details), categories and repairs, caches deltas like snaps, follows the store's redirects to its CDN, and reads compressed store answers instead of passing them on unrewritten. Docker's
referrersrequests go to the registry rather than the snap store, and a request no part of pkgproxy handles gets a 404.Be gentler on the Snap Store (gitlab.com/zygoon/pkgproxy#56).
Answers are kept for the
max-agethe store announces, clients asking the same thing at once share one request to the store, and an expired answer is served when the store answers 429 or 5xx or cannot be reached, instead of passing the failure on.Say in the access log how each request was served.
The "handled request" line of every apt, snap, Go module, LXD and Docker request ends with an
outcome:hit,fetched,revalidated,stale,joined,passthrough,synthesised,tunnelorerror. A response with a 5xx status is logged at error level with the start of its body asresponse, and the line of a snap refresh answered online says what pkgproxy fetched ahead (assertions_fetched,chains_incomplete).Count only content, and only what was sent, as downloads saved.
pkgproxyctl statsand the cache page add up packages, modules, images and blobs, not the indexes that say what there is (such as apt'sPackagesandInRelease), and show the metadata served from the cache on its own (in parentheses in the SAVED column). A hit saves the bytes it sent: nothing for aHEADor a 304, the part for aRangerequest. A request that waited for another's download counts as a hit and the one that started it as a fetch. Each entry of/pkgproxy/v1/statshas a new field,content.Set up LXD and the craft tools more reliably (gitlab.com/zygoon/pkgproxy#62, gitlab.com/zygoon/pkgproxy#64, gitlab.com/zygoon/pkgproxy#67, gitlab.com/zygoon/pkgproxy#71, gitlab.com/zygoon/pkgproxy#73, gitlab.com/zygoon/pkgproxy#83).
The setup scripts configure the local LXD even when another remote is the default, and put pkgproxy on the bridge LXD manages for the project, never Docker's docker0; when there is none, they stop before changing anything. They need the
lxdgroup, not root, so pipe them tosh, notsudo sh; they check first that LXD can be used and stop with an explanation when it cannot, or when pkgproxy is not running. The standalonepkgproxyprofile uses pkgproxy's real port, not always 3142. The profile now also setsSNAPPY_FORCE_API_URL, so thestage-snapsof craft builds (such as every rock'spebble) come through pkgproxy, and apt in the containers getsAcquire::Retries::Delay "false", so it cannot hang while pkgproxy is offline. The snap no longer has anetwork-observeplug.Do not make apt wait while pkgproxy is offline (gitlab.com/zygoon/pkgproxy#72).
In the mode
offline, what is not cached is answered without aRetry-After, which apt 3 waited for, three times, soapt updatetook about 90 seconds instead of about 8.pkgproxyctl setup aptalso addsAcquire::Retries::Delay "false";where apt is older than 3.1.3, such as on Ubuntu 24.04: that apt can hang inapt updatewhen one source fails and the others work (LP: #2003851).Say what each option and setup step does, in plain words (gitlab.com/zygoon/pkgproxy#63).
The help of
pkgproxyandpkgproxyctl, the setup guides, the startup banner, errors and log messages say what happens rather than how it works inside, and no longer name source files or internal packages. The help of each command starts with a usage line that names its arguments, and a wrong number of arguments prints it.Refuse a listen address pkgproxy cannot use in
snap set.snap set pkgproxy addr=...orlxd-tls-addr=...with a value the daemon cannot listen on now fails and keeps the old value, instead of leaving a daemon that cannot start.Revalidate cached account-key assertions, so that clients see the newest revision the store has re-issued.
Drain in-flight requests on SIGTERM, as on SIGINT.
snap stop,systemctl stopand container runtimes send SIGTERM, which killed pkgproxy at once, cutting off downloads and losing the last statistics. It now shuts down gracefully, bounded byshutdown-grace(10s by default).Make the setup scripts safe to pipe to sh, and to run twice.
Every piped setup script is one
{ ... }block, which sh reads in full before running any of it;setup lxd | shfailed the first time becauselxc profile createread the rest of the script as the profile. A setup command that fails makes the sh it is piped to fail too, instead of running nothing and succeeding.-undobefore setting up, or twice, now succeeds and changes nothing forsetup lxd,setup goandsetup lxd-remote, and forsetup snapcraft,setup rockcraftandsetup charmcraft;setup lxd-remote -undoalso touches only the remotes that point at pkgproxy, andsetup docker -undoremoves an emptiedregistry-mirrorskey.setup dockerno longer needsjq, so it works on Ubuntu Core.Let
pkgproxyctl setup lxd-remoterun in a root login, and in a fresh LXD snap install.The script now refuses root only under
sudo, which configures the wrong user, and puts the pinned certificates where a freshly installed LXD snap'slxclooks for them.Write IPv6 listen addresses with brackets in printed setup commands:
-addr [::1]:3142gavehttp://::1:3142, which clients cannot parse.Fix smaller problems.
A cache entry whose file is missing, as in a partly restored cache directory, is fetched again instead of failing with a 500. Headers that a
Connectionheader names are no longer passed between snapd and the store./pkgproxy/v1/offlinereports"auto_offline": "off"instead of leaving the field out.snap set pkgproxyno longer logs AppArmor denials. Commands on the setup and cache pages no longer render in a serif font in some browsers.Test the snap end to end: a spread suite runs it with the real apt, snapd, Docker, Go, LXD, snapcraft, rockcraft and charmcraft of an Ubuntu VM (gitlab.com/zygoon/pkgproxy#82, docs/testing.md).
0.8.0
Make the listening ports configurable in the snap (gitlab.com/zygoon/pkgproxy#25).
snap set pkgproxy addr=...andsnap set pkgproxy lxd-tls-addr=...move pkgproxy off ports 3142 and 3143 when those are taken. The daemon reports its listen addresses at/v1/infoon the stats socket, andpkgproxyctl setupuses them unless-addror-lxd-tls-addris given, so the printed client configuration follows the daemon.Send resumed downloads of a file still being fetched as it arrives (gitlab.com/zygoon/pkgproxy#41).
A
Rangerequest for a file that pkgproxy was still downloading could have up to 4 KiB of the data that had already arrived held back until more came in.Say "no cache hits yet" instead of "none cached yet" in
pkgproxyctl stats, which only lists entries that have been served from the cache at least once.Fix a rare error 500 for an apt package list (gitlab.com/zygoon/pkgproxy#38).
A request for a package list that arrived while pkgproxy was passing a corrupt copy of the same list straight from the mirror to another client got an error instead of the mirror's answer. Cached Go module metadata is now also served with
Last-Modifiedand honoursRangeandIf-Modified-Since, like every other kind of cached file.Keep Go and LXD metadata quick while their upstream is down (gitlab.com/zygoon/pkgproxy#37).
pkgproxy already served the cached copy of a Go module list or an LXD image index when its upstream failed, but only after the failure, which for an upstream that stopped answering meant a timeout per file. As for apt package lists, it now waits at most 10 seconds and leaves a failing upstream alone for a minute.
Stream snap and LXD downloads to every client (gitlab.com/zygoon/pkgproxy#36).
When several machines downloaded the same uncached snap or LXD image at once, only the first got the file as it arrived; the others got nothing until the whole file was cached, long enough for snapd or LXD to give up on a large one, and a cut-short response if the download failed. Resuming such a download with a
Rangerequest also waited for the whole file. Every client now follows the download as it arrives, the same way apt packages and container image layers already were.Relay ETag revalidation on uncached paths (gitlab.com/zygoon/pkgproxy#35).
A client revalidating a file that pkgproxy passes straight to the mirror by
If-None-Matchgot the whole file back instead of304 Not Modified.Give up on upstreams that stop sending (gitlab.com/zygoon/pkgproxy#26).
A mirror or registry that went silent in the middle of a download used to keep that download open forever, and every later request for the same file joined it and hung too, until pkgproxy was restarted. A request now fails once its upstream has sent nothing for
-upstream-idle-timeout(default 60s, alsosnap set pkgproxy upstream-idle-timeout=...), and the next request starts the download afresh. Slow but steady downloads are unaffected, as is time spent sending to slow clients.Stop holding whole packages in memory after a corrupt download (gitlab.com/zygoon/pkgproxy#34).
A package that failed its hash check, from a mirror that also does not announce the file size, was re-read into memory in full for every waiting client before any of them got a byte. It is now streamed.
Keep
apt updateworking while a mirror is down (gitlab.com/zygoon/pkgproxy#33).When checking cached package lists against a mirror failed, apt got an error even though pkgproxy had a copy. pkgproxy now serves its copy and logs a warning, as it already did for Go and LXD. It waits at most 10 seconds for a mirror that does not answer, and leaves a failing mirror alone for a minute, so that an outage does not make each file wait out its own timeout. A list the mirror reports as gone (404 or 410) returns 404.
Fix shared downloads failing when the client that started them left (gitlab.com/zygoon/pkgproxy#32).
When several clients asked for the same uncached file at once and the first of them hung up, the others got an error (apt and Go) or a truncated download (snap and LXD). For snap and LXD, a first client that stays connected but stops reading for a minute is now treated as gone too, instead of holding up everyone else's download.
Fix resumed downloads of uncached files (gitlab.com/zygoon/pkgproxy#31).
A
Rangerequest that pkgproxy passes straight to the mirror got its206 Partial Contentanswer without theContent-Rangeheader that says which part of the file it is.Translate every error and all setup instructions (gitlab.com/zygoon/pkgproxy#27).
All errors pkgproxy reports are now translatable, and failure messages consistently read "cannot ...", in errors, log lines and HTTP error bodies alike. Log messages that operators may grep for changed wording accordingly: for example "failed to open cache directory" is now "cannot open cache directory", and "origin fetch failed" is now "cannot fetch from origin".
pkgproxyctl setupoutput is translated paragraph by paragraph and reflowed to the terminal width, while commands and configuration are always printed verbatim. The Polish translation covers all of it.Translate the daemon's log messages (gitlab.com/zygoon/pkgproxy#27).
Log messages and the errors they carry are now logged in the daemon's locale. Attribute names and other values are unchanged, so log lines keep the same
key=valueshape in every language. The pkgproxy snap's service normally runs in the C locale, so its logs stay in English.Fix flag help mangled by quoting (gitlab.com/zygoon/pkgproxy#29).
pkgproxy -hshowed-admin-socket-path pkgproxyctl setup lxdwhere it meant-admin-socket-path string, andpkgproxyctl setupsubcommands printed the default of-addrand-base-pathtwice.Name the internal handler in the access log.
Each "handled request" line now carries
handler=(apt,snap,gomod,lxd,docker, orlxd-cert), so snap store and Docker registry requests, which both look like/v2/..., can be told apart.Cache Docker Hub images (gitlab.com/zygoon/pkgproxy#20).
pkgproxy now acts as a registry mirror for Docker Hub:
pkgproxyctl setup docker | sudo shadds it to the Docker daemon'sregistry-mirrors, and image manifests and layers are then cached by digest, verified, and served from the cache on every later pull. Tags are revalidated after-docker-revalidate-ttl(default 5m) with a HEAD request, which does not count against Docker Hub's anonymous pull rate limit. Only anonymous pulls of public images are supported. The mirror is on by default and is disabled with-docker-upstream off. Docker requires a mirror at the root of its URL, so the registry API is served at/v2/..., told apart from the snap store's by path shape.pkgproxyctl statsand the stats API report the mirror's layer and config blobs as typedocker, keyed<repository>@<digest>.
0.7.0
Stream cache-miss apt downloads instead of fetching the whole file first (gitlab.com/zygoon/pkgproxy#24).
A miss on a
pool/**package used to stay silent, with no headers, until the entire file had been downloaded from the mirror. Clients that give up on a silent connection (a 300 MB package took 38s; something in a snapcraft/LXD build hung up at ~30s) got502 … context canceled, and because the download was tied to that client it was thrown away, so every retry started from zero and could never finish.The proxy now answers as soon as the mirror does and streams the body while it is cached. The download is independent of any one client, so it completes and is cached even if the client leaves; clients arriving meanwhile, including
Rangeresumes, follow the same download. On a hash mismatch clients still receive the mirror's bytes unmodified and nothing is cached.dists/**metadata is unchanged. How long such a download waits for slow clients is-fill-drain-timeout(default 10m).Tunable intervals (gitlab.com/zygoon/pkgproxy#23).
New flags
-min-forced-revalidate-interval,-stats-checkpoint- interval,-lxd-checkpoint-interval,-shutdown-graceand-read-header-timeoutexpose what were hardcoded constants. Every daemon flag can now also be set through aPKGPROXY_<FLAG>environment variable (flag beats environment beats default), and the snap accepts the interval options viasnap set pkgproxy revalidate-ttl=10metc. See the README's Configuration section.Fix apt cache keys dropping the path prefix before
dists//pool/(gitlab.com/zygoon/pkgproxy#22).The key used to be
<host>/<path from dists/ or pool/ onward>, so archives that differ only in that prefix shared cache entries and index hashes. For Ubuntu (/ubuntu/) the dropped segment was constant, but KDE Neon's/unstable/and/release/editions aliased to one entry, and clients were served the other edition'sInRelease. The key is now<host>/<prefix>/<path>, e.g.archive.ubuntu.com/ubuntu/dists/....**Upgrade note:** existing apt cache entries are stored under the old keys and are no longer found; they are re-fetched once on demand and the old
objects/<host>/{dists,pool}trees can be deleted by hand.Honour
If-Rangeon aptRange(resume) requests.apt resumes a partial download with
RangeplusIf-Rangeset to the partial'sLast-Modified. pkgproxy used to ignoreIf-Rangeand answer206from whatever was cached, so a partial left over from an older generation of an index file got the tail of the newer one spliced on, corrupting the download or failing signature checks. ARangeis now served only ifIf-Rangematches the cached entry (exactLast-Modified, or a strongETag); otherwise the whole body is sent with200. Uncached (passthrough) requests forwardIf-Rangeto the origin. The snap and LXD caches share the same range handling (newinternal/httprange, replacing three copies) and so honourIf-Rangetoo.Answer
If-None-Match/If-Modified-Sincewith304 Not Modifiedon cache hits.apt sends
If-Modified-Sincewhen refreshing an index it already has, but pkgproxy used to resend the whole file every time. A hit whoseLast-Modifiedis not later than the client's date (or whoseETagmatchesIf-None-Match, which takes precedence) now gets a bodyless 304 with the entry's validators. The decision follows the usual TTL/revalidation step, so a 304 is never answered from an entry pkgproxy knows to be stale. Shared by the apt, snap and LXD caches.Honour a client's
Cache-Control: no-cache/max-ageon aptdists/**hits (apt'sAcquire::http::No-Cache/Max-Age).A request that wants fresher content than the cached entry's age (
no-cache,max-age=Nexceeded, orPragma: no-cachealone) now makes pkgproxy revalidate with the origin, with a conditional GET, before serving instead of waiting out-revalidate-ttl. At most one such check per entry every 30 seconds, so a client cannot turn every request into an origin round trip.pool/**and by-hash entries are immutable and unaffected. A forced check cannot replace content the origin keeps reporting as unmodified; usepkgproxyctl cache invalidatefor that.
0.6.1
Fix a
dists/**cache entry outliving its own suite's rotation.A cached
Packages/Sources/Release/InReleaseobject could keep being served — within its-revalidate-ttlwindow, or indefinitely longer via a conditional-GET304from an origin whoseLast-Modifiedlags its content — even after this proxy's own index (refreshed by a newerRelease/InReleasefetch) already expected different content at that path. Real-world symptom: an apt-family client (reported with chisel/snapcraft) fetching a freshReleasethrough the proxy but a stalePackages.gzbehind it, failing that file's checksum against the digestReleasejust gave it. Every serve of adists/**object now cross-checks it against the index first; a disagreement forces a full unconditional refetch instead of trusting the TTL or the origin's conditional-GET response.Add
pkgproxyctl cache invalidate <url>.Evicts one cached apt object (identified by the exact URL a client would fetch it at) without root access to
-cache-dir— the operator escape hatch for a stale entry that needs to go now, backed by a newDELETE /v1/cacheadmin-API route.
0.6.0
Add
-content-socket-path/-lxd-tls-content-socket-path, and asocketscontent-interface slot in the snap package.Additional UNIX-socket listeners alongside the normal
-addr/-lxd-tls-addrTCP ones (unlike-socket-path/-lxd-tls-socket-path, which replace TCP rather than adding to it), so a standalonepkgproxyinstall can share its cache with another snap via the content interface without giving up its own host-side TCP listeners. The snap package binds them under$SNAP_COMMON/sockets/and exposes that directory via a newsocketsslot (content: pkgproxy-sockets) — image-garden is the first consumer, bind-mounting them in place of its own bundled instance.Warn instead of silently dropping
-lxd-tls-socket-path/-lxd-tls-content-socket-pathwhen the LXD HTTPS listener isn't up.Those flags only take effect once the LXD TLS listener actually starts (LXD side on,
-lxd-tls-addrnotoff); with it disabled, the sockets they name simply never appeared, with no indication why. A warning is now logged in that case.Add
-addrtopkgproxyctl setup apt/setup snap.Brings these two in line with
setup go/setup lxd/setup lxd-remote/setup snapcraft, which already let you point the printed instructions at a differently-addressed pkgproxy instance.Make
pkgproxyctl setup lxd's provisioning-file writes atomic and verify the pre-start hook.The admin-API writes (apt/snapd config, the https-rewrite hook script) now go through temp-file-plus-rename, so a reader never sees a partial file and a crash mid-write leaves the previous file (or nothing) rather than a truncated one — a missing or non-executable hook otherwise fails every container on that profile with an opaque
forkstart: exit status 1. The write now also verifies the hook landed and is executable, and every write/remove is logged to the daemon journal.Fix LXD provisioning-file placement for snap-installed LXD.
Files written under
/var/lib/pkgproxyare invisible to a snap-packaged LXD, which only sees/var/snap/<name>inside its own mount namespace — the pre-start hook then failed containers withrun_buffer: Script exited with status 127. The provisioning directory is now resolved by how LXD itself is installed (snap vs. deb/package), not by how pkgproxy is installed, so a host-built pkgproxy driving a snap-installed LXD writes where that LXD can actually read.
0.5.1
No user-visible changes; internal clean-up of the setup commands.
0.5.0
Add
pkgproxyctl setup {apt,snap,go,lxd,snapcraft} -undo.Prints the commands that reverse that subcommand's setup instead of applying it — same TTY-vs-piped split as the existing
| shone-liner, sopkgproxyctl setup apt -undo | shis a complete undo.setup lxd/setup snapcraft -undoskip LXD bridge-IP detection entirely, since none of their undo commands are host-dependent.Add
pkgproxyctl setup snapcraft.Hardwires
setup lxd's-projectlogic to the well-known "snapcraft" LXD project craft-providers/snapcraft builds in, sosnapcraft packusers get correct instructions without needing to know craft-providers' project naming convention.Fix LXD bridge gateway detection under snap strict confinement.
Detection used to shell out through
sh -c "... | awk ... | cut ...", which swallowedip(8)'s own exit status — so a permission failure (netlink denied without thenetwork-observeplug connected) looked identical to "no bridge configured yet" and silently fell back to this machine's hostname, which can itself be wrong (e.g. under WSL). Detection now runsipdirectly and uses sysfs to tell "no such device" apart from "query failed", so a real failure now errors out — with asnap connect pkgproxy:network-observehint, shown only when that plug isn't already connected — instead of guessing. The hostname fallback still applies to the ordinary "no bridge exists yet" case.Fix
pkgproxyctl stats' report header separator for translated locales.The
===line under the report title was hardcoded to the English header's length, so it stopped lining up under longer/shorter translated headers. It's now sized to match.
0.4.0
Add
pkgproxyctl stats -r/?since=windowed reports.pkgproxyctl stats -r <since>(a Unix timestamp, RFC3339 timestamp, or a duration meaning "ago", e.g.-r 30m) and the matching?since=<unix-seconds>parameter on all three stats API routes show activity since a point in time instead of all-time totals — e.g.watch pkgproxyctl stats -r $(date +%s)for the cost of one workload in progress. Backed by a fixed-size, multi-resolution bucket ladder per cache key (exact to the minute for the last 30m, to the hour for 2d, to the day for ~2mo) that rides along in the existing checkpoint file. See docs/design.md §13.6.Update the snap package description and add missing store metadata.
Documents
pkgproxyctl setup apt/snap/go/lxd(replacing the removed startup-banner snippets) and the previously-undocumented Go module caching. Also adds thetitleandcontactfields snapcraft's metadata linter flags as missing on tagged releases.
0.3.0
Add a caching Go module proxy (the GOPROXY protocol).
pkgproxy now also acts as a GOPROXY-protocol module proxy, sharing the same listener and persistent cache as apt and snap: point the go command at it with
GOPROXY=http://<host>:3142/go,directand.mod/.zipcontent is fetched once from an upstream proxy (proxy.golang.org by default), hash-verified against the checksum database, and cached forever. New -go-upstream, -go-base-path, -go-revalidate-ttl and -go-sumdb daemon flags;pkgproxyctl setup goprints copy-paste-ready GOPROXY setup instructions, the same shape assetup apt/setup snap.Route Go module traffic through pkgproxy in LXD build containers too.
pkgproxyctl setup lxdnow also setsenvironment.GOPROXYon the LXD profile it configures, so snapcraft/craft-providers build containers pick it up for every process automatically, not just apt/snap traffic.Remove
pkgproxyctl setup lxd's --apply flag.One way to actually apply the printed configuration now, consistent with every other
setupsubcommand: pipe the output throughsh(pkgproxyctl setup lxd | sh).
0.2.1
Fix the pkgproxy.svg icon's aspect ratio.
Its viewBox was wider than tall, so snapcraft.io's square icon tile stretched it non-uniformly and squished it horizontally. Padded the viewBox to a square 112x112 (8px added above and below, artwork unchanged) so it renders undistorted.
0.2.0
Add a read-only stats REST API and a pkgproxyctl CLI to read it.
pkgproxy now tracks cache hit/fetch counts and bytes saved, exposed as JSON over a second UNIX socket (-stats-socket-path): GET /v1/stats/snaps (per-snap download/hit/revision counts and bandwidth saved, rolled up across every cached revision of that snap) and GET /v1/stats/debs (apt pool files ranked by bytes saved — the packages actually worth caching). Counts persist across restarts, checkpointed to <cache-dir>/stats.json every 30 seconds and on a clean shutdown.
pkgproxyctl is a new CLI for reading it:
pkgproxyctl statsrenders a human-readable report (per-snap table, top-apt-packages table, overall bandwidth-saved summary), or the same data as JSON with -json for scripting. It's the same compiled binary as the pkgproxy daemon, dispatched by which name it was invoked as (apkgproxyctlsymlink topkgproxyin the snap), so it adds negligible size.Both -stats-socket-path and pkgproxyctl's -socket-path are optional: they default to $SNAP_COMMON/stats.sock inside a snap, or /run/pkgproxy/stats.sock otherwise (with -cache-dir's own default moving to /var/cache/pkgproxy, the matching FHS/systemd convention) — the common case needs no flags on either side.
Add -socket-path: listen on a UNIX socket instead of TCP.
Lets pkgproxy be bridged into an environment that only has a UNIX socket to offer it — e.g. a host proxy reached from inside a VM guest over a QEMU guestfwd forwarded straight to a UNIX socket (see image-garden, the motivating case) — without needing TCP at all.