待整理
你描述的这个需求,在 NixOS 社区里确实已经有了非常成熟的解决方案。你设想的“代理 + 本地缓存”工作流,正是 **Nix Cache Proxy** 这类项目的核心功能。
### 🎯 核心解决方案:ncps
**ncps (Nix Cache Proxy Server)** 是一个高性能的代理服务器,完全实现了你描述的缓存逻辑。它的工作流程是:
1. **请求到达**:Nix 客户端向 ncps 请求一个 store path。
2. **检查本地缓存**:ncps 首先检查本地是否已有该路径。如果有,直接快速返回。
3. **向上游获取**:如果本地没有,ncps 会从配置的上游缓存(如 `cache.nixos.org`)获取。
4. **缓存并签名**:获取后,ncps 会在本地存储一份,并使用自己的私钥对其进行签名,然后返回给客户端。
它**原生支持 Docker 部署**,可以完美融入你的 Docker Compose 工作流。
### 📦 其他可选方案
除了 ncps,还有几个项目也值得了解,你可以根据具体需求进行选择:
* **Spongix**:一个用 Go 编写的代理,同样具备本地缓存和签名功能,并支持将 NAR 文件转发到 S3 进行长期存储。
* **Attic**:一个可自托管的 Nix 二进制缓存服务器,特点是支持**全局去重**和垃圾回收,适合规模较大的部署场景。
* **nix-serve**:Nix 官方的参考实现,功能简单直接,适合快速搭建一个基础的二进制缓存服务。
* **Nginx 透明代理**:如果你不想引入额外的服务,也可以使用 Nginx 的 `proxy_store` 模块,配置一个透明的缓存代理,将上游的包镜像到本地磁盘。
### 🚀 如何在 NixOS 上快速启用
在 NixOS 上,你可以通过 `nix-ld` 来运行 ncps 的 Docker 容器,或者直接使用社区提供的 NixOS 模块。以下是一个 Docker Compose 的配置示例:
```yaml
version: '3.8'
services:
ncps:
image: ghcr.io/kalbasit/ncps:latest
container_name: ncps
restart: unless-stopped
ports:
- "8501:8501"
volumes:
- ncps-storage:/storage
command: >
/bin/ncps serve
--cache-hostname=ncps.local
--cache-storage-local=/storage
--cache-database-url=sqlite:/storage/var/ncps/db/db.sqlite
--cache-upstream-url=https://cache.nixos.org
--cache-upstream-public-key=cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
volumes:
ncps-storage:
```
启动容器后,在你的 NixOS 配置中,将 `substituters` 指向这个代理即可:
```nix
# configuration.nix
nix.settings.substituters = [ "http://ncps.local:8501" ];
```
这样,所有 `nixos-rebuild` 的请求都会优先经过 ncps 代理,实现你期望的加速和缓存效果。
### 💎 总结
**ncps** 是你需求最直接的对应方案,它通过 Docker 部署,完美实现了你描述的“代理 + 缓存 + 签名”的完整工作流。你可以直接从它的 Docker 镜像开始,快速搭建起自己的私有 Nix 缓存代理。
是的,**ncps 可以通过在其 Docker 容器中设置环境变量来使用代理**,这独立于 NixOS 系统的全局代理配置。
### 解决方案:在 Docker Compose 中注入代理环境变量
在 `docker-compose.yml` 文件中,为 `ncps` 服务添加 `environment` 字段,写入 `http_proxy` 和 `https_proxy` 变量即可:
```yaml
services:
ncps:
image: ghcr.io/kalbasit/ncps:latest
# ... 其他配置
environment:
- HTTP_PROXY=http://你的代理地址:端口
- HTTPS_PROXY=http://你的代理地址:端口
- NO_PROXY=localhost,127.0.0.1
# ...
```
### 原理与注意事项
* **独立于宿主系统**:Docker 容器的环境变量与宿主机是隔离的。通过 `environment` 注入的代理设置,能确保 ncps 在向 `cache.nixos.org` 等上游地址发起请求时,流量会经过你指定的代理服务器。
* **区分大小写**:建议同时设置 `HTTP_PROXY` 和 `http_proxy`,以兼容不同的网络库实现。`HTTPS_PROXY`/`https_proxy` 同理。
* **`NO_PROXY` 变量**:推荐设置 `NO_PROXY`,将 `localhost` 和 `127.0.0.1` 排除在外,避免容器内部通信也走代理。
* **代理地址可达性**:请确保你填写的代理地址(如 `http://127.0.0.1:7890`)在 **Docker 容器的网络命名空间内是可达的**。如果代理运行在宿主机上,通常可以使用 `http://host.docker.internal:7890` 或宿主机的局域网 IP 地址。
这样配置后,ncps 就能通过你指定的代理服务器去拉取和缓存包,解决没有全局代理时的网络问题。