diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 3fd7ebd1ca7..6ac12e4e138 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -680,6 +680,7 @@ ./services/networking/murmur.nix ./services/networking/mxisd.nix ./services/networking/namecoind.nix + ./services/networking/nar-serve.nix ./services/networking/nat.nix ./services/networking/ndppd.nix ./services/networking/networkmanager.nix diff --git a/nixos/modules/services/networking/nar-serve.nix b/nixos/modules/services/networking/nar-serve.nix new file mode 100644 index 00000000000..ddd42fa0107 --- /dev/null +++ b/nixos/modules/services/networking/nar-serve.nix @@ -0,0 +1,55 @@ +{ config, pkgs, lib, ... }: + +with lib; +let + cfg = config.services.nar-serve; +in +{ + meta = { + maintainers = [ maintainers.rizary ]; + }; + options = { + services.nar-serve = { + enable = mkEnableOption "Serve NAR file contents via HTTP"; + + port = mkOption { + type = types.int; + default = 8383; + description = '' + Port number where nar-serve will listen on. + ''; + }; + + cacheURL = mkOption { + type = types.str; + default = "https://cache.nixos.org/"; + description = '' + Binary cache URL to connect to. + + The URL format is compatible with the nix remote url style, such as: + - http://, https:// for binary caches via HTTP or HTTPS + - s3:// for binary caches stored in Amazon S3 + - gs:// for binary caches stored in Google Cloud Storage + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.nar-serve = { + description = "NAR server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + environment.PORT = toString cfg.port; + environment.NAR_CACHE_URL = cfg.cacheURL; + + serviceConfig = { + Restart = "always"; + RestartSec = "5s"; + ExecStart = "${pkgs.nar-serve}/bin/nar-serve"; + DynamicUser = true; + }; + }; + }; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index e2a5263a95d..7d582aa5921 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -225,6 +225,7 @@ in mysql-backup = handleTest ./mysql/mysql-backup.nix {}; mysql-replication = handleTest ./mysql/mysql-replication.nix {}; nagios = handleTest ./nagios.nix {}; + nar-serve = handleTest ./nar-serve.nix {}; nat.firewall = handleTest ./nat.nix { withFirewall = true; }; nat.firewall-conntrack = handleTest ./nat.nix { withFirewall = true; withConntrackHelpers = true; }; nat.standalone = handleTest ./nat.nix { withFirewall = false; }; diff --git a/nixos/tests/nar-serve.nix b/nixos/tests/nar-serve.nix new file mode 100644 index 00000000000..9ee738ffb17 --- /dev/null +++ b/nixos/tests/nar-serve.nix @@ -0,0 +1,48 @@ +import ./make-test-python.nix ( + { pkgs, lib, ... }: + { + name = "nar-serve"; + meta.maintainers = [ lib.maintainers.rizary ]; + nodes = + { + server = { pkgs, ... }: { + services.nginx = { + enable = true; + virtualHosts.default.root = "/var/www"; + }; + services.nar-serve = { + enable = true; + # Connect to the localhost nginx instead of the default + # https://cache.nixos.org + cacheURL = "http://localhost/"; + }; + environment.systemPackages = [ + pkgs.hello + pkgs.curl + ]; + + networking.firewall.allowedTCPPorts = [ 8383 ]; + + # virtualisation.diskSize = 2 * 1024; + }; + }; + testScript = '' + start_all() + + # Create a fake cache with Nginx service the static files + server.succeed( + "nix copy --to file:///var/www ${pkgs.hello}" + ) + server.wait_for_unit("nginx.service") + server.wait_for_open_port(80) + + # Check that nar-serve can return the content of the derivation + drvName = os.path.basename("${pkgs.hello}") + drvHash = drvName.split("-")[0] + server.wait_for_unit("nar-serve.service") + server.succeed( + "curl -o hello -f http://localhost:8383/nix/store/{}/bin/hello".format(drvHash) + ) + ''; + } +) diff --git a/pkgs/tools/nix/nar-serve/default.nix b/pkgs/tools/nix/nar-serve/default.nix new file mode 100644 index 00000000000..89a38b40a19 --- /dev/null +++ b/pkgs/tools/nix/nar-serve/default.nix @@ -0,0 +1,31 @@ +{ buildGoModule +, fetchFromGitHub +, lib +, stdenv +}: +let + pname = "nar-serve"; + version = "0.3.0"; + +in +buildGoModule rec { + inherit pname version; + + src = fetchFromGitHub { + owner = "numtide"; + repo = "nar-serve"; + rev = "v${version}"; + sha256 = "000xxrar5ngrqqfi7ynx84i6wi27mirgm26brhyg0y4pygc9ykhz"; + }; + + vendorSha256 = "0qkzbr85wkx3r7qgnzg9pdl7vsli10bzcdbj2gqd1kdzwb8khszs"; + + doCheck = false; + + meta = with stdenv.lib; { + description = "Serve NAR file contents via HTTP"; + homepage = "https://github.com/numtide/nar-serve"; + license = licenses.mit; + maintainers = with maintainers; [ rizary ]; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index b20511f88d2..68001e7db32 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -27314,6 +27314,8 @@ in mynewt-newt = callPackage ../tools/package-management/mynewt-newt { }; + nar-serve = callPackage ../tools/nix/nar-serve { }; + inherit (callPackage ../tools/package-management/nix { storeDir = config.nix.storeDir or "/nix/store"; stateDir = config.nix.stateDir or "/nix/var";