1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8with lib;
9
10let
11 cfg = config.services.stubby;
12 settingsFormat = pkgs.formats.yaml { };
13 confFile = settingsFormat.generate "stubby.yml" cfg.settings;
14in
15{
16 imports =
17 [
18 (mkRemovedOptionModule [
19 "stubby"
20 "debugLogging"
21 ] "Use services.stubby.logLevel = \"debug\"; instead.")
22 ]
23 ++ map
24 (
25 x:
26 (mkRemovedOptionModule [
27 "services"
28 "stubby"
29 x
30 ] "Stubby configuration moved to services.stubby.settings.")
31 )
32 [
33 "authenticationMode"
34 "fallbackProtocols"
35 "idleTimeout"
36 "listenAddresses"
37 "queryPaddingBlocksize"
38 "roundRobinUpstreams"
39 "subnetPrivate"
40 "upstreamServers"
41 ];
42
43 options = {
44 services.stubby = {
45
46 enable = mkEnableOption "Stubby DNS resolver";
47
48 settings = mkOption {
49 type = types.attrsOf settingsFormat.type;
50 example = lib.literalExpression ''
51 pkgs.stubby.passthru.settingsExample // {
52 upstream_recursive_servers = [{
53 address_data = "158.64.1.29";
54 tls_auth_name = "kaitain.restena.lu";
55 tls_pubkey_pinset = [{
56 digest = "sha256";
57 value = "7ftvIkA+UeN/ktVkovd/7rPZ6mbkhVI7/8HnFJIiLa4=";
58 }];
59 }];
60 };
61 '';
62 description = ''
63 Content of the Stubby configuration file. All Stubby settings may be set or queried
64 here. The default settings are available at
65 `pkgs.stubby.passthru.settingsExample`. See
66 <https://dnsprivacy.org/wiki/display/DP/Configuring+Stubby>.
67 A list of the public recursive servers can be found here:
68 <https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Test+Servers>.
69 '';
70 };
71
72 logLevel =
73 let
74 logLevels = {
75 emerg = 0;
76 alert = 1;
77 crit = 2;
78 error = 3;
79 warning = 4;
80 notice = 5;
81 info = 6;
82 debug = 7;
83 };
84 in
85 mkOption {
86 default = null;
87 type = types.nullOr (types.enum (attrNames logLevels ++ attrValues logLevels));
88 apply = v: if isString v then logLevels.${v} else v;
89 description = "Log verbosity (syslog keyword or level).";
90 };
91
92 };
93 };
94
95 config = mkIf cfg.enable {
96 assertions = [
97 {
98 assertion = (cfg.settings.resolution_type or "") == "GETDNS_RESOLUTION_STUB";
99 message = ''
100 services.stubby.settings.resolution_type must be set to "GETDNS_RESOLUTION_STUB".
101 Is services.stubby.settings unset?
102 '';
103 }
104 ];
105
106 services.stubby.settings.appdata_dir = "/var/cache/stubby";
107
108 systemd.services.stubby = {
109 description = "Stubby local DNS resolver";
110 after = [ "network.target" ];
111 before = [ "nss-lookup.target" ];
112 wantedBy = [ "multi-user.target" ];
113
114 serviceConfig = {
115 Type = "notify";
116 AmbientCapabilities = "CAP_NET_BIND_SERVICE";
117 CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
118 ExecStart = "${pkgs.stubby}/bin/stubby -C ${confFile} ${
119 optionalString (cfg.logLevel != null) "-v ${toString cfg.logLevel}"
120 }";
121 DynamicUser = true;
122 CacheDirectory = "stubby";
123 };
124 };
125 };
126}