at 25.11-pre 5.3 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.crab-hole; 9 10 settingsFormat = pkgs.formats.toml { }; 11 12 checkConfig = 13 file: 14 pkgs.runCommand "check-config" 15 { 16 nativeBuildInputs = [ 17 cfg.package 18 pkgs.cacert 19 pkgs.dig 20 ]; 21 } 22 '' 23 ln -s ${file} $out 24 25 ln -s ${file} ./config.toml 26 export CRAB_HOLE_DIR=$(pwd) 27 28 ${lib.getExe cfg.package} validate-config 29 ''; 30in 31{ 32 options = { 33 services.crab-hole = { 34 enable = lib.mkEnableOption "Crab-hole Service"; 35 36 package = lib.mkPackageOption pkgs "crab-hole" { }; 37 38 supplementaryGroups = lib.mkOption { 39 type = lib.types.listOf lib.types.str; 40 default = [ ]; 41 example = [ "acme" ]; 42 description = "Adds additional groups to the crab-hole service. Can be useful to prevent permission issues."; 43 }; 44 45 settings = lib.mkOption { 46 description = "Crab-holes config. See big example https://github.com/LuckyTurtleDev/crab-hole/blob/main/example-config.toml"; 47 48 example = { 49 downstream = [ 50 { 51 listen = "localhost"; 52 port = 8080; 53 protocol = "udp"; 54 } 55 { 56 certificate = "dns.example.com.crt"; 57 dns_hostname = "dns.example.com"; 58 key = "dns.example.com.key"; 59 listen = "[::]"; 60 port = 8055; 61 protocol = "https"; 62 timeout_ms = 3000; 63 } 64 ]; 65 api = { 66 admin_key = "1234"; 67 listen = "127.0.0.1"; 68 port = 8080; 69 show_doc = true; 70 }; 71 blocklist = { 72 allow_list = [ 73 "file:///allowed.txt" 74 ]; 75 include_subdomains = true; 76 lists = [ 77 "https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews-gambling-porn/hosts" 78 "https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt" 79 "file:///blocked.txt" 80 ]; 81 }; 82 upstream = { 83 name_servers = [ 84 { 85 protocol = "tls"; 86 socket_addr = "[2606:4700:4700::1111]:853"; 87 tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com"; 88 trust_nx_responses = false; 89 } 90 { 91 protocol = "tls"; 92 socket_addr = "1.1.1.1:853"; 93 tls_dns_name = "1dot1dot1dot1.cloudflare-dns.com"; 94 trust_nx_responses = false; 95 } 96 ]; 97 options = { 98 validate = false; 99 }; 100 }; 101 }; 102 103 type = lib.types.submodule { 104 freeformType = settingsFormat.type; 105 options = { 106 blocklist = 107 let 108 listOption = 109 name: 110 lib.mkOption { 111 type = lib.types.listOf (lib.types.either lib.types.str lib.types.path); 112 default = [ ]; 113 description = "List of ${name}. If files are added via url, make sure the service has access to them!"; 114 apply = map (v: if builtins.isPath v then "file://${v}" else v); 115 }; 116 in 117 { 118 include_subdomains = lib.mkEnableOption "Include subdomains"; 119 lists = listOption "blocklists"; 120 allow_list = listOption "allowlists"; 121 }; 122 }; 123 }; 124 }; 125 126 configFile = lib.mkOption { 127 type = lib.types.path; 128 description = '' 129 The config file of crab-hole. 130 131 If files are added via url, make sure the service has access to them. 132 Setting this option will override any configuration applied by the settings option. 133 ''; 134 }; 135 }; 136 }; 137 138 config = lib.mkIf cfg.enable { 139 # Warning due to DNSSec issue in crab-hole 140 warnings = lib.optional (cfg.settings.upstream.options.validate or false) '' 141 Validate options will ONLY allow DNSSec domains. See https://github.com/LuckyTurtleDev/crab-hole/issues/29 142 ''; 143 144 services.crab-hole.configFile = lib.mkDefault ( 145 checkConfig (settingsFormat.generate "crab-hole.toml" cfg.settings) 146 ); 147 environment.etc."crab-hole.toml".source = cfg.configFile; 148 149 systemd.services.crab-hole = { 150 wantedBy = [ "multi-user.target" ]; 151 after = [ "network-online.target" ]; 152 wants = [ "network-online.target" ]; 153 description = "Crab-hole dns server"; 154 environment.HOME = "/var/lib/crab-hole"; 155 restartTriggers = [ cfg.configFile ]; 156 serviceConfig = { 157 Type = "simple"; 158 DynamicUser = true; 159 SupplementaryGroups = cfg.supplementaryGroups; 160 161 StateDirectory = "crab-hole"; 162 WorkingDirectory = "/var/lib/crab-hole"; 163 164 ExecStart = lib.getExe cfg.package; 165 166 AmbientCapabilities = "CAP_NET_BIND_SERVICE"; 167 CapabilityBoundingSet = "CAP_NET_BIND_SERVICE"; 168 169 Restart = "on-failure"; 170 RestartSec = 1; 171 }; 172 }; 173 }; 174 175 meta.maintainers = [ 176 lib.maintainers.NiklasVousten 177 ]; 178 # Readme from upstream 179 meta.doc = ./crab-hole.md; 180}