Eric Radman : a Journal

A Mirror Cache

I regularly rebuild machines in my home lab. To cut down on the delay and bandwidth required to download the same package multiple times a forward proxy can be employed to cache and serve files.

Squid Configuration

cache_dir ufs /var/squid/cache 67275 16 256
refresh_pattern -i .rpm$ 129600 100% 129600 refresh-ims override-expire
maximum_object_size 4096 MB
cache_replacement_policy heap LFUDA
  1. Keeping a maximum of 67GB of data, spread out over the 16 directories and 256 subdirectories
  2. Since this cache is used for packages there is no need to HTTP cache control headers. Instead raise up the expiration times (in minutes) to provide a lifetime of 90 days
  3. By default squid does not cache objects over 4MB, crank this up to 4GB
  4. Enable dynamic aging

Finally, initialize the cache directory

squid -z

Manual Verification

A cache hit is indicated by the Cache-Status header

$ src=http://eradman.com/entrproject/code/entr-5.7.tar.gz
$ curl --proxy http://192.168.2.254:3128 -D - -s -o /tmp/entr-5.7.tgz $src
HTTP/1.1 200 OK
Content-Length: 23587
Content-Type: application/octet-stream
Date: Wed, 11 Feb 2026 19:02:10 UTC
Last-Modified: Thu, 06 Feb 2025 19:52:42 UTC
Server: OpenBSD httpd
Cache-Status: bhyve1;detail=mismatch
Via: 1.1 bhyve1 (squid/7.3)
Connection: keep-alive

$ sleep 120

$ curl --proxy http://192.168.2.254:3128 -D - -s -o /tmp/entr-5.7.tgz $src
HTTP/1.1 200 OK
Content-Length: 23587
Content-Type: application/octet-stream
Date: Wed, 11 Feb 2026 19:04:56 UTC
Last-Modified: Thu, 06 Feb 2025 19:52:42 UTC
Server: OpenBSD httpd
Age: 0
Cache-Status: bhyve1;hit;detail=match
Via: 1.1 bhyve1 (squid/7.3)
Connection: keep-alive

Client Configuration

On RPM-based systems yum will use this cache after setting the proxy option in /etc/dnf/dnf.conf

proxy=http://192.168.2.254:3128

Or for Ubuntu a configuration file in /etc/apt/apt.conf.d/

Acquire::http::Proxy "http://192.168.2.254:3128";
Acquire::https::Proxy "http://192.168.2.254:3128";

Failover

On OpenBSD and FreeBSD, Common Address Redundancy Protocol provides a relatively simple way to set up an IP that will failover if one server is offline. In this example an IP alias is defined on an interface that will float between systems

# /boot/loader.conf
carp_load="YES"
# /etc/rc.conf
ifconfig_em2_alias0="inet vhid 1 advskew 100 pass ****** alias 192.168.2.254/32"

dmesg(8) will show state transitions for the interface

carp: 1@ix0.82: INIT -> BACKUP (initialization complete)
carp: 1@ix0.82: BACKUP -> MASTER (master timed out)

Docker Proxy

Proxy settings for Docker has two aspects: access to repository images and the environment inside a running image.

Adjust the docker service a systemd environment variable to /etc/systemd/system/docker.service.d/

[Service]
Environment="HTTP_PROXY=http://192.168.2.254:3128"
Environment="HTTPS_PROXY=http://192.168.2.254:3128"
Environment="NO_PROXY=localhost,127.0.0.0/8"

To inject proxy settings into the docker runtime, create $HOME/.docker/config.json

{
  "proxies": {
    "default": {
      "httpProxy": "http://192.168.2.254:3129",
      "httpsProxy": "http://192.168.2.254:3129",
      "noProxy": "localhost,127.0.0.0/8"
    }
  }
}

Python

Pip can be configured to use a proxy using .config/pip/pip.conf
[global]
proxy = http://192.168.2.254:3128