1{ lib, ... }:
2{
3 name = "anubis";
4 meta.maintainers = with lib.maintainers; [
5 soopyc
6 nullcube
7 ryand56
8 ];
9
10 nodes.machine =
11 { config, pkgs, ... }:
12 {
13 services.anubis = {
14 defaultOptions = {
15 # Get default botPolicy
16 botPolicy = lib.importJSON "${config.services.anubis.package.src}/data/botPolicies.json";
17 settings = {
18 DIFFICULTY = 3;
19 USER_DEFINED_DEFAULT = true;
20 };
21 };
22 instances = {
23 "".settings = {
24 TARGET = "http://localhost:8080";
25 DIFFICULTY = 5;
26 USER_DEFINED_INSTANCE = true;
27 };
28
29 "tcp" = {
30 user = "anubis-tcp";
31 group = "anubis-tcp";
32 settings = {
33 TARGET = "http://localhost:8080";
34 BIND = ":9000";
35 BIND_NETWORK = "tcp";
36 METRICS_BIND = ":9001";
37 METRICS_BIND_NETWORK = "tcp";
38 };
39 };
40
41 "unix-upstream" = {
42 group = "nginx";
43 settings.TARGET = "unix:///run/nginx/nginx.sock";
44 };
45
46 "botPolicy-default" = {
47 botPolicy = null;
48 settings.TARGET = "http://localhost:8080";
49 };
50
51 "botPolicy-file" = {
52 settings = {
53 TARGET = "http://localhost:8080";
54 POLICY_FNAME = "/etc/anubis-botPolicy.json";
55 };
56 };
57 };
58 };
59
60 # Empty json for testing
61 environment.etc."anubis-botPolicy.json".text = lib.generators.toJSON { } {
62 bots = [
63 {
64 name = "allow-all";
65 user_agent_regex = ".*";
66 action = "ALLOW";
67 }
68 ];
69 };
70
71 # support
72 users.users.nginx.extraGroups = [ config.services.anubis.defaultOptions.group ];
73 services.nginx = {
74 enable = true;
75 recommendedProxySettings = true;
76 virtualHosts."basic.localhost".locations = {
77 "/".proxyPass = "http://unix:${config.services.anubis.instances."".settings.BIND}";
78 "/metrics".proxyPass = "http://unix:${config.services.anubis.instances."".settings.METRICS_BIND}";
79 };
80
81 virtualHosts."tcp.localhost".locations = {
82 "/".proxyPass = "http://localhost:9000";
83 "/metrics".proxyPass = "http://localhost:9001";
84 };
85
86 virtualHosts."unix.localhost".locations = {
87 "/".proxyPass = "http://unix:${config.services.anubis.instances.unix-upstream.settings.BIND}";
88 };
89
90 # emulate an upstream with nginx, listening on tcp and unix sockets.
91 virtualHosts."upstream.localhost" = {
92 default = true; # make nginx match this vhost for `localhost`
93 listen = [
94 { addr = "unix:/run/nginx/nginx.sock"; }
95 {
96 addr = "localhost";
97 port = 8080;
98 }
99 ];
100 locations."/" = {
101 tryFiles = "$uri $uri/index.html =404";
102 root = pkgs.runCommand "anubis-test-upstream" { } ''
103 mkdir $out
104 echo "it works" >> $out/index.html
105 '';
106 };
107 };
108 };
109 };
110
111 testScript = ''
112 for unit in ["nginx", "anubis", "anubis-tcp", "anubis-unix-upstream"]:
113 machine.wait_for_unit(unit + ".service")
114
115 for port in [9000, 9001]:
116 machine.wait_for_open_port(port)
117
118 for instance in ["anubis", "anubis-unix-upstream"]:
119 machine.wait_for_open_unix_socket(f"/run/anubis/{instance}.sock")
120 machine.wait_for_open_unix_socket(f"/run/anubis/{instance}-metrics.sock")
121
122 # Default unix socket mode
123 machine.succeed('curl -f http://basic.localhost | grep "it works"')
124 machine.succeed('curl -f http://basic.localhost -H "User-Agent: Mozilla" | grep anubis')
125 machine.succeed('curl -f http://basic.localhost/metrics | grep anubis_challenges_issued')
126
127 # TCP mode
128 machine.succeed('curl -f http://tcp.localhost -H "User-Agent: Mozilla" | grep anubis')
129 machine.succeed('curl -f http://tcp.localhost/metrics | grep anubis_challenges_issued')
130
131 # Upstream is a unix socket mode
132 machine.succeed('curl -f http://unix.localhost/index.html | grep "it works"')
133
134 # Default user-defined environment variables
135 machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "USER_DEFINED_DEFAULT"')
136 machine.succeed('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "USER_DEFINED_DEFAULT"')
137
138 # Instance-specific user-specified environment variables
139 machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "USER_DEFINED_INSTANCE"')
140 machine.fail('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "USER_DEFINED_INSTANCE"')
141
142 # Make sure defaults don't overwrite themselves
143 machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "DIFFICULTY=5"')
144 machine.succeed('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "DIFFICULTY=3"')
145
146 # Check correct BotPolicy settings are applied
147 machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "POLICY_FNAME=/nix/store"')
148 machine.fail('cat /run/current-system/etc/systemd/system/anubis-botPolicy-default.service | grep "POLICY_FNAME="')
149 machine.succeed('cat /run/current-system/etc/systemd/system/anubis-botPolicy-file.service | grep "POLICY_FNAME=/etc/anubis-botPolicy.json"')
150 '';
151}