-{ inputs, pkgs, lib, config, hosts, ... }:
+{ pkgs, lib, config, inputs, hosts, info, ... }:
let
domain = "autogeree.net";
- domainID = lib.replaceStrings ["."] ["_"] domain;
- inherit (builtins) attrValues;
+ domainID = lib.replaceStrings [ "." ] [ "_" ] domain;
inherit (config) networking;
- inherit (config.security) gnupg;
inherit (config.services) knot;
- inherit (config.users) users;
-in
-{
-services.knot.zones."${domain}" = {
- conf = ''
- acl:
- - id: acl_localhost_acme_${domainID}
- address: 127.0.0.1
- action: update
- update-owner: name
- update-owner-match: equal
- update-owner-name: [_acme-challenge]
- update-type: [TXT]
- - id: acl_tsig_acme_${domainID}
- key: acme_${domainID}
- action: update
- update-owner: name
- update-owner-match: equal
- update-owner-name: [_acme-challenge]
- update-type: [TXT]
+ inherit (config.users) users groups;
+ zoneData =
+ # TODO: increase the TTL once things have settled down
+ ''
+ $ORIGIN ${domain}.
+ $TTL 500
- zone:
- - domain: ${domain}
- file: ${domain}.zone
- serial-policy: increment
- semantic-checks: on
- notify: secondary_gandi
- #notify: secondary_muarf
- acl: acl_gandi
- #acl: acl_muarf
- acl: acl_localhost_acme_${domainID}
- acl: acl_tsig_acme_${domainID}
- dnssec-signing: off
- dnssec-policy: ed25519
- '';
- # TODO: increase the TTL once things have settled down
- data = ''
- $ORIGIN ${domain}.
- $TTL 500
+ ; SOA (Start Of Authority)
+ @ SOA ns root (
+ ${toString inputs.self.lastModified} ; Serial number
+ 24h ; Refresh
+ 15m ; Retry
+ 1000h ; Expire (1000h)
+ 1d ; Negative caching
+ )
- ; SOA (Start Of Authority)
- @ SOA ns root (
- ${toString inputs.self.lastModified} ; Serial number
- 24h ; Refresh
- 15m ; Retry
- 1000h ; Expire (1000h)
- 1d ; Negative caching
- )
+ ; NS (Name Server)
+ @ NS ns
+ @ NS ${info.gandi.dns.secondary.ns.name}.
+ ;@ NS ns0.muarf.org.
- ; NS (Name Server)
- @ NS ns
- @ NS ns6.gandi.net.
- ;@ NS ns0.muarf.org.
+ ; A (DNS -> IPv4)
+ @ A ${hosts.mermet._module.args.ipv4}
+ mermet A ${hosts.mermet._module.args.ipv4}
+ autoconfig A ${hosts.mermet._module.args.ipv4}
+ code A ${hosts.mermet._module.args.ipv4}
+ git A ${hosts.mermet._module.args.ipv4}
+ imap A ${hosts.mermet._module.args.ipv4}
+ mail A ${hosts.mermet._module.args.ipv4}
+ ns A ${hosts.mermet._module.args.ipv4}
+ pleroma A ${hosts.mermet._module.args.ipv4}
+ pop A ${hosts.mermet._module.args.ipv4}
+ smtp A ${hosts.mermet._module.args.ipv4}
+ submission A ${hosts.mermet._module.args.ipv4}
+ www A ${hosts.mermet._module.args.ipv4}
+ chomsky A 91.216.110.36
+ alpes A 195.88.84.51
- ; A (DNS -> IPv4)
- @ A ${hosts.mermet._module.args.ipv4}
- mermet A ${hosts.mermet._module.args.ipv4}
- autoconfig A ${hosts.mermet._module.args.ipv4}
- code A ${hosts.mermet._module.args.ipv4}
- git A ${hosts.mermet._module.args.ipv4}
- imap A ${hosts.mermet._module.args.ipv4}
- mail A ${hosts.mermet._module.args.ipv4}
- ns A ${hosts.mermet._module.args.ipv4}
- pop A ${hosts.mermet._module.args.ipv4}
- smtp A ${hosts.mermet._module.args.ipv4}
- submission A ${hosts.mermet._module.args.ipv4}
- www A ${hosts.mermet._module.args.ipv4}
- chomsky A 91.216.110.36
- alpes A 195.88.84.51
+ ; SPF (Sender Policy Framework)
+ @ 3600 IN SPF "v=spf1 mx ip4:${hosts.mermet._module.args.ipv4} -all"
+ @ 3600 IN TXT "v=spf1 mx ip4:${hosts.mermet._module.args.ipv4} -all"
- ; SPF (Sender Policy Framework)
- @ 3600 IN SPF "v=spf1 mx ip4:${hosts.mermet._module.args.ipv4} -all"
- @ 3600 IN TXT "v=spf1 mx ip4:${hosts.mermet._module.args.ipv4} -all"
+ ; MX (Mail eXchange)
+ @ 180 MX 5 mail
- ; MX (Mail eXchange)
- @ 180 MX 5 mail
+ ; SRV (SeRVice)
+ _git._tcp.git 18000 IN SRV 0 0 9418 git
- ; SRV (SeRVice)
- _git._tcp.git 18000 IN SRV 0 0 9418 git
-
- ; CAA (Certificate Authority Authorization)
- ; DOC: https://blog.qualys.com/ssllabs/2017/03/13/caa-mandated-by-cabrowser-forum
- @ CAA 128 issue "letsencrypt.org"
+ ; CAA (Certificate Authority Authorization)
+ ; DOC: https://blog.qualys.com/ssllabs/2017/03/13/caa-mandated-by-cabrowser-forum
+ @ CAA 128 issue "letsencrypt.org; validationmethods=dns-01"
+ '';
+ # Incorrect:
+ #@ CAA 128 issue "letsencrypt.org; validationmethods=dns-01; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/79737822"
+in
+{
+ services.knot.settingsFreeform = {
+ acl."acl_localhost_acme_${domainID}" = {
+ address = "127.0.0.1";
+ action = "update";
+ update-owner = "name";
+ update-owner-match = "equal";
+ update-owner-name = [ "_acme-challenge" ];
+ update-type = [ "TXT" ];
+ };
+ acl."acl_tsig_acme_${domainID}" = {
+ key = "acme_${domainID}";
+ action = "update";
+ update-owner = "name";
+ update-owner-match = "equal";
+ update-owner-name = [ "_acme-challenge" ];
+ update-type = [ "TXT" ];
+ };
+ zone."${domain}" = {
+ file = "${domain}.zone";
+ serial-policy = "increment";
+ semantic-checks = true;
+ notify = [
+ "secondary_gandi"
+ #"secondary_muarf"
+ ];
+ acl = [
+ "acl_gandi"
+ #"acl_muarf"
+ "acl_localhost_acme_${domainID}"
+ "acl_tsig_acme_${domainID}"
+ ];
+ dnssec-signing = false;
+ dnssec-policy = "ed25519";
+ };
+ };
+ networking.nftables.ruleset = ''
+ table inet filter {
+ set output-net-knot-ipv4 { type ipv4_addr; elements = { ${info.gandi.dns.secondary.axfr.ipv4} }; }
+ set output-net-knot-ipv6 { type ipv6_addr; elements = { ${info.gandi.dns.secondary.axfr.ipv6} }; }
+ }
'';
-};
-users.groups.keys.members = [ users.knot.name ];
-services.knot = {
- keyFiles = [ gnupg.secrets."knot/tsig/${domain}/acme.conf".path ];
-};
-security.gnupg.secrets."knot/tsig/${domain}/acme.conf" = {
- # Generated with: keymgr -t acme_${domainID}
- user = users.knot.name;
-};
-systemd.services.knot = {
- after = [ gnupg.secrets."knot/tsig/${domain}/acme.conf".service ];
- wants = [ gnupg.secrets."knot/tsig/${domain}/acme.conf".service ];
-};
-/* Useless since the zone is public
-services.unbound.settings = {
- stub-zone = {
+ services.knot = {
+ keyFiles = [
+ "/run/credentials/knot.service/${domain}.acme.conf"
+ ];
+ };
+ systemd.services.knot = {
+ serviceConfig = {
+ ExecStartPre = [
+ ''
+ +${pkgs.coreutils}/bin/install -D -o ${users.knot.name} -g ${groups."knot".name} -m 700 \
+ ${pkgs.writeText "${domain}.zone" zoneData} \
+ /var/lib/knot/zones/${domain}.zone
+ ''
+ ];
+ LoadCredentialEncrypted = [
+ "${domain}.acme.conf:${./. + "/${domain}/acme.conf.cred"}"
+ ];
+ };
+ };
+ /* Useless since the zone is public
+ services.unbound.settings = {
+ stub-zone = {
name = domain;
stub-addr = "127.0.0.1@5353";
- };
-};
-'';
-*/
+ };
+ };
+ '';
+ */
}