Rex's murmur

大量更新 FreeBSD 時建立 local cache 來加速

因為公司依然使用 FreeBSD 作為第一線 Server ,所以定期就要跑一下系統更新 但因為也是有個十幾台,每一台都在等他下載更新什麼的挺煩的就研究一下怎麼處理

基本概念就是 freebsd-update 等系統工具底層是使用 fetch 進行處理,而 fetch 本身可以利用 HTTP_PROXY 環境變數來設定代理

1. 伺服器端:Nginx 配置

路徑:/usr/local/etc/nginx/nginx.conf (http 區塊)

user www www;
worker_processes  1;

events {
  worker_connections  1024;
}

http {
  include       mime.types;
  default_type  application/octet-stream;

  # 為了確認有中 cache 在這邊改一下 log 把 cache 狀態記錄下來
  log_format cache_status '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    'RT=$request_time Cache=$upstream_cache_status';

  sendfile        on;
  keepalive_timeout  65;

  gzip  off;

  # 這邊啟用 cache 
  proxy_cache_path /var/cache/nginx/fbsd_update 
    levels=1:2 
    keys_zone=fbsd_cache:10m 
    max_size=10g 
    inactive=30d 
    use_temp_path=off;

  server {
    listen 8080;

    # 安全限制:務必限制來源 IP,否則會變成公開代理
    allow 127.0.0.1;
    allow 10.0.0.0/16;
    deny all;

    # 正向代理的關鍵:解析 DNS
    # nginx 預設啟動的時候會把設定檔的 domain name 解一遍,後續就不動作
    # 所以需要設定 resolver 讓他在收到不知道的 domain 要去解
    resolver 8.8.8.8;

    location / {
      proxy_pass $scheme://$http_host$request_uri;

      # 啟用 cache 的設定
      proxy_buffering on; 
      proxy_cache fbsd_cache;

      # 設定一定要 cache
      proxy_no_cache 0;
      proxy_cache_bypass 0;

      # 設定 cache 存活時間
      proxy_cache_valid 200 30d;
      proxy_cache_valid 302 30d;
      proxy_cache_valid 404 1m;

      # 確保 Cache Key 包含 Range,避免不同區段的檔案混淆
      proxy_cache_key "$scheme$http_host$request_uri$http_range";

      # 允許快取帶有 Range 標頭的請求 (關鍵!)
      proxy_set_header Range $http_range;
      proxy_set_header If-Range $http_if_range;
      proxy_cache_bypass $http_upgrade;

      add_header X-Cache-Status $upstream_cache_status;
      access_log /var/log/nginx/fbsd_cache_access.log cache_status;
    }
  }
}

2. 伺服器端:準備目錄

mkdir -p /var/cache/nginx/fbsd_update
chown -R www:www /var/cache/nginx/fbsd_update
service nginx restart

3. 客戶端設定 (每一台 FreeBSD 或 Jail)

# 設定環境變數
export HTTP_PROXY=http://<ip>:<port>

驗證快取命中

  1. 首次抓取:執行 freebsd-update fetch。此時 Nginx Log 應出現 MISS,且外網流量有波動。
  2. 二次抓取:在第二台機器執行相同指令。
    • 速度:下載速度應接近內網極限。
    • 日誌:Nginx Log 應顯示 Cache=HIT。
    • 指令驗證:使用 curl -I -x http://[Proxy]:8080 http://update.freebsd.org/... 檢查 X-Cache-Status 是否為 HIT。