nixos/anubis: deprecate legacy runtime directory
This commit is contained in:
@@ -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-<name>.
|
||||
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 "<name>"}". The prefix "/run/anubis" is deprecated.
|
||||
When using unix sockets:
|
||||
- use the prefix "${runtimeDirectoryPrefix ""}" if the instance name is the empty string,
|
||||
- "${runtimeDirectoryPrefix "<name>"}" 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 "<name>"}". The prefix "/run/anubis" is deprecated.
|
||||
When using unix sockets:
|
||||
- use the prefix "${runtimeDirectoryPrefix ""}" if the instance name is the empty string,
|
||||
- "${runtimeDirectoryPrefix "<name>"}" 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-<name>". Update services.anubis.instances.<name>.BIND to "${runtimeDirectoryPrefix "<name>"}anubis.sock" and services.anubis.instances.<name>.METRICS_BIND to "${runtimeDirectoryPrefix "<name>"}anubis-metrics.sock". Note: if <name> 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 "<name>"}" in services.anubis.instances.<name>.BIND and services.anubis.instances.<name>.METRICS_BIND'';
|
||||
assertion = lib.all (attrs: validInstanceUnixSocketAddrs attrs.name attrs.value) (
|
||||
lib.attrsToList enabledInstances
|
||||
);
|
||||
message = ''
|
||||
When using unix sockets in services.anubis.instances.<name>.settings.BIND and services.anubis.instances.<name>.settings.METRICS_BIND:
|
||||
- use the prefix "${runtimeDirectoryPrefix ""}" if the instance name is the empty string,
|
||||
- "${runtimeDirectoryPrefix "<name>"}" 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;
|
||||
|
||||
+29
-123
@@ -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"')
|
||||
'';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user