Merge pull request #234207 from emilylange/acme-dns
acme-dns: init at 1.0; nixos/acme-dns: init; nixos/acme-dns: init
This commit is contained in:
commit
7e820610e3
7 changed files with 244 additions and 0 deletions
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
- Create the first release note entry in this section!
|
- Create the first release note entry in this section!
|
||||||
|
|
||||||
|
- [acme-dns](https://github.com/joohoi/acme-dns), a limited DNS server to handle ACME DNS challenges easily and securely. Available as [services.acme-dns](#opt-services.acme-dns.enable).
|
||||||
|
|
||||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||||
|
|
||||||
- [river](https://github.com/riverwm/river), A dynamic tiling wayland compositor. Available as [programs.river](#opt-programs.river.enable).
|
- [river](https://github.com/riverwm/river), A dynamic tiling wayland compositor. Available as [programs.river](#opt-programs.river.enable).
|
||||||
|
|
|
@ -808,6 +808,7 @@
|
||||||
./services/network-filesystems/xtreemfs.nix
|
./services/network-filesystems/xtreemfs.nix
|
||||||
./services/network-filesystems/yandex-disk.nix
|
./services/network-filesystems/yandex-disk.nix
|
||||||
./services/networking/3proxy.nix
|
./services/networking/3proxy.nix
|
||||||
|
./services/networking/acme-dns.nix
|
||||||
./services/networking/adguardhome.nix
|
./services/networking/adguardhome.nix
|
||||||
./services/networking/alice-lg.nix
|
./services/networking/alice-lg.nix
|
||||||
./services/networking/amuled.nix
|
./services/networking/amuled.nix
|
||||||
|
|
154
nixos/modules/services/networking/acme-dns.nix
Normal file
154
nixos/modules/services/networking/acme-dns.nix
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
{ lib
|
||||||
|
, config
|
||||||
|
, pkgs
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.acme-dns;
|
||||||
|
format = pkgs.formats.toml { };
|
||||||
|
inherit (lib)
|
||||||
|
literalExpression
|
||||||
|
mdDoc
|
||||||
|
mkEnableOption
|
||||||
|
mkOption
|
||||||
|
mkPackageOptionMD
|
||||||
|
types
|
||||||
|
;
|
||||||
|
domain = "acme-dns.example.com";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.acme-dns = {
|
||||||
|
enable = mkEnableOption (mdDoc "acme-dns");
|
||||||
|
|
||||||
|
package = mkPackageOptionMD pkgs "acme-dns" { };
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
description = mdDoc ''
|
||||||
|
Free-form settings written directly to the `acme-dns.cfg` file.
|
||||||
|
Refer to <https://github.com/joohoi/acme-dns/blob/master/README.md#configuration> for supported values.
|
||||||
|
'';
|
||||||
|
|
||||||
|
default = { };
|
||||||
|
|
||||||
|
type = types.submodule {
|
||||||
|
freeformType = format.type;
|
||||||
|
options = {
|
||||||
|
general = {
|
||||||
|
listen = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = mdDoc "IP+port combination to bind and serve the DNS server on.";
|
||||||
|
default = "[::]:53";
|
||||||
|
example = "127.0.0.1:53";
|
||||||
|
};
|
||||||
|
|
||||||
|
protocol = mkOption {
|
||||||
|
type = types.enum [ "both" "both4" "both6" "udp" "udp4" "udp6" "tcp" "tcp4" "tcp6" ];
|
||||||
|
description = mdDoc "Protocols to serve DNS responses on.";
|
||||||
|
default = "both";
|
||||||
|
};
|
||||||
|
|
||||||
|
domain = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = mdDoc "Domain name to serve the requests off of.";
|
||||||
|
example = domain;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsname = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = mdDoc "Zone name server.";
|
||||||
|
example = domain;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsadmin = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = mdDoc "Zone admin email address for `SOA`.";
|
||||||
|
example = "admin.example.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
records = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
description = mdDoc "Predefined DNS records served in addition to the `_acme-challenge` TXT records.";
|
||||||
|
example = literalExpression ''
|
||||||
|
[
|
||||||
|
# replace with your acme-dns server's public IPv4
|
||||||
|
"${domain}. A 198.51.100.1"
|
||||||
|
# replace with your acme-dns server's public IPv6
|
||||||
|
"${domain}. AAAA 2001:db8::1"
|
||||||
|
# ${domain} should resolve any *.${domain} records
|
||||||
|
"${domain}. NS ${domain}."
|
||||||
|
]
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
database = {
|
||||||
|
engine = mkOption {
|
||||||
|
type = types.enum [ "sqlite3" "postgres" ];
|
||||||
|
description = mdDoc "Database engine to use.";
|
||||||
|
default = "sqlite3";
|
||||||
|
};
|
||||||
|
connection = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = mdDoc "Database connection string.";
|
||||||
|
example = "postgres://user:password@localhost/acmedns";
|
||||||
|
default = "/var/lib/acme-dns/acme-dns.db";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
api = {
|
||||||
|
ip = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = mdDoc "IP to bind the HTTP API on.";
|
||||||
|
default = "[::]";
|
||||||
|
example = "127.0.0.1";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
description = mdDoc "Listen port for the HTTP API.";
|
||||||
|
default = 8080;
|
||||||
|
# acme-dns expects this value to be a string
|
||||||
|
apply = toString;
|
||||||
|
};
|
||||||
|
|
||||||
|
disable_registration = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
description = mdDoc "Whether to disable the HTTP registration endpoint.";
|
||||||
|
default = false;
|
||||||
|
example = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
tls = mkOption {
|
||||||
|
type = types.enum [ "letsencrypt" "letsencryptstaging" "cert" "none" ];
|
||||||
|
description = mdDoc "TLS backend to use.";
|
||||||
|
default = "none";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
logconfig = {
|
||||||
|
loglevel = mkOption {
|
||||||
|
type = types.enum [ "error" "warning" "info" "debug" ];
|
||||||
|
description = mdDoc "Level to log on.";
|
||||||
|
default = "info";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
systemd.packages = [ cfg.package ];
|
||||||
|
systemd.services.acme-dns = {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = [ "" "${lib.getExe cfg.package} -c ${format.generate "acme-dns.toml" cfg.settings}" ];
|
||||||
|
StateDirectory = "acme-dns";
|
||||||
|
WorkingDirectory = "%S/acme-dns";
|
||||||
|
DynamicUser = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
50
nixos/tests/acme-dns.nix
Normal file
50
nixos/tests/acme-dns.nix
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import ./make-test-python.nix ({ ... }: {
|
||||||
|
name = "acme-dns";
|
||||||
|
|
||||||
|
nodes.machine = { pkgs, ... }: {
|
||||||
|
services.acme-dns = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
general = rec {
|
||||||
|
domain = "acme-dns.home.arpa";
|
||||||
|
nsname = domain;
|
||||||
|
nsadmin = "admin.home.arpa";
|
||||||
|
records = [
|
||||||
|
"${domain}. A 127.0.0.1"
|
||||||
|
"${domain}. AAAA ::1"
|
||||||
|
"${domain}. NS ${domain}."
|
||||||
|
];
|
||||||
|
};
|
||||||
|
logconfig.loglevel = "debug";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
environment.systemPackages = with pkgs; [ curl bind ];
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = ''
|
||||||
|
import json
|
||||||
|
|
||||||
|
machine.wait_for_unit("acme-dns.service")
|
||||||
|
machine.wait_for_open_port(53) # dns
|
||||||
|
machine.wait_for_open_port(8080) # http api
|
||||||
|
|
||||||
|
result = machine.succeed("curl --fail -X POST http://localhost:8080/register")
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
registration = json.loads(result)
|
||||||
|
|
||||||
|
machine.succeed(f'dig -t TXT @localhost {registration["fulldomain"]} | grep "SOA" | grep "admin.home.arpa"')
|
||||||
|
|
||||||
|
# acme-dns exspects a TXT value string length of exactly 43 chars
|
||||||
|
txt = "___dummy_validation_token_for_txt_record___"
|
||||||
|
|
||||||
|
machine.succeed(
|
||||||
|
"curl --fail -X POST http://localhost:8080/update "
|
||||||
|
+ f' -H "X-Api-User: {registration["username"]}"'
|
||||||
|
+ f' -H "X-Api-Key: {registration["password"]}"'
|
||||||
|
+ f' -d \'{{"subdomain":"{registration["subdomain"]}", "txt":"{txt}"}}\'''
|
||||||
|
)
|
||||||
|
|
||||||
|
assert txt in machine.succeed(f'dig -t TXT +short @localhost {registration["fulldomain"]}')
|
||||||
|
'';
|
||||||
|
})
|
|
@ -95,6 +95,7 @@ in {
|
||||||
_3proxy = runTest ./3proxy.nix;
|
_3proxy = runTest ./3proxy.nix;
|
||||||
aaaaxy = runTest ./aaaaxy.nix;
|
aaaaxy = runTest ./aaaaxy.nix;
|
||||||
acme = runTest ./acme.nix;
|
acme = runTest ./acme.nix;
|
||||||
|
acme-dns = handleTest ./acme-dns.nix {};
|
||||||
adguardhome = runTest ./adguardhome.nix;
|
adguardhome = runTest ./adguardhome.nix;
|
||||||
aesmd = runTestOn ["x86_64-linux"] ./aesmd.nix;
|
aesmd = runTestOn ["x86_64-linux"] ./aesmd.nix;
|
||||||
agate = runTest ./web-servers/agate.nix;
|
agate = runTest ./web-servers/agate.nix;
|
||||||
|
|
34
pkgs/servers/dns/acme-dns/default.nix
Normal file
34
pkgs/servers/dns/acme-dns/default.nix
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{ lib
|
||||||
|
, buildGoModule
|
||||||
|
, fetchFromGitHub
|
||||||
|
, nixosTests
|
||||||
|
}:
|
||||||
|
|
||||||
|
buildGoModule rec {
|
||||||
|
pname = "acme-dns";
|
||||||
|
version = "1.0";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "joohoi";
|
||||||
|
repo = pname;
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-qQwvhouqzkChWeu65epgoeMNqZyAD18T+xqEMgdMbhA=";
|
||||||
|
};
|
||||||
|
|
||||||
|
vendorHash = "sha256-q/P+cH2OihvPxPj2XWeLsTBHzQQABp0zjnof+Ys/qKo=";
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
install -D -m0444 -t $out/lib/systemd/system ./acme-dns.service
|
||||||
|
substituteInPlace $out/lib/systemd/system/acme-dns.service --replace "/usr/local/bin/acme-dns" "$out/bin/acme-dns"
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru.tests = { inherit (nixosTests) acme-dns; };
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Limited DNS server to handle ACME DNS challenges easily and securely";
|
||||||
|
homepage = "https://github.com/joohoi/acme-dns";
|
||||||
|
changelog = "https://github.com/joohoi/acme-dns/releases/tag/${src.rev}";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
maintainers = with lib.maintainers; [ emilylange ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -1303,6 +1303,8 @@ with pkgs;
|
||||||
|
|
||||||
accuraterip-checksum = callPackage ../tools/audio/accuraterip-checksum { };
|
accuraterip-checksum = callPackage ../tools/audio/accuraterip-checksum { };
|
||||||
|
|
||||||
|
acme-dns = callPackage ../servers/dns/acme-dns/default.nix { };
|
||||||
|
|
||||||
acme-sh = callPackage ../tools/admin/acme-sh { };
|
acme-sh = callPackage ../tools/admin/acme-sh { };
|
||||||
|
|
||||||
acousticbrainz-client = callPackage ../tools/audio/acousticbrainz-client { };
|
acousticbrainz-client = callPackage ../tools/audio/acousticbrainz-client { };
|
||||||
|
|
Loading…
Reference in a new issue