1 { pkgs, lib, config, inputs, hosts, info, ... }:
3 domain = "sourcephile.fr";
4 domainID = lib.replaceStrings [ "." ] [ "_" ] domain;
5 inherit (config) networking;
6 inherit (config.services) knot;
7 inherit (config.users) users groups;
9 # TODO: increase the TTL once things have settled down
14 ; SOA (Start Of Authority)
16 ${toString inputs.self.lastModified} ; Serial number
19 1000h ; Expire (1000h)
25 ;@ NS ${info.gandi.dns.secondary.ns.name}.
28 ns.whoami4 A ${hosts.mermet._module.args.ipv4}
31 @ A ${hosts.mermet._module.args.ipv4}
32 mermet A ${hosts.mermet._module.args.ipv4}
33 autoconfig A ${hosts.mermet._module.args.ipv4}
34 calibre A ${hosts.mermet._module.args.ipv4}
35 doc A ${hosts.mermet._module.args.ipv4}
36 git A ${hosts.mermet._module.args.ipv4}
37 imap A ${hosts.mermet._module.args.ipv4}
38 mail A ${hosts.mermet._module.args.ipv4}
39 mails A ${hosts.mermet._module.args.ipv4}
40 news A ${hosts.mermet._module.args.ipv4}
41 public-inbox A ${hosts.mermet._module.args.ipv4}
42 ns A ${hosts.mermet._module.args.ipv4}
43 pop A ${hosts.mermet._module.args.ipv4}
44 smtp A ${hosts.mermet._module.args.ipv4}
45 submission A ${hosts.mermet._module.args.ipv4}
46 www A ${hosts.mermet._module.args.ipv4}
47 croc A ${hosts.mermet._module.args.ipv4}
48 stun A ${hosts.mermet._module.args.ipv4}
49 turn A ${hosts.mermet._module.args.ipv4}
50 whoami A ${hosts.mermet._module.args.ipv4}
51 code A ${hosts.mermet._module.args.ipv4}
52 miniflux A ${hosts.mermet._module.args.ipv4}
57 ; CNAME (Canonical Name)
58 openconcerto CNAME losurdo
63 cryptpad CNAME losurdo
64 cryptpad-api CNAME losurdo
65 cryptpad-files CNAME losurdo
66 cryptpad-sandbox CNAME losurdo
69 nix-serve CNAME losurdo
70 nix-extracache CNAME losurdo
71 nix-localcache CNAME lan.losurdo
73 radicle-mermet CNAME mermet
75 radicle-explorer CNAME radicle
77 ; DMARC (Domain-based Message Authentication, Reporting and Conformance)
78 _dmarc 3600 IN TXT "v=DMARC1; p=none; pct=100; rua=mailto:root+dmarc+aggregate@sourcephile.fr; ruf=mailto:root+dmarc+forensic@sourcephile.fr"
80 ; SPF (Sender Policy Framework)
81 @ 3600 IN TXT "v=spf1 mx ip4:${hosts.mermet._module.args.ipv4} -all"
84 _git._tcp.git 18000 IN SRV 0 0 9418 git
85 _stun._udp 18000 IN SRV 0 5 3478 stun
86 _xmpp-client._tcp 18000 IN SRV 0 5 5222 xmpp
87 _xmpp-server._tcp 18000 IN SRV 0 5 5269 xmpp
88 _xmpp-server._tcp.salons 18000 IN SRV 0 5 5269 xmpp
89 _xmpps-client._tcp 18000 IN SRV 0 5 5223 xmpp
90 _xmpps-server._tcp 18000 IN SRV 0 5 5270 xmpp
91 _xmpps-server._tcp.salons 18000 IN SRV 0 5 5270 xmpp
93 ; CAA (Certificate Authority Authorization)
94 ; DOC: https://blog.qualys.com/ssllabs/2017/03/13/caa-mandated-by-cabrowser-forum
95 @ CAA 128 issue "letsencrypt.org; validationmethods=dns-01"
98 # accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/78014180
101 services.knot.settingsFreeform = {
102 remote.ns_iodine.address = "127.0.0.1@1053";
103 acl."acl_localhost_acme_${domainID}" = {
104 address = "127.0.0.1";
106 update-owner = "name";
107 update-owner-match = "equal";
108 update-owner-name = [ "_acme-challenge" ];
109 update-type = [ "TXT" ];
111 acl."acl_tsig_acme_${domainID}" = {
112 key = "acme_${domainID}";
114 update-owner = "name";
115 update-owner-match = "equal";
116 update-owner-name = [ "_acme-challenge" ];
117 update-type = [ "TXT" ];
119 acl."acl_tsig_losurdo_${domainID}" = {
120 key = "losurdo_${domainID}";
122 update-owner = "name";
123 update-owner-match = "equal";
124 update-owner-name = [ "losurdo" "lan.losurdo" ];
125 update-type = [ "A" "AAAA" ];
127 acl."acl_lebureau_${domainID}" = {
129 info.lebureau.dns.secondary.transfer.ipv4 ++
130 info.lebureau.dns.secondary.transfer.ipv6;
132 key = "lebureau_${domainID}";
134 mod-dnsproxy.proxy_iodine = {
135 remote = "ns_iodine";
138 remote."secondary_lebureau_${domainID}" = {
139 address = map (x: "${x}@53")
140 (info.lebureau.dns.secondary.transfer.ipv4 ++
141 info.lebureau.dns.secondary.transfer.ipv6);
142 key = "lebureau_${domainID}";
145 file = "${domain}.zone";
146 serial-policy = "increment";
147 semantic-checks = true;
149 "secondary_lebureau_${domainID}"
152 "acl_localhost_acme_${domainID}"
153 "acl_tsig_acme_${domainID}"
154 "acl_tsig_losurdo_${domainID}"
155 "acl_lebureau_${domainID}"
157 dnssec-signing = true;
158 dnssec-policy = "ed25519";
160 #zone."i.${domain}" = {
161 # module = "mod-dnsproxy/proxy_iodine";
163 zone."whoami4.${domain}" = {
164 module = "mod-whoami";
165 file = pkgs.writeText "whoami4.zone" ''
167 @ SOA ns root.${domain}. (
176 ns A ${hosts.mermet._module.args.ipv4}
182 "/run/credentials/knot.service/${domain}.acme.conf"
183 # Generated with: keymgr -t losurdo_${domainID}
184 "/run/credentials/knot.service/losurdo.conf"
185 # Generated with: keymgr -t lebureau_${domainID}
186 "/run/credentials/knot.service/${domain}.lebureau.conf"
189 systemd.services.knot = {
193 +${pkgs.coreutils}/bin/install -D -o ${users.knot.name} -g ${groups."knot".name} -m 700 \
194 ${pkgs.writeText "${domain}.zone" zoneData} \
195 /var/lib/knot/zones/${domain}.zone
198 LoadCredentialEncrypted = [
199 "${domain}.acme.conf:${builtins.path { path = ./. + "/${domain}/acme.conf.cred"; }}"
200 "${domain}.lebureau.conf:${builtins.path { path = ./. + "/${domain}/lebureau.conf.cred"; }}"
201 "losurdo.conf:${builtins.path { path = ./. + "/${domain}/losurdo.conf.cred"; }}"
205 networking.nftables.ruleset = ''
207 set output-net-knot-ipv4 { type ipv4_addr; elements = { ${lib.concatStringsSep ", " info.lebureau.dns.secondary.transfer.ipv4} }; }
208 set output-net-knot-ipv6 { type ipv6_addr; elements = { ${lib.concatStringsSep ", " info.lebureau.dns.secondary.transfer.ipv6} }; }
211 /* Useless since the zone is public
212 services.unbound.settings = {
215 stub-addr = "127.0.0.1@5353";