Apt-cacher-ng with offline-mode for clients?

tldr:
apt-cacher-ng provides OfflineMode flag in its config, so clients can only request those packages that are already cached. Is it still possible from within the cacher qube to install new or update existing packages in cache?


Longer story:
Hi. Having x online qubes running roughly means a factor x of internet traffic and requests for apt/dnf in comparison to a conventional Linux distro, if I am not mistaken (*1).

Background is, each qube - connected to netvm or with update proxy - searches on its own for repository updates, in order to notify dom0 about template updates.

With 20 qubes, from the outside this even might look like a small company network searching for updates. And conceptionally this makes sense, as in the end we are managing many virtual computers with Qubes OS.

I’d like to reduce this “chatiness” by usage of apt-cacher-ng. But caching downloaded packages is only one side of the coin - each qube will still ask apt-cacher-ng 5 minutes after boot (qubes-update-check.service), if there are new versions. apt-cacher-ng then will ping online repositories. You can test it manually be either installing Opensnitch or tcpdump in a qube.

Hence the idea: Is it possible to configure apt-cacher-ng in offline mode for clients?

  • Clients (AppVM with NetVM, Template with update proxy) can only request, what is already cached in apt-cacher-ng qube.
  • apt-cacher-ng won’t poll for updates on its own.
  • Instead we ask apt-cacher-ng manually and explicitly to update existing packages or load new ones needed in qubes.
  • After manual update, each qube can find these updated, packages in cacher.

This would be a sweet spot between having no update checks at all and every qube doing its own thing.

There seems to be an OfflineMode flag in apt-cacher-ng config, but afaik this is basically an on/off switch and I don’t know if/wether its possible to install new or update existing packages in cache. I couldn’t find a tutorial on it.

In addition to leveraging installation speed and disk space optimizations by apt-cacher-ng, I am also a proponent of explicitly-made internet connections (no fancy connections by apps in the background on their own), hence hope to improve privacy aspects.

Thanks for any help!


(*1) assuming one AppVM per template for maximal compartmentalization and usage of normal templates; please don’t take this estimate too seriously.

1 Like

Why do you really need OfflineMode? By default, apt-cacher-ng will only download the files once and then keep them in cache, and serve it locally to all your qubes. From outside perspective, this will only look like a single Linux system downloading updates.

While it is true, that apt-cacher-ng will download files only once, it still creates a new online request to remote repositories each time any online qube gets started - on behalf of the qube’s automatic update check. With default config apt-cacher-ng basically is same online requests minus re- downloading the whole binary. From privacy perspective I’d just like to reduce the number of automatic internet connections made in the background.

While I don’t have an answer to this question, I’d like to note that there is a tool called apt-clone (on github mvo5/apt-clone) which lets you install and upgrade packages on airgapped machines (or qubes VMs) quite easily. Its what I used a longer while back when I had the same problem.

Could you share some insight / your config files on how you setup said apt-cacher-ng qube? I’d love to do the same.

@tannerlambert Appreciate your suggestion on apt-clone. Will try that out as well after apt-cacher-ng.

One thing first: I am complete beginner with apt-cacher-ng. So if anyone is ahead, you are very welcome to present a possible solution!


Now to question:
Rough idea after some initial research is to let apt-cacher-ng do a partial mirror of package repositories like Debian. This is to be combined with an offline mode for clients, that seems to be configured with Offlinemode: 1.

Emphasis is on partial mirror: Mirror only those packages explicitely needed for client qubes. Say you want to have firefox-esr cached, then put explicit reference to it via PrecacheFor config entry. Everything else would be overkill.

Above link’s site is one of the most comprehensive documentations I could find on apt-cacher-ng - but apparently there is no mentioning of Offlinemode. This sneaky setting is barely found on the net:

If both mirroring + offline mode should work together as I hope, ideal workflow is:

  • Let apt-cacher-ng update/mirror say once a day all configured sources
  • Keep update checks of all qubes active (default)
  • Qubes can only request what is in the cache and not trigger remote requests to online repos (worst case: outdated packages by one day)

At least that’s the plan for next experiments.

There also is a hint for Offlinemode in /etc/apt-cacher-ng/acng.conf:

# Forbid outgoing connections and work without an internet connection or
# respond with 503 error where it's not possible.
# 
# Offlinemode: 0

Thing to test is, if partial mirroring and offline mode are mutual exclusive. I.e. if even partial mirroring wouldn’t be able to consult online sources or if that setting only is in direction to clients.

untested, just some thoughts
Maybe you can run second apt-cacher-ng process with different config where you can set Offlinemode and change port number, log file paths etc so they won’t interfere with one another.
Then set new qrexec policy for offline updates and tag the qubes that should be updated using offline cacher should be tagged with some specific tag.
In dom0 add policy:

qubes.UpdatesProxy +Offline @tag:OfflineUpdates  @default  allow target=cacher

Before other UpdatesProxy policies.
Set some templates to update only using offline cacher:

qvm-tags debian-12-xfce-offline add tag OfflineUpdates

Add the new qrexec UpdatesProxy+Offline in cacher qube:

sudo mkdir /usr/local/etc/qubes-rpc
cat << 'EOF' | sudo tee /usr/local/etc/qubes-rpc/user.UpdatesProxy+Offline
#!/bin/sh
exec socat STDIO TCP4:127.0.0.1:8083
EOF

Then create new systemd service and config with 8083 port and Offlinemode set for apt-cacher-ng.

You mean having two apt-cacher-ng instances with access to the same package cache open - one in offline mode for clients only to read, the other for updating or adding packages manually to the cache? That is a clever idea and might be worth to try out, if offline mode and mirroring don’t work together. Albeit a bit hacky :slight_smile: . Also I don’t know if consistency of the cache is guaranteed, if more instances access it, even possibly concurrently.

It would be great, if we could use a command similar to apt install to either load or update packages in the cache manually within the cacher qube, but I think this is not easily possible:

# install/upgrade something in system
apt install firefox-esr
# load / update something in apt-cacher-ng cache
apt-cacher-ng install firefox-esr

Yes.

Yes, I’m not sure how it works as well, but to be safe you’ll have to keep in mind that you shouldn’t update the qubes using online and offline cacher simultaneously.

There is --download-only option in apt:

apt -d install <package>
   -d, --download-only
       Download only; package files are only retrieved, not unpacked or installed. Configuration Item: APT::Get::Download-Only.

Yeah I know. But how can we use it get something in apt-cacher-ng cache easily?
(If I recall from reading, it requires some nasty move operations.) Would be nice, if the process could be more seamlessly integrated.

PS: Hope to have time to try out some scenarios in the next days.

You need to run apt --download-only in the qube where you want to download the packages without installing them. Then the packages will be downloaded in this qube through cacher.

Interesting - why is that? Does apt within localhost transparently delegate to apt-cacher-ng, if latter package is installed? (Because update proxy is out of the way within localhost and we also haven’t modified any the repository URLs.)

But I assume apt --download-only in localhost would just act like a local client, similar to the remote clients connecting via update proxy, right? In other words, with Offlinemode: 1, local apt wouldn’t be able to add or update packages either, so we still had an on/off switch.

What about enabling updates-proxy-setup in cacher qube itself, so that we could use its local apt to download remote packages manually by using upstream update proxy (like sys-net) and let them put into apt-cacher-ng cache, given what you said? “We have to go deeper” haha. That seems simpler than having two apt-cacher-ng processes. Just some random thoughts as well…

My bad, I’ve missed that you wanted to run the download commands in cacaher qube itself.
For this to work in cacaher qube itself you’ll also need to get all the repositories that are configured in other qubes and set them in cacher qube as well. And you’ll also need to download the packages for different debian version (e.g. oldstable/stable/sid) and backports for them since you don’t know which ones will be requested by the qubes. And it’ll work for debian updates but I’m not sure how to set it up for other OS (Fedora/Arch/Gentoo/etc).