nixpkgs/nixos/modules/services/networking/ncdns.nix

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

270 lines
7.8 KiB
Nix
Raw Normal View History

2020-06-06 02:55:17 +02:00
{
config,
lib,
pkgs,
...
}:
let
cfgs = config.services;
cfg = cfgs.ncdns;
dataDir = "/var/lib/ncdns";
format = pkgs.formats.toml { };
2020-06-06 02:55:17 +02:00
defaultFiles = {
public = "${dataDir}/bit.key";
private = "${dataDir}/bit.private";
zonePublic = "${dataDir}/bit-zone.key";
zonePrivate = "${dataDir}/bit-zone.private";
};
# if all keys are the default value
needsKeygen = lib.all lib.id (
lib.flip lib.mapAttrsToList cfg.dnssec.keys (n: v: v == lib.getAttr n defaultFiles)
);
2020-06-06 02:55:17 +02:00
mkDefaultAttrs = lib.mapAttrs (_n: v: lib.mkDefault v);
2020-06-06 02:55:17 +02:00
in
{
###### interface
options = {
services.ncdns = {
enable = lib.mkEnableOption ''
2020-06-06 02:55:17 +02:00
ncdns, a Go daemon to bridge Namecoin to DNS.
To resolve .bit domains set `services.namecoind.enable = true;`
and an RPC username/password
'';
address = lib.mkOption {
type = lib.types.str;
2022-04-13 18:16:38 +02:00
default = "[::1]";
2020-06-06 02:55:17 +02:00
description = ''
The IP address the ncdns resolver will bind to. Leave this unchanged
if you do not wish to directly expose the resolver.
'';
};
port = lib.mkOption {
type = lib.types.port;
2020-06-06 02:55:17 +02:00
default = 5333;
description = ''
The port the ncdns resolver will bind to.
'';
};
identity.hostname = lib.mkOption {
type = lib.types.str;
2020-06-06 02:55:17 +02:00
default = config.networking.hostName;
defaultText = lib.literalExpression "config.networking.hostName";
2020-06-06 02:55:17 +02:00
example = "example.com";
description = ''
The hostname of this ncdns instance, which defaults to the machine
hostname. If specified, ncdns lists the hostname as an NS record at
the zone apex:
```
2020-06-06 02:55:17 +02:00
bit. IN NS ns1.example.com.
```
2022-12-17 19:31:14 -05:00
If unset ncdns will generate an internal pseudo-hostname under the
2020-06-06 02:55:17 +02:00
zone, which will resolve to the value of
{option}`services.ncdns.identity.address`.
If you are only using ncdns locally you can ignore this.
'';
};
identity.hostmaster = lib.mkOption {
type = lib.types.str;
2020-06-06 02:55:17 +02:00
default = "";
example = "root@example.com";
description = ''
An email address for the SOA record at the bit zone.
If you are only using ncdns locally you can ignore this.
'';
};
identity.address = lib.mkOption {
type = lib.types.str;
2020-06-06 02:55:17 +02:00
default = "127.127.127.127";
description = ''
The IP address the hostname specified in
{option}`services.ncdns.identity.hostname` should resolve to.
If you are only using ncdns locally you can ignore this.
'';
};
dnssec.enable = lib.mkEnableOption ''
2020-06-06 02:55:17 +02:00
DNSSEC support in ncdns. This will generate KSK and ZSK keypairs
(unless provided via the options
{option}`services.ncdns.dnssec.publicKey`,
{option}`services.ncdns.dnssec.privateKey` etc.) and add a trust
anchor to recursive resolvers
'';
dnssec.keys.public = lib.mkOption {
type = lib.types.path;
2020-06-06 02:55:17 +02:00
default = defaultFiles.public;
description = ''
Path to the file containing the KSK public key.
The key can be generated using the `dnssec-keygen`
command, provided by the package `bind` as follows:
```
2020-06-06 02:55:17 +02:00
$ dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
```
2020-06-06 02:55:17 +02:00
'';
};
dnssec.keys.private = lib.mkOption {
type = lib.types.path;
2020-06-06 02:55:17 +02:00
default = defaultFiles.private;
description = ''
Path to the file containing the KSK private key.
'';
};
dnssec.keys.zonePublic = lib.mkOption {
type = lib.types.path;
2020-06-06 02:55:17 +02:00
default = defaultFiles.zonePublic;
description = ''
Path to the file containing the ZSK public key.
The key can be generated using the `dnssec-keygen`
command, provided by the package `bind` as follows:
```
2020-06-06 02:55:17 +02:00
$ dnssec-keygen -a RSASHA256 -3 -b 2048 bit
```
2020-06-06 02:55:17 +02:00
'';
};
dnssec.keys.zonePrivate = lib.mkOption {
type = lib.types.path;
2020-06-06 02:55:17 +02:00
default = defaultFiles.zonePrivate;
description = ''
Path to the file containing the ZSK private key.
'';
};
settings = lib.mkOption {
type = format.type;
2020-06-06 02:55:17 +02:00
default = { };
example = lib.literalExpression ''
2020-06-06 02:55:17 +02:00
{ # enable webserver
ncdns.httplistenaddr = ":8202";
# synchronize TLS certs
certstore.nss = true;
# note: all paths are relative to the config file
certstore.nsscertdir = "../../var/lib/ncdns";
certstore.nssdbdir = "../../home/alice/.pki/nssdb";
}
'';
description = ''
ncdns settings. Use this option to configure ncds
settings not exposed in a NixOS option or to bypass one.
2022-07-31 17:13:03 +02:00
See the example ncdns.conf file at <https://github.com/namecoin/ncdns/blob/master/_doc/ncdns.conf.example>
for the available options.
2020-06-06 02:55:17 +02:00
'';
};
};
services.pdns-recursor.resolveNamecoin = lib.mkOption {
type = lib.types.bool;
2020-06-06 02:55:17 +02:00
default = false;
description = ''
Resolve `.bit` top-level domains using ncdns and namecoin.
'';
};
};
###### implementation
config = lib.mkIf cfg.enable {
2020-06-06 02:55:17 +02:00
services.pdns-recursor = lib.mkIf cfgs.pdns-recursor.resolveNamecoin {
2022-04-13 18:16:38 +02:00
forwardZonesRecurse.bit = "${cfg.address}:${toString cfg.port}";
2020-06-06 02:55:17 +02:00
luaConfig =
if cfg.dnssec.enable then
''readTrustAnchorsFromFile("${cfg.dnssec.keys.public}")''
else
''addNTA("bit", "namecoin DNSSEC disabled")'';
};
# Avoid pdns-recursor not finding the DNSSEC keys
systemd.services.pdns-recursor = lib.mkIf cfgs.pdns-recursor.resolveNamecoin {
2020-06-06 02:55:17 +02:00
after = [ "ncdns.service" ];
wants = [ "ncdns.service" ];
};
services.ncdns.settings = mkDefaultAttrs {
ncdns =
{
# Namecoin RPC
namecoinrpcaddress = "${cfgs.namecoind.rpc.address}:${toString cfgs.namecoind.rpc.port}";
namecoinrpcusername = cfgs.namecoind.rpc.user;
namecoinrpcpassword = cfgs.namecoind.rpc.password;
# Identity
selfname = cfg.identity.hostname;
hostmaster = cfg.identity.hostmaster;
selfip = cfg.identity.address;
# Other
bind = "${cfg.address}:${toString cfg.port}";
}
// lib.optionalAttrs cfg.dnssec.enable {
2020-06-06 02:55:17 +02:00
# DNSSEC
publickey = "../.." + cfg.dnssec.keys.public;
privatekey = "../.." + cfg.dnssec.keys.private;
zonepublickey = "../.." + cfg.dnssec.keys.zonePublic;
zoneprivatekey = "../.." + cfg.dnssec.keys.zonePrivate;
};
# Daemon
service.daemon = true;
xlog.journal = true;
};
users.users.ncdns = {
isSystemUser = true;
group = "ncdns";
description = "ncdns daemon user";
};
users.groups.ncdns = { };
2020-06-06 02:55:17 +02:00
systemd.services.ncdns = {
description = "ncdns daemon";
after = [ "namecoind.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "ncdns";
StateDirectory = "ncdns";
Restart = "on-failure";
ExecStart = "${pkgs.ncdns}/bin/ncdns -conf=${format.generate "ncdns.conf" cfg.settings}";
2020-06-06 02:55:17 +02:00
};
preStart = lib.optionalString (cfg.dnssec.enable && needsKeygen) ''
2020-06-06 02:55:17 +02:00
cd ${dataDir}
if [ ! -e bit.key ]; then
${pkgs.bind}/bin/dnssec-keygen -a RSASHA256 -3 -b 2048 bit
mv Kbit.*.key bit-zone.key
mv Kbit.*.private bit-zone.private
${pkgs.bind}/bin/dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
mv Kbit.*.key bit.key
mv Kbit.*.private bit.private
fi
'';
};
};
meta.maintainers = with lib.maintainers; [ rnhmjoj ];
}