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}