nixos/ncdns: init module
This commit is contained in:
parent
5ec0bd7649
commit
e23c57c347
2 changed files with 279 additions and 0 deletions
|
@ -606,6 +606,7 @@
|
||||||
./services/networking/dnscrypt-wrapper.nix
|
./services/networking/dnscrypt-wrapper.nix
|
||||||
./services/networking/dnsdist.nix
|
./services/networking/dnsdist.nix
|
||||||
./services/networking/dnsmasq.nix
|
./services/networking/dnsmasq.nix
|
||||||
|
./services/networking/ncdns.nix
|
||||||
./services/networking/ejabberd.nix
|
./services/networking/ejabberd.nix
|
||||||
./services/networking/epmd.nix
|
./services/networking/epmd.nix
|
||||||
./services/networking/ergo.nix
|
./services/networking/ergo.nix
|
||||||
|
|
278
nixos/modules/services/networking/ncdns.nix
Normal file
278
nixos/modules/services/networking/ncdns.nix
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfgs = config.services;
|
||||||
|
cfg = cfgs.ncdns;
|
||||||
|
|
||||||
|
dataDir = "/var/lib/ncdns";
|
||||||
|
username = "ncdns";
|
||||||
|
|
||||||
|
valueType = with types; oneOf [ int str bool path ]
|
||||||
|
// { description = "setting type (integer, string, bool or path)"; };
|
||||||
|
|
||||||
|
configType = with types; attrsOf (nullOr (either valueType configType))
|
||||||
|
// { description = ''
|
||||||
|
ncdns.conf configuration type. The format consists of an
|
||||||
|
attribute set of settings. Each setting can be either `null`,
|
||||||
|
a value or an attribute set. The allowed values are integers,
|
||||||
|
strings, booleans or paths.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
configFile = pkgs.runCommand "ncdns.conf"
|
||||||
|
{ json = builtins.toJSON cfg.settings;
|
||||||
|
passAsFile = [ "json" ];
|
||||||
|
}
|
||||||
|
"${pkgs.remarshal}/bin/json2toml < $jsonPath > $out";
|
||||||
|
|
||||||
|
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 = all id (flip mapAttrsToList cfg.dnssec.keys
|
||||||
|
(n: v: v == getAttr n defaultFiles));
|
||||||
|
|
||||||
|
mkDefaultAttrs = mapAttrs (n: v: mkDefault v);
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.ncdns = {
|
||||||
|
|
||||||
|
enable = mkEnableOption ''
|
||||||
|
ncdns, a Go daemon to bridge Namecoin to DNS.
|
||||||
|
To resolve .bit domains set <literal>services.namecoind.enable = true;</literal>
|
||||||
|
and an RPC username/password
|
||||||
|
'';
|
||||||
|
|
||||||
|
address = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "127.0.0.1";
|
||||||
|
description = ''
|
||||||
|
The IP address the ncdns resolver will bind to. Leave this unchanged
|
||||||
|
if you do not wish to directly expose the resolver.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 5333;
|
||||||
|
description = ''
|
||||||
|
The port the ncdns resolver will bind to.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
identity.hostname = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = config.networking.hostName;
|
||||||
|
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:
|
||||||
|
<programlisting>
|
||||||
|
bit. IN NS ns1.example.com.
|
||||||
|
</programlisting>
|
||||||
|
If unset ncdns will generate an internal psuedo-hostname under the
|
||||||
|
zone, which will resolve to the value of
|
||||||
|
<option>services.ncdns.identity.address</option>.
|
||||||
|
If you are only using ncdns locally you can ignore this.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
identity.hostmaster = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
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 = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "127.127.127.127";
|
||||||
|
description = ''
|
||||||
|
The IP address the hostname specified in
|
||||||
|
<option>services.ncdns.identity.hostname</option> should resolve to.
|
||||||
|
If you are only using ncdns locally you can ignore this.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dnssec.enable = mkEnableOption ''
|
||||||
|
DNSSEC support in ncdns. This will generate KSK and ZSK keypairs
|
||||||
|
(unless provided via the options
|
||||||
|
<option>services.ncdns.dnssec.publicKey</option>,
|
||||||
|
<option>services.ncdns.dnssec.privateKey</option> etc.) and add a trust
|
||||||
|
anchor to recursive resolvers
|
||||||
|
'';
|
||||||
|
|
||||||
|
dnssec.keys.public = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = defaultFiles.public;
|
||||||
|
description = ''
|
||||||
|
Path to the file containing the KSK public key.
|
||||||
|
The key can be generated using the <literal>dnssec-keygen</literal>
|
||||||
|
command, provided by the package <package>bind</package> as follows:
|
||||||
|
<programlisting>
|
||||||
|
$ dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
|
||||||
|
</programlisting>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dnssec.keys.private = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = defaultFiles.private;
|
||||||
|
description = ''
|
||||||
|
Path to the file containing the KSK private key.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dnssec.keys.zonePublic = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = defaultFiles.zonePublic;
|
||||||
|
description = ''
|
||||||
|
Path to the file containing the ZSK public key.
|
||||||
|
The key can be generated using the <literal>dnssec-keygen</literal>
|
||||||
|
command, provided by the package <package>bind</package> as follows:
|
||||||
|
<programlisting>
|
||||||
|
$ dnssec-keygen -a RSASHA256 -3 -b 2048 bit
|
||||||
|
</programlisting>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dnssec.keys.zonePrivate = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = defaultFiles.zonePrivate;
|
||||||
|
description = ''
|
||||||
|
Path to the file containing the ZSK private key.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
type = configType;
|
||||||
|
default = { };
|
||||||
|
example = literalExample ''
|
||||||
|
{ # 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.
|
||||||
|
See the example ncdns.conf file at <link xlink:href="
|
||||||
|
https://git.io/JfX7g"/> for the available options.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
services.pdns-recursor.resolveNamecoin = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Resolve <literal>.bit</literal> top-level domains using ncdns and namecoin.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveNamecoin {
|
||||||
|
forwardZonesRecurse.bit = "127.0.0.1:${toString cfg.port}";
|
||||||
|
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 = mkIf cfgs.pdns-recursor.resolveNamecoin {
|
||||||
|
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}";
|
||||||
|
}
|
||||||
|
// optionalAttrs cfg.dnssec.enable
|
||||||
|
{ # 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 =
|
||||||
|
{ description = "ncdns daemon user"; };
|
||||||
|
|
||||||
|
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=${configFile}";
|
||||||
|
};
|
||||||
|
|
||||||
|
preStart = optionalString (cfg.dnssec.enable && needsKeygen) ''
|
||||||
|
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 ];
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue