nixos/nsd: Fix indentation/coding style.
For Nix, we indent using two spaces, but in this module somehow 4 spaces were snuck in. Other than that, remoteControl and ratelimit are just nested attribute sets, so we don't need to make another submodule type for no particular reason. Signed-off-by: aszlig <aszlig@redmoonstudios.org>
This commit is contained in:
parent
eac5176529
commit
6386df1645
@ -10,16 +10,16 @@ let
|
|||||||
pidFile = stateDir + "/var/nsd.pid";
|
pidFile = stateDir + "/var/nsd.pid";
|
||||||
|
|
||||||
zoneFiles = pkgs.stdenv.mkDerivation {
|
zoneFiles = pkgs.stdenv.mkDerivation {
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
name = "nsd-env";
|
name = "nsd-env";
|
||||||
buildCommand = concatStringsSep "\n"
|
buildCommand = concatStringsSep "\n"
|
||||||
[ "mkdir -p $out"
|
[ "mkdir -p $out"
|
||||||
(concatStrings (mapAttrsToList (zoneName: zoneOptions: ''
|
(concatStrings (mapAttrsToList (zoneName: zoneOptions: ''
|
||||||
cat > "$out/${zoneName}" <<_EOF_
|
cat > "$out/${zoneName}" <<_EOF_
|
||||||
${zoneOptions.data}
|
${zoneOptions.data}
|
||||||
_EOF_
|
_EOF_
|
||||||
'') zoneConfigs))
|
'') zoneConfigs))
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
configFile = pkgs.writeText "nsd.conf" ''
|
configFile = pkgs.writeText "nsd.conf" ''
|
||||||
@ -105,21 +105,20 @@ let
|
|||||||
|
|
||||||
|
|
||||||
zoneConfigFile = name: zone: ''
|
zoneConfigFile = name: zone: ''
|
||||||
zone:
|
zone:
|
||||||
name: "${name}"
|
name: "${name}"
|
||||||
zonefile: "${stateDir}/zones/${name}"
|
zonefile: "${stateDir}/zones/${name}"
|
||||||
${maybeString "outgoing-interface: " zone.outgoingInterface}
|
${maybeString "outgoing-interface: " zone.outgoingInterface}
|
||||||
${forEach " rrl-whitelist: " zone.rrlWhitelist}
|
${forEach " rrl-whitelist: " zone.rrlWhitelist}
|
||||||
|
|
||||||
${forEach " allow-notify: " zone.allowNotify}
|
${forEach " allow-notify: " zone.allowNotify}
|
||||||
${forEach " request-xfr: " zone.requestXFR}
|
${forEach " request-xfr: " zone.requestXFR}
|
||||||
allow-axfr-fallback: ${yesOrNo zone.allowAXFRFallback}
|
allow-axfr-fallback: ${yesOrNo zone.allowAXFRFallback}
|
||||||
|
|
||||||
${forEach " notify: " zone.notify}
|
${forEach " notify: " zone.notify}
|
||||||
notify-retry: ${toString zone.notifyRetry}
|
notify-retry: ${toString zone.notifyRetry}
|
||||||
${forEach " provide-xfr: " zone.provideXFR}
|
${forEach " provide-xfr: " zone.provideXFR}
|
||||||
|
'';
|
||||||
'';
|
|
||||||
|
|
||||||
zoneConfigs = zoneConfigs' {} "" { children = cfg.zones; };
|
zoneConfigs = zoneConfigs' {} "" { children = cfg.zones; };
|
||||||
|
|
||||||
@ -130,8 +129,8 @@ let
|
|||||||
|
|
||||||
# fork -> pattern
|
# fork -> pattern
|
||||||
else zipAttrsWith (name: head) (
|
else zipAttrsWith (name: head) (
|
||||||
mapAttrsToList (name: child: zoneConfigs' (parent // zone // { children = {}; }) name child)
|
mapAttrsToList (name: child: zoneConfigs' (parent // zone // { children = {}; }) name child)
|
||||||
zone.children
|
zone.children
|
||||||
);
|
);
|
||||||
|
|
||||||
# fighting infinite recursion
|
# fighting infinite recursion
|
||||||
@ -145,138 +144,135 @@ let
|
|||||||
|
|
||||||
childConfig = x: v: { options.children = { type = types.attrsOf x; visible = v; }; };
|
childConfig = x: v: { options.children = { type = types.attrsOf x; visible = v; }; };
|
||||||
|
|
||||||
zoneOptionsRaw = types.submodule (
|
zoneOptionsRaw = types.submodule {
|
||||||
{ options, ... }:
|
options = {
|
||||||
{ options = {
|
children = mkOption {
|
||||||
children = mkOption {
|
default = {};
|
||||||
default = {};
|
description = ''
|
||||||
description = ''
|
Children zones inherit all options of their parents. Attributes
|
||||||
Children zones inherit all options of their parents. Attributes
|
defined in a child will overwrite the ones of its parent. Only
|
||||||
defined in a child will overwrite the ones of its parent. Only
|
leaf zones will be actually served. This way it's possible to
|
||||||
leaf zones will be actually served. This way it's possible to
|
define maybe zones which share most attributes without
|
||||||
define maybe zones which share most attributes without
|
duplicating everything. This mechanism replaces nsd's patterns
|
||||||
duplicating everything. This mechanism replaces nsd's patterns
|
in a save and functional way.
|
||||||
in a save and functional way.
|
'';
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
allowNotify = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
example = [ "192.0.2.0/24 NOKEY" "10.0.0.1-10.0.0.5 my_tsig_key_name"
|
|
||||||
"10.0.3.4&255.255.0.0 BLOCKED"
|
|
||||||
];
|
|
||||||
description = ''
|
|
||||||
Listed primary servers are allowed to notify this secondary server.
|
|
||||||
<screen><![CDATA[
|
|
||||||
Format: <ip> <key-name | NOKEY | BLOCKED>
|
|
||||||
|
|
||||||
<ip> either a plain IPv4/IPv6 address or range. Valid patters for ranges:
|
|
||||||
* 10.0.0.0/24 # via subnet size
|
|
||||||
* 10.0.0.0&255.255.255.0 # via subnet mask
|
|
||||||
* 10.0.0.1-10.0.0.254 # via range
|
|
||||||
|
|
||||||
A optional port number could be added with a '@':
|
|
||||||
* 2001:1234::1@1234
|
|
||||||
|
|
||||||
<key-name | NOKEY | BLOCKED>
|
|
||||||
* <key-name> will use the specified TSIG key
|
|
||||||
* NOKEY no TSIG signature is required
|
|
||||||
* BLOCKED notifies from non-listed or blocked IPs will be ignored
|
|
||||||
* ]]></screen>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
requestXFR = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
example = [];
|
|
||||||
description = ''
|
|
||||||
Format: <code>[AXFR|UDP] <ip-address> <key-name | NOKEY></code>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
allowAXFRFallback = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
If NSD as secondary server should be allowed to AXFR if the primary
|
|
||||||
server does not allow IXFR.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
notify = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
example = [ "10.0.0.1@3721 my_key" "::5 NOKEY" ];
|
|
||||||
description = ''
|
|
||||||
This primary server will notify all given secondary servers about
|
|
||||||
zone changes.
|
|
||||||
<screen><![CDATA[
|
|
||||||
Format: <ip> <key-name | NOKEY>
|
|
||||||
|
|
||||||
<ip> a plain IPv4/IPv6 address with on optional port number (ip@port)
|
|
||||||
|
|
||||||
<key-name | NOKEY>
|
|
||||||
* <key-name> sign notifies with the specified key
|
|
||||||
* NOKEY don't sign notifies
|
|
||||||
]]></screen>
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
notifyRetry = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
default = 5;
|
|
||||||
description = ''
|
|
||||||
Specifies the number of retries for failed notifies. Set this along with notify.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
provideXFR = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
example = [ "192.0.2.0/24 NOKEY" "192.0.2.0/24 my_tsig_key_name" ];
|
|
||||||
description = ''
|
|
||||||
Allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED
|
|
||||||
address range 192.0.2.0/24, 1.2.3.4&255.255.0.0, 3.0.2.20-3.0.2.40
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
outgoingInterface = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
example = "2000::1@1234";
|
|
||||||
description = ''
|
|
||||||
This address will be used for zone-transfere requests if configured
|
|
||||||
as a secondary server or notifications in case of a primary server.
|
|
||||||
Supply either a plain IPv4 or IPv6 address with an optional port
|
|
||||||
number (ip@port).
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
rrlWhitelist = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
description = ''
|
|
||||||
Whitelists the given rrl-types.
|
|
||||||
The RRL classification types are: nxdomain, error, referral, any,
|
|
||||||
rrsig, wildcard, nodata, dnskey, positive, all
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
data = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "";
|
|
||||||
example = "";
|
|
||||||
description = ''
|
|
||||||
The actual zone data. This is the content of your zone file.
|
|
||||||
Use imports or pkgs.lib.readFile if you don't want this data in your config file.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
);
|
allowNotify = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "192.0.2.0/24 NOKEY" "10.0.0.1-10.0.0.5 my_tsig_key_name"
|
||||||
|
"10.0.3.4&255.255.0.0 BLOCKED"
|
||||||
|
];
|
||||||
|
description = ''
|
||||||
|
Listed primary servers are allowed to notify this secondary server.
|
||||||
|
<screen><![CDATA[
|
||||||
|
Format: <ip> <key-name | NOKEY | BLOCKED>
|
||||||
|
|
||||||
|
<ip> either a plain IPv4/IPv6 address or range. Valid patters for ranges:
|
||||||
|
* 10.0.0.0/24 # via subnet size
|
||||||
|
* 10.0.0.0&255.255.255.0 # via subnet mask
|
||||||
|
* 10.0.0.1-10.0.0.254 # via range
|
||||||
|
|
||||||
|
A optional port number could be added with a '@':
|
||||||
|
* 2001:1234::1@1234
|
||||||
|
|
||||||
|
<key-name | NOKEY | BLOCKED>
|
||||||
|
* <key-name> will use the specified TSIG key
|
||||||
|
* NOKEY no TSIG signature is required
|
||||||
|
* BLOCKED notifies from non-listed or blocked IPs will be ignored
|
||||||
|
* ]]></screen>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
requestXFR = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = [];
|
||||||
|
description = ''
|
||||||
|
Format: <code>[AXFR|UDP] <ip-address> <key-name | NOKEY></code>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
allowAXFRFallback = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
If NSD as secondary server should be allowed to AXFR if the primary
|
||||||
|
server does not allow IXFR.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
notify = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = [ "10.0.0.1@3721 my_key" "::5 NOKEY" ];
|
||||||
|
description = ''
|
||||||
|
This primary server will notify all given secondary servers about
|
||||||
|
zone changes.
|
||||||
|
<screen><![CDATA[
|
||||||
|
Format: <ip> <key-name | NOKEY>
|
||||||
|
|
||||||
|
<ip> a plain IPv4/IPv6 address with on optional port number (ip@port)
|
||||||
|
|
||||||
|
<key-name | NOKEY>
|
||||||
|
* <key-name> sign notifies with the specified key
|
||||||
|
* NOKEY don't sign notifies
|
||||||
|
]]></screen>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
notifyRetry = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 5;
|
||||||
|
description = ''
|
||||||
|
Specifies the number of retries for failed notifies. Set this along with notify.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
provideXFR = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = [ "192.0.2.0/24 NOKEY" "192.0.2.0/24 my_tsig_key_name" ];
|
||||||
|
description = ''
|
||||||
|
Allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED
|
||||||
|
address range 192.0.2.0/24, 1.2.3.4&255.255.0.0, 3.0.2.20-3.0.2.40
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
outgoingInterface = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
example = "2000::1@1234";
|
||||||
|
description = ''
|
||||||
|
This address will be used for zone-transfere requests if configured
|
||||||
|
as a secondary server or notifications in case of a primary server.
|
||||||
|
Supply either a plain IPv4 or IPv6 address with an optional port
|
||||||
|
number (ip@port).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
rrlWhitelist = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
Whitelists the given rrl-types.
|
||||||
|
The RRL classification types are: nxdomain, error, referral, any,
|
||||||
|
rrsig, wildcard, nodata, dnskey, positive, all
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
data = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "";
|
||||||
|
example = "";
|
||||||
|
description = ''
|
||||||
|
The actual zone data. This is the content of your zone file.
|
||||||
|
Use imports or pkgs.lib.readFile if you don't want this data in your config file.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@ -585,37 +581,33 @@ in
|
|||||||
|
|
||||||
|
|
||||||
keys = mkOption {
|
keys = mkOption {
|
||||||
type = types.attrsOf (types.submodule (
|
type = types.attrsOf (types.submodule {
|
||||||
{ options, ... }:
|
options = {
|
||||||
{ options = {
|
algorithm = mkOption {
|
||||||
|
type = types.str;
|
||||||
algorithm = mkOption {
|
default = "hmac-sha256";
|
||||||
type = types.str;
|
description = ''
|
||||||
default = "hmac-sha256";
|
Authentication algorithm for this key.
|
||||||
description = ''
|
'';
|
||||||
Authentication algorithm for this key.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
keyFile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
description = ''
|
|
||||||
Path to the file which contains the actual base64 encoded
|
|
||||||
key. The key will be copied into "${stateDir}/private" before
|
|
||||||
NSD starts. The copied file is only accessibly by the NSD
|
|
||||||
user.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}));
|
|
||||||
default = {
|
keyFile = mkOption {
|
||||||
};
|
type = types.path;
|
||||||
|
description = ''
|
||||||
|
Path to the file which contains the actual base64 encoded
|
||||||
|
key. The key will be copied into "${stateDir}/private" before
|
||||||
|
NSD starts. The copied file is only accessibly by the NSD
|
||||||
|
user.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = {};
|
||||||
example = {
|
example = {
|
||||||
"tsig.example.org" = {
|
"tsig.example.org" = {
|
||||||
algorithm = "hmac-md5";
|
algorithm = "hmac-md5";
|
||||||
secret = "aaaaaabbbbbbccccccdddddd";
|
secret = "aaaaaabbbbbbccccccdddddd";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
description = ''
|
description = ''
|
||||||
Define your TSIG keys here.
|
Define your TSIG keys here.
|
||||||
@ -626,32 +618,32 @@ in
|
|||||||
type = types.attrsOf zoneOptions;
|
type = types.attrsOf zoneOptions;
|
||||||
default = {};
|
default = {};
|
||||||
example = {
|
example = {
|
||||||
"serverGroup1" = {
|
"serverGroup1" = {
|
||||||
provideXFR = [ "10.1.2.3 NOKEY" ];
|
provideXFR = [ "10.1.2.3 NOKEY" ];
|
||||||
children = {
|
children = {
|
||||||
"example.com." = {
|
"example.com." = {
|
||||||
data = ''
|
data = ''
|
||||||
$ORIGIN example.com.
|
$ORIGIN example.com.
|
||||||
$TTL 86400
|
$TTL 86400
|
||||||
@ IN SOA a.ns.example.com. admin.example.com. (
|
@ IN SOA a.ns.example.com. admin.example.com. (
|
||||||
...
|
...
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
"example.org." = {
|
"example.org." = {
|
||||||
data = ''
|
data = ''
|
||||||
$ORIGIN example.org.
|
$ORIGIN example.org.
|
||||||
$TTL 86400
|
$TTL 86400
|
||||||
@ IN SOA a.ns.example.com. admin.example.com. (
|
@ IN SOA a.ns.example.com. admin.example.com. (
|
||||||
...
|
...
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
"example.net." = {
|
"example.net." = {
|
||||||
provideXFR = [ "10.3.2.1 NOKEY" ];
|
provideXFR = [ "10.3.2.1 NOKEY" ];
|
||||||
data = ''...'';
|
data = ''...'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
description = ''
|
description = ''
|
||||||
Define your zones here. Zones can cascade other zones and therefore
|
Define your zones here. Zones can cascade other zones and therefore
|
||||||
@ -670,23 +662,23 @@ in
|
|||||||
|
|
||||||
# this is not working :(
|
# this is not working :(
|
||||||
nixpkgs.config.nsd = {
|
nixpkgs.config.nsd = {
|
||||||
ipv6 = cfg.ipv6;
|
ipv6 = cfg.ipv6;
|
||||||
ratelimit = cfg.ratelimit.enable;
|
ratelimit = cfg.ratelimit.enable;
|
||||||
rootServer = cfg.rootServer;
|
rootServer = cfg.rootServer;
|
||||||
};
|
};
|
||||||
|
|
||||||
users.extraGroups = singleton {
|
users.extraGroups = singleton {
|
||||||
name = username;
|
name = username;
|
||||||
gid = config.ids.gids.nsd;
|
gid = config.ids.gids.nsd;
|
||||||
};
|
};
|
||||||
|
|
||||||
users.extraUsers = singleton {
|
users.extraUsers = singleton {
|
||||||
name = username;
|
name = username;
|
||||||
description = "NSD service user";
|
description = "NSD service user";
|
||||||
home = stateDir;
|
home = stateDir;
|
||||||
createHome = true;
|
createHome = true;
|
||||||
uid = config.ids.uids.nsd;
|
uid = config.ids.uids.nsd;
|
||||||
group = username;
|
group = username;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.nsd = {
|
systemd.services.nsd = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user