{ config, pkgs, lib, ... }: let cfg = config.qois.nixpkgs-cache; in with lib; { options.qois.nixpkgs-cache = { enable = mkEnableOption ''Enable nixpkgs cache server.''; hostname = mkOption { type = types.str; example = "mycache.myhost.org"; description = "Hostname, under which the cache is served"; }; timeout = mkOption { type = types.str; default = "90d"; description = "Timespan after which cache entries should be removed."; }; size = mkOption { type = types.int; default = 50; description = "in GB; maximum size of the cache on disk."; }; dnsResolvers = mkOption { type = types.listOf types.str; example = [ "8.8.8.8" ]; description = '' List of DNS resolvers to use for upstream cache hostname resolution. Note: IPv6 is not supported currently. ''; }; }; config = mkIf cfg.enable { networking.hosts."127.0.0.1" = [ cfg.hostname ]; services.nginx = { enable = true; resolver.ipv6 = false; # TODO(6): Support IPv6 resolver.addresses = cfg.dnsResolvers; proxyCachePath.nixpkgs-cache = { enable = true; keysZoneName = "nixpkgs_cache"; maxSize = "${builtins.toString cfg.size}G"; keysZoneSize = "${builtins.toString (cfg.size * 3)}M"; # Assumes 3MB keys storage per GB inactive = cfg.timeout; }; virtualHosts.${cfg.hostname} = { kTLS = true; forceSSL = true; enableACME = true; locations."/" = { proxyPass = "https://cache.nixos.org"; recommendedProxySettings = false; extraConfig = '' proxy_cache nixpkgs_cache; proxy_cache_valid ${cfg.timeout}; proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_504 http_403 http_404 http_429; proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie; # Files are immutable so just keep them proxy_cache_lock on; proxy_ssl_server_name on; proxy_ssl_session_reuse off; proxy_ssl_verify on; proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; proxy_set_header Host cache.nixos.org; ''; }; }; }; }; }