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