diff --git a/nixos/modules/services/networking/anubis.nix b/nixos/modules/services/networking/anubis.nix index fefc7001677d..37ab52b51b36 100644 --- a/nixos/modules/services/networking/anubis.nix +++ b/nixos/modules/services/networking/anubis.nix @@ -19,20 +19,8 @@ let (unixAddr settings.BIND_NETWORK settings.BIND) (unixAddr settings.METRICS_BIND_NETWORK settings.METRICS_BIND) ]; - - runtimeDirectoryPrefix = name: "/run/anubis/${instanceName name}/"; instanceUsesUnixSockets = instance: lib.length (unixSocketAddrs instance.settings) > 0; - instanceUsesDedicatedRuntimeDirectory = - name: instance: - lib.any (lib.hasPrefix (runtimeDirectoryPrefix name)) (unixSocketAddrs instance.settings); - useLegacyRuntimeDirectory = - # Set when: - # - Only one instance is configured with unix sockets. - # - No instance uses the new runtime directory prefix: /run/anubis/anubis-. - lib.count instanceUsesUnixSockets (lib.attrValues enabledInstances) == 1 - && !(lib.any (attrs: instanceUsesDedicatedRuntimeDirectory attrs.name attrs.value) ( - lib.attrsToList enabledInstances - )); + runtimeDirectoryPrefix = name: "/run/anubis/${instanceName name}/"; commonSubmodule = isDefault: @@ -204,10 +192,12 @@ let options = { # see other options above BIND = lib.mkOption { - default = "/run/anubis/${instanceName name}.sock"; + default = "${runtimeDirectoryPrefix name}anubis.sock"; description = '' The address that Anubis listens to. See Go's [`net.Listen`](https://pkg.go.dev/net#Listen) for syntax. - Use the prefix "${runtimeDirectoryPrefix ""}". The prefix "/run/anubis" is deprecated. + When using unix sockets: + - use the prefix "${runtimeDirectoryPrefix ""}" if the instance name is the empty string, + - "${runtimeDirectoryPrefix ""}" otherwise. Defaults to Unix domain sockets. To use TCP sockets, set this to a TCP address and `BIND_NETWORK` to `"tcp"`. ''; @@ -215,11 +205,13 @@ let type = types.str; }; METRICS_BIND = lib.mkOption { - default = "/run/anubis/${instanceName name}-metrics.sock"; + default = "${runtimeDirectoryPrefix name}anubis-metrics.sock"; description = '' The address Anubis' metrics server listens to. See Go's [`net.Listen`](https://pkg.go.dev/net#Listen) for syntax. - Use the prefix "${runtimeDirectoryPrefix ""}". The prefix "/run/anubis" is deprecated. + When using unix sockets: + - use the prefix "${runtimeDirectoryPrefix ""}" if the instance name is the empty string, + - "${runtimeDirectoryPrefix ""}" otherwise. The metrics server is enabled by default and may be disabled. However, due to implementation details, this is only possible by setting a command line flag. See {option}`services.anubis.defaultOptions.extraFlags` for an @@ -269,20 +261,22 @@ in }; config = lib.mkIf (enabledInstances != { }) { - warnings = lib.optional useLegacyRuntimeDirectory ''Anubis service: runtime directory is going to be migrated from "anubis" to "anubis/anubis-". Update services.anubis.instances..BIND to "${runtimeDirectoryPrefix ""}anubis.sock" and services.anubis.instances..METRICS_BIND to "${runtimeDirectoryPrefix ""}anubis-metrics.sock". Note: if is "", use the prefix "/run/anubis/anubis".''; - assertions = let validInstanceUnixSocketAddrs = - { name, value }: - lib.all (lib.hasPrefix (runtimeDirectoryPrefix name)) (unixSocketAddrs value.settings); + name: instance: + lib.all (lib.hasPrefix (runtimeDirectoryPrefix name)) (unixSocketAddrs instance.settings); in [ { - assertion = - useLegacyRuntimeDirectory - || lib.all validInstanceUnixSocketAddrs (lib.attrsToList enabledInstances); - message = ''use the prefix "${runtimeDirectoryPrefix ""}" in services.anubis.instances..BIND and services.anubis.instances..METRICS_BIND''; + assertion = lib.all (attrs: validInstanceUnixSocketAddrs attrs.name attrs.value) ( + lib.attrsToList enabledInstances + ); + message = '' + When using unix sockets in services.anubis.instances..settings.BIND and services.anubis.instances..settings.METRICS_BIND: + - use the prefix "${runtimeDirectoryPrefix ""}" if the instance name is the empty string, + - "${runtimeDirectoryPrefix ""}" otherwise. + ''; } ]; @@ -328,14 +322,7 @@ in ExecStart = lib.concatStringsSep " " ( (lib.singleton (lib.getExe cfg.package)) ++ instance.extraFlags ); - RuntimeDirectory = - if useLegacyRuntimeDirectory && instanceUsesUnixSockets instance then - # Warning: `anubis` will be deprecated eventually. - "anubis" - else if instanceUsesUnixSockets instance then - "anubis/${instanceName name}" - else - null; + RuntimeDirectory = if instanceUsesUnixSockets instance then "anubis/${instanceName name}" else null; # hardening NoNewPrivileges = true; CapabilityBoundingSet = null; diff --git a/nixos/tests/anubis.nix b/nixos/tests/anubis.nix index b2b3b2f8fa82..67f21d2e55be 100644 --- a/nixos/tests/anubis.nix +++ b/nixos/tests/anubis.nix @@ -39,72 +39,6 @@ in ryand56 ]; - nodes.machineLegacy = - { config, pkgs, ... }: - { - services.anubis = { - defaultOptions = { - botPolicy = builtins.fromJSON legacyBotPolicyJSON; - settings = { - DIFFICULTY = 3; - USER_DEFINED_DEFAULT = true; - }; - }; - - instances."".settings = { - TARGET = "http://localhost:8080"; - DIFFICULTY = 5; - USER_DEFINED_INSTANCE = true; - }; - - instances."tcp" = { - user = "anubis-tcp"; - group = "anubis-tcp"; - settings = { - TARGET = "http://localhost:8080"; - BIND = "127.0.0.1:9000"; - BIND_NETWORK = "tcp"; - METRICS_BIND = "127.0.0.1:9001"; - METRICS_BIND_NETWORK = "tcp"; - }; - }; - }; - - users.users.nginx.extraGroups = [ config.users.groups.anubis.name ]; - services.nginx = { - enable = true; - recommendedProxySettings = true; - virtualHosts."basic.localhost".locations = { - "/".proxyPass = "http://unix:${config.services.anubis.instances."".settings.BIND}"; - "/metrics".proxyPass = "http://unix:${config.services.anubis.instances."".settings.METRICS_BIND}"; - }; - - virtualHosts."tcp.localhost".locations = { - "/".proxyPass = "http://${config.services.anubis.instances."tcp".settings.BIND}"; - "/metrics".proxyPass = "http://${config.services.anubis.instances."tcp".settings.METRICS_BIND}"; - }; - - # emulate an upstream with nginx, listening on tcp and unix sockets. - virtualHosts."upstream.localhost" = { - default = true; # make nginx match this vhost for `localhost` - listen = [ - { addr = "unix:/run/nginx/nginx.sock"; } - { - addr = "localhost"; - port = 8080; - } - ]; - locations."/" = { - tryFiles = "$uri $uri/index.html =404"; - root = pkgs.runCommand "anubis-test-upstream" { } '' - mkdir $out - echo "it works" >> $out/index.html - ''; - }; - }; - }; - }; - nodes.machine = { config, pkgs, ... }: { @@ -131,8 +65,6 @@ in TARGET = "http://localhost:8080"; DIFFICULTY = 5; USER_DEFINED_INSTANCE = true; - BIND = "/run/anubis/anubis/anubis.sock"; - METRICS_BIND = "/run/anubis/anubis/anubis-metrics.sock"; }; instances."tcp" = { @@ -150,16 +82,12 @@ in instances."another-unix-listen" = { settings = { TARGET = "http://localhost:8080"; - BIND = "/run/anubis/anubis-another-unix-listen/anubis.sock"; - METRICS_BIND = "/run/anubis/anubis-another-unix-listen/anubis-metrics.sock"; }; }; instances."unix-upstream" = { group = "nginx"; settings = { - BIND = "/run/anubis/anubis-unix-upstream/anubis.sock"; - METRICS_BIND = "/run/anubis/anubis-unix-upstream/anubis-metrics.sock"; TARGET = "unix:///run/nginx/nginx.sock"; }; }; @@ -168,8 +96,6 @@ in botPolicy = null; settings = { TARGET = "http://localhost:8080"; - BIND = "/run/anubis/anubis-botPolicy-default/anubis.sock"; - METRICS_BIND = "/run/anubis/anubis-botPolicy-default/anubis-metrics.sock"; }; }; @@ -177,8 +103,6 @@ in settings = { TARGET = "http://localhost:8080"; POLICY_FNAME = "/etc/anubis-botPolicy.json"; - BIND = "/run/anubis/anubis-botPolicy-file/anubis.sock"; - METRICS_BIND = "/run/anubis/anubis-botPolicy-file/anubis-metrics.sock"; }; }; }; @@ -233,61 +157,43 @@ in }; testScript = '' - with subtest("Legacy anubis service configuration: supports only a single RuntimeDirectory"): - for unit in ["nginx", "anubis", "anubis-tcp"]: - machineLegacy.wait_for_unit(unit + ".service") + for unit in ["nginx", "anubis", "anubis-another-unix-listen", "anubis-tcp", "anubis-unix-upstream"]: + machine.wait_for_unit(unit + ".service") - machineLegacy.wait_for_open_unix_socket("/run/anubis/anubis.sock") - machineLegacy.wait_for_open_unix_socket("/run/anubis/anubis-metrics.sock") + for port in [9000, 9001]: + machine.wait_for_open_port(port) - # Default unix socket mode with 1 instance listening on unix sockets. - machineLegacy.succeed('curl -f http://localhost:8080 | grep "it works"') - machineLegacy.succeed('curl -f http://basic.localhost | grep "it works"') - machineLegacy.succeed('curl -f http://basic.localhost -H "User-Agent: Mozilla" | grep anubis') - machineLegacy.succeed('curl -f http://basic.localhost/metrics | grep anubis_challenges_issued') + machine.wait_for_open_unix_socket("/run/anubis/anubis/anubis.sock") + machine.wait_for_open_unix_socket("/run/anubis/anubis/anubis-metrics.sock") + for instance in ["another-unix-listen", "unix-upstream"]: + machine.wait_for_open_unix_socket(f"/run/anubis/anubis-{instance}/anubis.sock") + machine.wait_for_open_unix_socket(f"/run/anubis/anubis-{instance}/anubis-metrics.sock") - # TCP mode. - machineLegacy.succeed('curl -f http://tcp.localhost -H "User-Agent: Mozilla" | grep anubis') - machineLegacy.succeed('curl -f http://tcp.localhost/metrics | grep anubis_challenges_issued') + machine.succeed('curl -f http://basic.localhost | grep "it works"') + machine.succeed('curl -f http://basic.localhost -H "User-Agent: Mozilla" | grep anubis') + machine.succeed('curl -f http://basic.localhost/metrics | grep anubis_challenges_issued') - with subtest("Dedicated RuntimeDirectory"): - for unit in ["nginx", "anubis", "anubis-another-unix-listen", "anubis-tcp", "anubis-unix-upstream"]: - machine.wait_for_unit(unit + ".service") + machine.succeed('curl -f http://another-unix-listen.localhost -H "User-Agent: Mozilla" | grep anubis') + machine.succeed('curl -f http://another-unix-listen.localhost/metrics | grep anubis_challenges_issued') - for port in [9000, 9001]: - machine.wait_for_open_port(port) + # Upstream is a unix socket mode. + machine.succeed('curl -f http://unix.localhost/index.html | grep "it works"') - machine.wait_for_open_unix_socket("/run/anubis/anubis/anubis.sock") - machine.wait_for_open_unix_socket("/run/anubis/anubis/anubis-metrics.sock") - for instance in ["another-unix-listen", "unix-upstream"]: - machine.wait_for_open_unix_socket(f"/run/anubis/anubis-{instance}/anubis.sock") - machine.wait_for_open_unix_socket(f"/run/anubis/anubis-{instance}/anubis-metrics.sock") + # Default user-defined environment variables. + machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "USER_DEFINED_DEFAULT"') + machine.succeed('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "USER_DEFINED_DEFAULT"') - machine.succeed('curl -f http://basic.localhost | grep "it works"') - machine.succeed('curl -f http://basic.localhost -H "User-Agent: Mozilla" | grep anubis') - machine.succeed('curl -f http://basic.localhost/metrics | grep anubis_challenges_issued') + # Instance-specific user-specified environment variables. + machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "USER_DEFINED_INSTANCE"') + machine.fail('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "USER_DEFINED_INSTANCE"') - machine.succeed('curl -f http://another-unix-listen.localhost -H "User-Agent: Mozilla" | grep anubis') - machine.succeed('curl -f http://another-unix-listen.localhost/metrics | grep anubis_challenges_issued') + # Make sure defaults don't overwrite themselves. + machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "DIFFICULTY=5"') + machine.succeed('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "DIFFICULTY=3"') - # Upstream is a unix socket mode. - machine.succeed('curl -f http://unix.localhost/index.html | grep "it works"') - - # Default user-defined environment variables. - machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "USER_DEFINED_DEFAULT"') - machine.succeed('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "USER_DEFINED_DEFAULT"') - - # Instance-specific user-specified environment variables. - machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "USER_DEFINED_INSTANCE"') - machine.fail('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "USER_DEFINED_INSTANCE"') - - # Make sure defaults don't overwrite themselves. - machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "DIFFICULTY=5"') - machine.succeed('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "DIFFICULTY=3"') - - # Check correct BotPolicy settings are applied - machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "POLICY_FNAME=/nix/store"') - machine.fail('cat /run/current-system/etc/systemd/system/anubis-botPolicy-default.service | grep "POLICY_FNAME="') - machine.succeed('cat /run/current-system/etc/systemd/system/anubis-botPolicy-file.service | grep "POLICY_FNAME=/etc/anubis-botPolicy.json"') + # Check correct BotPolicy settings are applied + machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "POLICY_FNAME=/nix/store"') + machine.fail('cat /run/current-system/etc/systemd/system/anubis-botPolicy-default.service | grep "POLICY_FNAME="') + machine.succeed('cat /run/current-system/etc/systemd/system/anubis-botPolicy-file.service | grep "POLICY_FNAME=/etc/anubis-botPolicy.json"') ''; }