{ config, pkgs, lib, ... }: with lib; let cfg = config.services.acme-dns; tomlFormat = pkgs.formats.toml {}; configFile = tomlFormat.generate "acme-dns.cfg" cfg.settings; in { options.services.acme-dns = { enable = mkEnableOption "ACME DNS server"; package = mkOption { type = types.package; default = pkgs.rz.acme-dns; defaultText = "pkgs.rz.acme-dns"; }; stateDir = mkOption { type = types.str; default = "/var/lib/acme-dns"; }; domain = mkOption { type = types.str; }; nsname = mkOption { type = types.str; }; nsadmin = mkOption { type = types.str; }; records = mkOption { type = types.listOf types.str; }; api.port = mkOption { type = types.port; default = 8090; }; api.listen = mkOption { type = types.str; default = "127.0.0.1"; }; dns.port = mkOption { type = types.port; default = 53; }; dns.listen = mkOption { type = types.str; default = "127.0.0.1"; }; settings = mkOption { type = types.attrs; default = { general = { listen = "${cfg.dns.listen}:${toString cfg.dns.port}"; protocol = "both"; domain = cfg.domain; nsname = cfg.nsname; nsadmin = cfg.nsadmin; records = cfg.records; debug = false; }; database = { engine = "sqlite"; connection = "${cfg.stateDir}/acme-dns.db"; }; api = { ip = cfg.api.listen; disable_registration = false; port = cfg.api.port; tls = "none"; notification_email = config.security.acme.email; corsorigins = [ "*" ]; use_header = false; header_name = "X-Forwarded-For"; }; logconfig = { loglevel = "debug"; logtype = "stdout"; logformat = "text"; }; }; }; }; config = mkIf cfg.enable { systemd.services.acme-dns = { description = "ACME-DNS name server for ACME DNS challenges"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; startLimitBurst = 4; startLimitIntervalSec = 5 * 60; # 5 mins serviceConfig = { AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; DynamicUser = true; BindPaths = [ cfg.stateDir ]; ExecStart = "${cfg.package}/bin/acme-dns -d -c ${configFile}"; Restart = "always"; RestartSec = "4s"; }; }; }; }