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