{
imports = [
modules/services/networking/domains.nix
+ modules/services/networking/knot.nix
modules/services/databases/openldap.nix
];
+disabledModules = [
+ "services/networking/knot.nix"
+];
}
/*
--- /dev/null
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.knot;
+
+ configFile = pkgs.writeText "knot.conf" cfg.extraConfig;
+ socketFile = "/run/knot/knot.sock";
+
+ knotConfCheck = file: pkgs.runCommand "knot-config-checked"
+ { buildInputs = [ cfg.package ]; } ''
+ ln -s ${configFile} $out
+ knotc --config=${configFile} conf-check
+ '';
+ keymgr = pkgs.writeShellScriptBin "keymgr" ''
+ ${pkgs.systemd}/bin/systemd-run --pipe \
+ --uid knot --working-directory="$PWD" \
+ -p DynamicUser=yes -p StateDirectory=knot \
+ ${cfg.package}/bin/keymgr --config=${configFile} "$@"
+ '';
+ knot-cli-wrappers = pkgs.stdenv.mkDerivation {
+ name = "knot-cli-wrappers";
+ buildInputs = [ pkgs.makeWrapper ];
+ buildCommand = ''
+ mkdir -p $out/bin
+ makeWrapper ${cfg.package}/bin/knotc "$out/bin/knotc" \
+ --add-flags "--config=${configFile}" \
+ --add-flags "--socket=${socketFile}"
+ for executable in kdig khost kjournalprint knsec3hash knsupdate kzonecheck
+ do
+ ln -s "${cfg.package}/bin/$executable" "$out/bin/$executable"
+ done
+ mkdir -p "$out/share"
+ ln -s '${cfg.package}/share/man' "$out/share/"
+ '';
+ };
+in {
+ options = {
+ services.knot = {
+ enable = mkEnableOption "Knot authoritative-only DNS server";
+
+ extraArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ List of additional command line paramters for knotd
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra lines to be added verbatim to knot.conf
+ '';
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.knot-dns;
+ defaultText = "pkgs.knot-dns";
+ description = ''
+ Which Knot DNS package to use
+ '';
+ };
+ };
+ };
+
+ config = mkIf config.services.knot.enable {
+ systemd.services.knot = {
+ unitConfig.Documentation = "man:knotd(8) man:knot.conf(5) man:knotc(8) https://www.knot-dns.cz/docs/${cfg.package.version}/html/";
+ description = cfg.package.meta.description;
+ wantedBy = [ "multi-user.target" ];
+ wants = [ "network.target" ];
+ after = ["network.target" ];
+
+ serviceConfig = {
+ Type = "notify";
+ ExecStart = "${cfg.package}/bin/knotd --config=${knotConfCheck configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
+ ExecReload = "${knot-cli-wrappers}/bin/knotc reload";
+ CapabilityBoundingSet = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
+ AmbientCapabilities = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
+ NoNewPrivileges = true;
+ DynamicUser = "yes";
+ RuntimeDirectory = "knot";
+ StateDirectory = "knot";
+ StateDirectoryMode = "0700";
+ PrivateDevices = true;
+ RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
+ SystemCallArchitectures = "native";
+ Restart = "on-abort";
+ };
+ };
+
+ environment.systemPackages = [ knot-cli-wrappers keymgr ];
+ };
+}
imports =
[ ../nixos/defaults.nix
mermet/unbound.nix
- mermet/nsd.nix
+ #mermet/nsd.nix
+ mermet/knot.nix
mermet/openldap.nix
mermet/gitolite.nix
mermet/nginx.nix
--- /dev/null
+{ pkgs, lib, config, ... }:
+let
+ inherit (lib) types;
+ inherit (config.services) knot;
+in
+{
+imports = [
+ knot/sourcephile.fr.nix
+];
+options.services.knot = {
+ zones = lib.mkOption {
+ default = {};
+ type = types.attrsOf (types.submodule ({domain, ...}: {
+ #config.domain = lib.mkDefault domain;
+ options = {
+ conf = lib.mkOption {
+ type = types.lines;
+ };
+ data = lib.mkOption {
+ type = types.nullOr types.lines;
+ };
+ };
+ }));
+ };
+};
+config = {
+systemd.services.knot.preStart = lib.concatStringsSep "\n" (lib.mapAttrsToList (domain: {data, ...}:
+ lib.optionalString (data != null) ''
+ install -D -o knot -g knot -m 700 ${pkgs.writeText "${domain}.zone" data} /var/lib/knot/zones/${domain}.zone
+ '') knot.zones);
+/*
+systemd.services.knot.postStart = lib.mkAfter ''
+ PATH="/run/current-system/sw/bin:$PATH"
+ knotc zone-freeze ${domain}.
+ while ! knotc zone-status ${domain}. +freeze | grep -q 'freeze: yes'; do sleep 1; done
+ knotc zone-flush ${domain}.
+ install -o knot -g knot -m 700 ${zone} /var/lib/knot/signed/${domain}.zone
+ knotc zone-reload ${domain}.
+ knotc zone-thaw ${domain}.
+'';
+*/
+services.knot = {
+ enable = true;
+ extraArgs = [ "-v" ];
+ # https://www.knot-dns.cz/docs/2.6/html/reference.html
+ extraConfig = ''
+ template:
+ - id: default
+ dnssec-signing: off
+ # move databases below the state directory, because they need to be writable
+ storage: /var/lib/knot/zones
+ # Input-only zone files
+ # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-3
+ # prevents modification of the zonefiles, since the zonefiles are immutable
+ #zonefile-sync: -1
+ zonefile-load: difference
+ journal-content: changes
+
+ database:
+ journal-db: /var/lib/knot/journal
+ kasp-db: /var/lib/knot/kasp
+ timer-db: /var/lib/knot/timer
+
+ log:
+ - target: syslog
+ any: info
+
+ remote:
+ - id: local_resolver
+ address: 127.0.0.1@53
+
+ - id: secondary_gandi
+ address: 217.70.177.40@53
+
+ submission:
+ - id: dnssec_validating_resolver
+ parent: local_resolver
+
+ policy:
+ - id: rsa
+ single-type-signing: false
+ ksk-shared: false
+ algorithm: RSASHA256
+ ksk-size: 4096
+ zsk-size: 2048
+ zsk-lifetime: 30d
+ ksk-lifetime: 365d
+ ksk-submission: dnssec_validating_resolver
+
+ - id: ed25519
+ single-type-signing: false
+ ksk-shared: false
+ algorithm: ED25519
+ ksk-size: 256
+ zsk-size: 256
+ zsk-lifetime: 30d
+ ksk-lifetime: 365d
+ cds-cdnskey-publish: always
+ ksk-submission: dnssec_validating_resolver
+
+ acl:
+ - id: acl_localhost
+ address: 127.0.0.1
+ action: transfer
+
+ # DOC: https://docs.gandi.net/en/domain_names/advanced_users/secondary_nameserver.html
+ - id: acl_gandi
+ address: 217.70.177.40
+ action: transfer
+
+ '' + lib.concatStringsSep "\n" (lib.mapAttrsToList (domain: {conf, ...}: conf) knot.zones);
+};
+};
+}
--- /dev/null
+{ pkgs, lib, config, ... }:
+with builtins;
+let
+ inherit (builtins.extraBuiltins) pass git;
+ inherit (pkgs.lib) unlinesAttrs types;
+ inherit (config) networking;
+ inherit (config.services) knot;
+ # Use the Git commit time of the ${domain}.nix file to set the serial number.
+ # WARNING: the ${domain}.nix must be committed into Git for this to work.
+ # WARNING: this does not take other .nix into account, though they may contribute to the zone's data.
+ serial = domain: toString (git ./. [ "log" "-1" "--format=%ct" "--" (domain + ".nix") ]);
+ mermetIPv4 = "80.67.180.129";
+ domain = "sourcephile.fr";
+ # TODO: increase the TTL once things have settled down
+in
+{
+services.knot.zones."${domain}" = {
+ conf = ''
+ zone:
+ - domain: ${domain}
+ file: ${domain}.zone
+ serial-policy: increment
+ semantic-checks: on
+ notify: secondary_gandi
+ acl: acl_gandi
+ acl: acl_localhost
+ dnssec-signing: on
+ dnssec-policy: rsa
+ '';
+ data = ''
+ $ORIGIN ${domain}.
+ $TTL 500
+
+ ; SOA (Start Of Authority)
+ @ SOA ns admin (
+ ${serial domain} ; Serial number
+ 24h ; Refresh
+ 15m ; Retry
+ 1000h ; Expire (1000h)
+ 1d ; Negative caching
+ )
+
+ ; NS (Name Server)
+ @ NS ns
+ @ NS ns6.gandi.net.
+
+ ; A (DNS -> IPv4)
+ @ A ${mermetIPv4}
+ mermet A ${mermetIPv4}
+ autoconfig A ${mermetIPv4}
+ code A ${mermetIPv4}
+ git A ${mermetIPv4}
+ imap A ${mermetIPv4}
+ mail A ${mermetIPv4}
+ ns A ${mermetIPv4}
+ pop A ${mermetIPv4}
+ smtp A ${mermetIPv4}
+ submission A ${mermetIPv4}
+ www A ${mermetIPv4}
+
+ ; SPF (Sender Policy Framework)
+ @ 3600 IN SPF "v=spf1 mx ip4:${mermetIPv4} -all"
+ @ 3600 IN TXT "v=spf1 mx ip4:${mermetIPv4} -all"
+
+ ; MX (Mail eXchange)
+ @ 180 MX 5 mail
+
+ ; SRV (SeRVice)
+ _git._tcp.git 18000 IN SRV 0 0 9418 git
+ '';
+};
+}
# (though / may still be encrypted at this point).
# boot.kernelParams = [ "boot.shell_on_fail" ];
- services.nsd.interfaces = [ netIPv4 ];
+ #services.nsd.interfaces = [ netIPv4 ];
+ services.knot.extraConfig = lib.mkBefore ''
+ server:
+ listen: ${netIPv4}@53
+ #listen: ::@53
+ '';
networking = {
useDHCP = false;
defaultGateway = {
# By port
DNS(ACCEPT) $FW net {user=${users.users.unbound.name}}
+ DNS(ACCEPT) $FW net:217.70.177.40 # for knot to notify ns6.gandi.net
Git(ACCEPT) $FW net
- HKP(ACCEPT) $FW net {user=julm}
+ HKP(ACCEPT) $FW net {user=${users.users.julm.name}}
HTTP(ACCEPT) $FW net
HTTPS(ACCEPT) $FW net
SMTP(ACCEPT) $FW net
{ pkgs, lib, config, ... }:
let
inherit (builtins.extraBuiltins) pass;
+ inherit (lib) types;
inherit (config.services) rspamd;
domain = "sourcephile.fr";
selector = "20200101";
mermet ${selector}
${domain} ${selector}
'';
+services.knot.zones."${domain}".data = ''
+ 20200101._domainkey IN TXT ( "v=DKIM1; k=rsa; "
+ "p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7EKzverbG+5JF+yFjH3MrxLyauiHyLqBbV/8LEMunoKXF8sqhBpQtAQXruLqsyUkxR/4CAyPMyzmcdrU43boMj9yFqLrg/kEz2RIvai9jXBqRoWRW1y7F0LbZmdtOTncuDSP8Zzo02XUzsOC4f/C3tEQHS5rc"
+ "hzfhU5FY1CeO6eBMV79qKBOvGMKahQTrrtU6olAAJxOhn6wRuwSf"
+ "+m3on1OqiuXYYIgNHKdRhJ8gDwIm/3LEpYMD0gTgJiyclCLoLGHGtKZy1Wf9xV9/7V6fHE4JW5SDivwslVTL+KPXOlIpo5NDHpMxPYOcIg2K4Rj/j7jhavo+fG43q1LhwaPkEMQMbplgnjeMY8300odRiklTkMMpH0m35ZNeHQJSRpEtV8y5xUNxVaGzfqX5iStwV/mQ1Kn"
+ "ZSe8ORTNq+eTTFnDk6zdUXjagcf0wO6QsSTeAz/G8CqOBbwmrU+q"
+ "F8WbGAeRnhz51mH6fTTfsQ1nwjAiF4ou+eQGTkTMN23KkCKpuozJnxqx4DCEr6J1bL83fhXw7CgcfgKgTOk/HFJpeiGhqodw18r4DWBA6G57z9utm7Mr/9SoVnMq6iK9iEcbCllLR8Sz4viatLSRzhodbk7hfvXS3jmCFjILAjFmA7aMTemDMBDQhpAGF9F8sjFUbEJIZjK"
+ "rWWtSTdO8DilDqN8CAwEAAQ=="
+ )
+'';
services.nsd.zones."${domain}".data = ''
20200101._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7EKzverbG+5JF+yFjH3MrxLyauiHyLqBbV/8LEMunoKXF8sqhBpQtAQXruLqsyUkxR/4CAyPMyzmcdrU43boMj9yFqLrg/kEz2RIvai9jXBqRoWRW1y7F0LbZmdtOTncuDSP8Zzo02XUzsOC4f/C3tEQHS5rc"
port: 53
verbosity: 1
+ server:
+ log-queries: no
+
# The file which contains the listing of primary root DNS servers.
# To be updated once every six months.
root-hints: /var/lib/unbound/named.root
sha256 = "15zs2146zh54jg1gywrcwyqxpx7izc35vlakk3cvrlqwwsvlr2rf";
}
];
+ localNixpkgsPatches = [
+ ];
nixpkgs = originPkgs.stdenv.mkDerivation {
name = "nixpkgs-patched";
src = originNixpkgs;
phases = [ "unpackPhase" "patchPhase" ];
- patches = map originPkgs.fetchpatch nixpkgsPatches;
+ patches = map originPkgs.fetchpatch nixpkgsPatches ++ localNixpkgsPatches;
postPatch = ''
patch=$(printf '%s\n' ${builtins.concatStringsSep " " (map (p: p.sha256) nixpkgsPatches)} |
sort | sha256sum | cut -c -7)