at 25.11-pre 5.0 kB view raw
1{ 2 lib, 3 config, 4 pkgs, 5 ... 6}: 7 8let 9 cfg = config.services.acme-dns; 10 format = pkgs.formats.toml { }; 11 inherit (lib) 12 literalExpression 13 mkEnableOption 14 mkOption 15 mkPackageOption 16 types 17 ; 18 domain = "acme-dns.example.com"; 19in 20{ 21 options.services.acme-dns = { 22 enable = mkEnableOption "acme-dns"; 23 24 package = mkPackageOption pkgs "acme-dns" { }; 25 26 settings = mkOption { 27 description = '' 28 Free-form settings written directly to the `acme-dns.cfg` file. 29 Refer to <https://github.com/joohoi/acme-dns/blob/master/README.md#configuration> for supported values. 30 ''; 31 32 default = { }; 33 34 type = types.submodule { 35 freeformType = format.type; 36 options = { 37 general = { 38 listen = mkOption { 39 type = types.str; 40 description = "IP+port combination to bind and serve the DNS server on."; 41 default = "[::]:53"; 42 example = "127.0.0.1:53"; 43 }; 44 45 protocol = mkOption { 46 type = types.enum [ 47 "both" 48 "both4" 49 "both6" 50 "udp" 51 "udp4" 52 "udp6" 53 "tcp" 54 "tcp4" 55 "tcp6" 56 ]; 57 description = "Protocols to serve DNS responses on."; 58 default = "both"; 59 }; 60 61 domain = mkOption { 62 type = types.str; 63 description = "Domain name to serve the requests off of."; 64 example = domain; 65 }; 66 67 nsname = mkOption { 68 type = types.str; 69 description = "Zone name server."; 70 example = domain; 71 }; 72 73 nsadmin = mkOption { 74 type = types.str; 75 description = "Zone admin email address for `SOA`."; 76 example = "admin.example.com"; 77 }; 78 79 records = mkOption { 80 type = types.listOf types.str; 81 description = "Predefined DNS records served in addition to the `_acme-challenge` TXT records."; 82 example = literalExpression '' 83 [ 84 # replace with your acme-dns server's public IPv4 85 "${domain}. A 198.51.100.1" 86 # replace with your acme-dns server's public IPv6 87 "${domain}. AAAA 2001:db8::1" 88 # ${domain} should resolve any *.${domain} records 89 "${domain}. NS ${domain}." 90 ] 91 ''; 92 }; 93 }; 94 95 database = { 96 engine = mkOption { 97 type = types.enum [ 98 "sqlite3" 99 "postgres" 100 ]; 101 description = "Database engine to use."; 102 default = "sqlite3"; 103 }; 104 connection = mkOption { 105 type = types.str; 106 description = "Database connection string."; 107 example = "postgres://user:password@localhost/acmedns"; 108 default = "/var/lib/acme-dns/acme-dns.db"; 109 }; 110 }; 111 112 api = { 113 ip = mkOption { 114 type = types.str; 115 description = "IP to bind the HTTP API on."; 116 default = "[::]"; 117 example = "127.0.0.1"; 118 }; 119 120 port = mkOption { 121 type = types.port; 122 description = "Listen port for the HTTP API."; 123 default = 8080; 124 # acme-dns expects this value to be a string 125 apply = toString; 126 }; 127 128 disable_registration = mkOption { 129 type = types.bool; 130 description = "Whether to disable the HTTP registration endpoint."; 131 default = false; 132 example = true; 133 }; 134 135 tls = mkOption { 136 type = types.enum [ 137 "letsencrypt" 138 "letsencryptstaging" 139 "cert" 140 "none" 141 ]; 142 description = "TLS backend to use."; 143 default = "none"; 144 }; 145 }; 146 147 logconfig = { 148 loglevel = mkOption { 149 type = types.enum [ 150 "error" 151 "warning" 152 "info" 153 "debug" 154 ]; 155 description = "Level to log on."; 156 default = "info"; 157 }; 158 }; 159 }; 160 }; 161 }; 162 }; 163 164 config = lib.mkIf cfg.enable { 165 systemd.packages = [ cfg.package ]; 166 systemd.services.acme-dns = { 167 wantedBy = [ "multi-user.target" ]; 168 serviceConfig = { 169 ExecStart = [ 170 "" 171 "${lib.getExe cfg.package} -c ${format.generate "acme-dns.toml" cfg.settings}" 172 ]; 173 StateDirectory = "acme-dns"; 174 WorkingDirectory = "%S/acme-dns"; 175 DynamicUser = true; 176 }; 177 }; 178 }; 179}