diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index e728dcb3f192..12c854335efe 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1282,6 +1282,7 @@ ./services/web-servers/pomerium.nix ./services/web-servers/rustus.nix ./services/web-servers/stargazer.nix + ./services/web-servers/static-web-server.nix ./services/web-servers/tomcat.nix ./services/web-servers/traefik.nix ./services/web-servers/trafficserver/default.nix diff --git a/nixos/modules/services/web-servers/static-web-server.nix b/nixos/modules/services/web-servers/static-web-server.nix new file mode 100644 index 000000000000..07187f00fecc --- /dev/null +++ b/nixos/modules/services/web-servers/static-web-server.nix @@ -0,0 +1,68 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.static-web-server; + toml = pkgs.formats.toml {}; + configFilePath = toml.generate "config.toml" cfg.configuration; +in { + options = { + services.static-web-server = { + enable = lib.mkEnableOption (lib.mdDoc ''Static Web Server''); + listen = lib.mkOption { + default = "[::]:8787"; + type = lib.types.str; + description = lib.mdDoc '' + The "ListenStream" used in static-web-server.socket. + This is equivalent to SWS's "host" and "port" options. + See here for specific syntax: + ''; + }; + root = lib.mkOption { + type = lib.types.path; + description = lib.mdDoc '' + The location of files for SWS to serve. Equivalent to SWS's "root" config value. + NOTE: This folder must exist before starting SWS. + ''; + }; + configuration = lib.mkOption { + default = { }; + type = toml.type; + example = { + general = { log-level = "error"; directory-listing = true; }; + }; + description = lib.mdDoc '' + Configuration for Static Web Server. See + . + NOTE: Don't set "host", "port", or "root" here. They will be ignored. + Use the top-level "listen" and "root" options instead. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ pkgs.static-web-server ]; + systemd.packages = [ pkgs.static-web-server ]; + # Have to set wantedBy since systemd.packages ignores the "Install" section + systemd.sockets.static-web-server = { + wantedBy = [ "sockets.target" ]; + # Start with empty string to reset upstream option + listenStreams = [ "" cfg.listen ]; + }; + systemd.services.static-web-server = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + # Remove upstream sample environment file; use config.toml exclusively + EnvironmentFile = [ "" ]; + ExecStart = [ "" "${pkgs.static-web-server}/bin/static-web-server --fd 0 --config-file ${configFilePath} --root ${cfg.root}" ]; + # Supplementary groups doesn't work unless we create the group ourselves + SupplementaryGroups = [ "" ]; + # If the user is serving files from their home dir, override ProtectHome to allow that + ProtectHome = if lib.hasPrefix "/home" cfg.root then "tmpfs" else "true"; + BindReadOnlyPaths = cfg.root; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ mac-chaffee ]; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 02bef2039075..d62a4dd49fbf 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -709,6 +709,7 @@ in { sssd-ldap = handleTestOn ["x86_64-linux"] ./sssd-ldap.nix {}; stargazer = runTest ./web-servers/stargazer.nix; starship = handleTest ./starship.nix {}; + static-web-server = handleTest ./web-servers/static-web-server.nix {}; step-ca = handleTestOn ["x86_64-linux"] ./step-ca.nix {}; stratis = handleTest ./stratis {}; strongswan-swanctl = handleTest ./strongswan-swanctl.nix {}; diff --git a/nixos/tests/web-servers/static-web-server.nix b/nixos/tests/web-servers/static-web-server.nix new file mode 100644 index 000000000000..da1a9bdec5d2 --- /dev/null +++ b/nixos/tests/web-servers/static-web-server.nix @@ -0,0 +1,32 @@ +import ../make-test-python.nix ({ pkgs, lib, ... } : { + name = "static-web-server"; + meta = { + maintainers = with lib.maintainers; [ mac-chaffee ]; + }; + + nodes.machine = { pkgs, ... }: { + services.static-web-server = { + enable = true; + listen = "[::]:8080"; + root = toString (pkgs.writeTextDir "nixos-test.html" '' +

Hello NixOS!

+ ''); + configuration = { + general = { directory-listing = true; }; + }; + }; + }; + + testScript = '' + machine.start() + machine.wait_for_unit("static-web-server.socket") + machine.wait_for_open_port(8080) + # We don't use wait_until_succeeds() because we're testing socket + # activation which better work on the first request + response = machine.succeed("curl -fsS localhost:8080") + assert "nixos-test.html" in response, "The directory listing page did not include a link to our nixos-test.html file" + response = machine.succeed("curl -fsS localhost:8080/nixos-test.html") + assert "Hello NixOS!" in response + machine.wait_for_unit("static-web-server.service") + ''; +}) diff --git a/pkgs/servers/static-web-server/default.nix b/pkgs/servers/static-web-server/default.nix index 0cedcd50768d..24024d235ff0 100644 --- a/pkgs/servers/static-web-server/default.nix +++ b/pkgs/servers/static-web-server/default.nix @@ -1,4 +1,4 @@ -{ lib, rustPlatform, fetchFromGitHub, stdenv, darwin }: +{ lib, rustPlatform, fetchFromGitHub, stdenv, darwin, nixosTests }: rustPlatform.buildRustPackage rec { pname = "static-web-server"; @@ -24,6 +24,13 @@ rustPlatform.buildRustPackage rec { "--skip=handle_precondition" ]; + # Need to copy in the systemd units for systemd.packages to discover them + postInstall = '' + install -Dm444 -t $out/lib/systemd/system/ systemd/static-web-server.{service,socket} + ''; + + passthru.tests = { inherit (nixosTests) static-web-server; }; + meta = with lib; { description = "An asynchronus web server for static files-serving"; homepage = "https://static-web-server.net/";