1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9
10 cfg = config.services.dnscrypt-proxy;
11
12in
13
14{
15 imports = [
16 (lib.mkRenamedOptionModule [ "services" "dnscrypt-proxy2" ] [ "services" "dnscrypt-proxy" ])
17 ];
18
19 options.services.dnscrypt-proxy = {
20 enable = lib.mkEnableOption "dnscrypt-proxy";
21
22 package = lib.mkPackageOption pkgs "dnscrypt-proxy" { };
23
24 settings = lib.mkOption {
25 description = ''
26 Attrset that is converted and passed as TOML config file.
27 For available params, see: <https://github.com/DNSCrypt/dnscrypt-proxy/blob/${pkgs.dnscrypt-proxy.version}/dnscrypt-proxy/example-dnscrypt-proxy.toml>
28 '';
29 example = lib.literalExpression ''
30 {
31 sources.public-resolvers = {
32 urls = [ "https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md" ];
33 cache_file = "public-resolvers.md";
34 minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
35 refresh_delay = 72;
36 };
37 }
38 '';
39 type = lib.types.attrs;
40 default = { };
41 };
42
43 upstreamDefaults = lib.mkOption {
44 description = ''
45 Whether to base the config declared in {option}`services.dnscrypt-proxy.settings` on the upstream example config (<https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml>)
46
47 Disable this if you want to declare your dnscrypt config from scratch.
48 '';
49 type = lib.types.bool;
50 default = true;
51 };
52
53 configFile = lib.mkOption {
54 description = ''
55 Path to TOML config file. See: <https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml>
56 If this option is set, it will override any configuration done in options.services.dnscrypt-proxy.settings.
57 '';
58 example = "/etc/dnscrypt-proxy/dnscrypt-proxy.toml";
59 type = lib.types.path;
60 default =
61 pkgs.runCommand "dnscrypt-proxy.toml"
62 {
63 json = builtins.toJSON cfg.settings;
64 passAsFile = [ "json" ];
65 }
66 ''
67 ${
68 if cfg.upstreamDefaults then
69 ''
70 ${pkgs.buildPackages.remarshal}/bin/toml2json ${pkgs.dnscrypt-proxy.src}/dnscrypt-proxy/example-dnscrypt-proxy.toml > example.json
71 ${pkgs.buildPackages.jq}/bin/jq --slurp add example.json $jsonPath > config.json # merges the two
72 ''
73 else
74 ''
75 cp $jsonPath config.json
76 ''
77 }
78 ${pkgs.buildPackages.remarshal}/bin/json2toml < config.json > $out
79 '';
80 defaultText = lib.literalMD "TOML file generated from {option}`services.dnscrypt-proxy.settings`";
81 };
82 };
83
84 config = lib.mkIf cfg.enable {
85
86 networking.nameservers = lib.mkDefault [ "127.0.0.1" ];
87
88 systemd.services.dnscrypt-proxy = {
89 description = "DNSCrypt-proxy client";
90 wants = [
91 "network-online.target"
92 "nss-lookup.target"
93 ];
94 before = [
95 "nss-lookup.target"
96 ];
97 wantedBy = [
98 "multi-user.target"
99 ];
100 aliases = [ "dnscrypt-proxy2.service" ];
101 serviceConfig = {
102 AmbientCapabilities = "CAP_NET_BIND_SERVICE";
103 CacheDirectory = "dnscrypt-proxy";
104 DynamicUser = true;
105 ExecStart = "${lib.getExe cfg.package} -config ${cfg.configFile}";
106 LockPersonality = true;
107 LogsDirectory = "dnscrypt-proxy";
108 MemoryDenyWriteExecute = true;
109 NoNewPrivileges = true;
110 NonBlocking = true;
111 PrivateDevices = true;
112 ProtectClock = true;
113 ProtectControlGroups = true;
114 ProtectHome = true;
115 ProtectHostname = true;
116 ProtectKernelLogs = true;
117 ProtectKernelModules = true;
118 ProtectKernelTunables = true;
119 ProtectSystem = "strict";
120 Restart = "always";
121 RestrictAddressFamilies = [
122 "AF_INET"
123 "AF_INET6"
124 ];
125 RestrictNamespaces = true;
126 RestrictRealtime = true;
127 RuntimeDirectory = "dnscrypt-proxy";
128 StateDirectory = "dnscrypt-proxy";
129 SystemCallArchitectures = "native";
130 SystemCallFilter = [
131 "@system-service"
132 "@chown"
133 "~@aio"
134 "~@keyring"
135 "~@memlock"
136 "~@setuid"
137 "~@timer"
138 ];
139 };
140 };
141 };
142
143 # uses attributes of the linked package
144 meta.buildDocsInSandbox = false;
145}