Informis Checkin
This commit is contained in:
parent
acac0ef720
commit
d429825817
|
@ -6,26 +6,28 @@ with lib;
|
||||||
let
|
let
|
||||||
cfg = config.fudo.acme;
|
cfg = config.fudo.acme;
|
||||||
|
|
||||||
wwwRoot = hostname:
|
# wwwRoot = hostname:
|
||||||
pkgs.writeTextFile {
|
# pkgs.writeTextFile {
|
||||||
name = "index.html";
|
# name = "index.html";
|
||||||
|
|
||||||
text = ''
|
# text = ''
|
||||||
<html>
|
# <html>
|
||||||
<head>
|
# <head>
|
||||||
<title>${hostname}</title>
|
# <title>${hostname}</title>
|
||||||
</head>
|
# </head>
|
||||||
<body>
|
# <body>
|
||||||
<h1>${hostname}</title>
|
# <h1>${hostname}</title>
|
||||||
</body>
|
# </body>
|
||||||
</html>
|
# </html>
|
||||||
'';
|
# '';
|
||||||
destination = "/www";
|
# destination = "/www";
|
||||||
};
|
# };
|
||||||
|
|
||||||
in {
|
in {
|
||||||
|
|
||||||
options.fudo.acme = {
|
options.fudo.acme = {
|
||||||
|
enable = mkEnableOption "Fetch ACME certs for supplied local hostnames.";
|
||||||
|
|
||||||
hostnames = mkOption {
|
hostnames = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
description = "A list of hostnames mapping to this host, for which to acquire SSL certificates.";
|
description = "A list of hostnames mapping to this host, for which to acquire SSL certificates.";
|
||||||
|
@ -35,9 +37,15 @@ in {
|
||||||
"alt.hostname.com"
|
"alt.hostname.com"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
admin-address = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "The admin address in charge of these addresses.";
|
||||||
|
default = "admin@fudo.org";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -49,13 +57,13 @@ in {
|
||||||
{
|
{
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
root = (wwwRoot hostname) + ("/" + "www");
|
# root = (wwwRoot hostname) + ("/" + "www");
|
||||||
})
|
})
|
||||||
cfg.hostnames);
|
cfg.hostnames);
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme.certs = listToAttrs
|
security.acme.certs = listToAttrs
|
||||||
(map (hostname: nameValuePair hostname { email = "admin@fudo.org"; })
|
(map (hostname: nameValuePair hostname { email = cfg.admin-address; })
|
||||||
cfg.hostnames);
|
cfg.hostnames);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
{ lib, config, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.fudo.dns;
|
||||||
|
|
||||||
|
ip = import ../../lib/ip.nix { lib = lib; };
|
||||||
|
|
||||||
|
join-lines = concatStringsSep "\n";
|
||||||
|
|
||||||
|
hostOpts = { host, ...}: {
|
||||||
|
options = {
|
||||||
|
ip-addresses = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
description = ''
|
||||||
|
A list of IPv4 addresses assigned to this host.
|
||||||
|
'';
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
ipv6-addresses = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
description = ''
|
||||||
|
A list of IPv6 addresses assigned to this host.
|
||||||
|
'';
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
ssh-fingerprints = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
description = ''
|
||||||
|
A list of DNS SSHFP records for this host.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
srvRecordOpts = with types; {
|
||||||
|
options = {
|
||||||
|
weight = mkOption {
|
||||||
|
type = int;
|
||||||
|
description = "Weight relative to other records.";
|
||||||
|
default = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
priority = mkOption {
|
||||||
|
type = int;
|
||||||
|
description = "Priority to give this record.";
|
||||||
|
default = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = port;
|
||||||
|
description = "Port to use while connecting to this service.";
|
||||||
|
};
|
||||||
|
|
||||||
|
host = mkOption {
|
||||||
|
type = str;
|
||||||
|
description = "Host that provides this service.";
|
||||||
|
example = "my-host.my-domain.com";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
domainOpts = { domain, ... }: with types; {
|
||||||
|
options = {
|
||||||
|
hosts = mkOption {
|
||||||
|
type = loaOf (submodule hostOpts);
|
||||||
|
default = {};
|
||||||
|
description = "A map of hostname to { host_attributes }.";
|
||||||
|
};
|
||||||
|
|
||||||
|
dnssec = mkEnableOption "Enable DNSSEC security for this zone.";
|
||||||
|
|
||||||
|
mx = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
description = "A list of mail servers serving this domain.";
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
srv-records = mkOption {
|
||||||
|
type = attrsOf (attrsOf (listOf (submodule srvRecordOpts)));
|
||||||
|
description = "Map of traffic type to srv records.";
|
||||||
|
default = {};
|
||||||
|
example = {
|
||||||
|
tcp = {
|
||||||
|
kerberos = {
|
||||||
|
port = 88;
|
||||||
|
host = "auth-host.my-domain.com";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
aliases = mkOption {
|
||||||
|
type = loaOf str;
|
||||||
|
default = {};
|
||||||
|
description = "A mapping of host-alias => hostnames to add to DNS.";
|
||||||
|
example = {
|
||||||
|
"music" = "host.dom.com.";
|
||||||
|
"mail" = "hostname";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extra-dns-records = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
description = "Records to be inserted verbatim into the DNS zone.";
|
||||||
|
example = ["some-host IN CNAME base-host"];
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
dmarc-report-address = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
description = "The email to use to recieve DMARC reports, if any.";
|
||||||
|
example = "admin-user@domain.com";
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
default-host = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
description = "IP of the host which will act as the default server for this domain, if any.";
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
hostARecords = host: data:
|
||||||
|
join-lines ((map (ip: "${host} IN A ${ip}") data.ip-addresses) ++
|
||||||
|
(map (ip: "${host} IN AAAA ${ip}") data.ipv6-addresses));
|
||||||
|
|
||||||
|
makeSrvRecords = protocol: type: records:
|
||||||
|
join-lines (map (record: "_${type}._${protocol} IN SRV ${toString record.priority} ${toString record.weight} ${toString record.port} ${toString record.host}.")
|
||||||
|
records);
|
||||||
|
|
||||||
|
makeSrvProtocolRecords = protocol: types: join-lines (mapAttrsToList (makeSrvRecords protocol) types);
|
||||||
|
|
||||||
|
cnameRecord = alias: host: "${alias} IN CNAME ${host}";
|
||||||
|
|
||||||
|
hostSshFpRecords = host: data: join-lines (map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints);
|
||||||
|
|
||||||
|
mxRecords = mxs:
|
||||||
|
concatStringsSep "\n"
|
||||||
|
(map (mx: "@ IN MX 10 ${mx}.") mxs);
|
||||||
|
|
||||||
|
dmarcRecord = dmarc-email:
|
||||||
|
optionalString (dmarc-email != null)
|
||||||
|
''_dmarc IN TXT "v=DMARC1;p=quarantine;sp=quarantine;rua=mailto:${dmarc-email};"'';
|
||||||
|
|
||||||
|
nsRecords = ns-hosts:
|
||||||
|
join-lines ((mapAttrsToList (host: _: "@ IN NS ${host}.") ns-hosts) ++
|
||||||
|
(mapAttrsToList (host: ip: "${host} IN A ${ip}") ns-hosts));
|
||||||
|
|
||||||
|
in {
|
||||||
|
|
||||||
|
options.fudo.dns = with types; {
|
||||||
|
enable = mkEnableOption "Enable master DNS services.";
|
||||||
|
|
||||||
|
# FIXME: This should allow for AAAA addresses too...
|
||||||
|
dns-hosts = mkOption {
|
||||||
|
type = loaOf str;
|
||||||
|
description = "Map of domain nameserver FQDNs to IP.";
|
||||||
|
example = { "ns1.domain.com" = "1.1.1.1"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
domains = mkOption {
|
||||||
|
type = loaOf (submodule domainOpts);
|
||||||
|
default = {};
|
||||||
|
description = "A map of domain to domain options.";
|
||||||
|
};
|
||||||
|
|
||||||
|
listen-ips = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
description = "A list of IPs on which to listen for DNS queries.";
|
||||||
|
example = ["1.2.3.4"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
services.nsd = {
|
||||||
|
enable = true;
|
||||||
|
identity = "procul.informis.land";
|
||||||
|
interfaces = cfg.listen-ips;
|
||||||
|
zones = mapAttrs' (dom: dom-cfg:
|
||||||
|
nameValuePair "${dom}." {
|
||||||
|
dnssec = dom-cfg.dnssec;
|
||||||
|
|
||||||
|
data = ''
|
||||||
|
$ORIGIN ${dom}.
|
||||||
|
$TTL 12h
|
||||||
|
|
||||||
|
@ IN SOA ns1.${dom}. hostmaster.${dom}. (
|
||||||
|
${toString builtins.currentTime}
|
||||||
|
5m
|
||||||
|
2m
|
||||||
|
6w
|
||||||
|
5m)
|
||||||
|
|
||||||
|
${optionalString (dom-cfg.default-host != null) "@ IN A ${dom-cfg.default-host}"}
|
||||||
|
|
||||||
|
${mxRecords dom-cfg.mx}
|
||||||
|
|
||||||
|
$TTL 6h
|
||||||
|
|
||||||
|
${nsRecords cfg.dns-hosts}
|
||||||
|
|
||||||
|
${dmarcRecord dom-cfg.dmarc-report-address}
|
||||||
|
|
||||||
|
${join-lines (mapAttrsToList makeSrvProtocolRecords dom-cfg.srv-records)}
|
||||||
|
${join-lines (mapAttrsToList hostARecords dom-cfg.hosts)}
|
||||||
|
${join-lines (mapAttrsToList hostSshFpRecords dom-cfg.hosts)}
|
||||||
|
${join-lines (mapAttrsToList cnameRecord dom-cfg.aliases)}
|
||||||
|
${join-lines dom-cfg.extra-dns-records}
|
||||||
|
'';
|
||||||
|
}) cfg.domains;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -104,6 +104,7 @@ in {
|
||||||
user-aliases = mkOption {
|
user-aliases = mkOption {
|
||||||
type = with types; loaOf(listOf str);
|
type = with types; loaOf(listOf str);
|
||||||
description = "A map of real user to list of aliases.";
|
description = "A map of real user to list of aliases.";
|
||||||
|
default = {};
|
||||||
example = {
|
example = {
|
||||||
someuser = ["alias0" "alias1"];
|
someuser = ["alias0" "alias1"];
|
||||||
};
|
};
|
||||||
|
@ -167,4 +168,22 @@ in {
|
||||||
./mail/rspamd.nix
|
./mail/rspamd.nix
|
||||||
./mail/clamav.nix
|
./mail/clamav.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
users = {
|
||||||
|
users = {
|
||||||
|
mailuser = {
|
||||||
|
isSystemUser = true;
|
||||||
|
uid = cfg.mail-user-id;
|
||||||
|
group = "mailgroup";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
groups = {
|
||||||
|
mailgroup = {
|
||||||
|
members = ["mailuser"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,61 +23,86 @@ let
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
ldap-conf = filename: uris:
|
ldap-conf = filename: config:
|
||||||
pkgs.writeText filename ''
|
let
|
||||||
uris = ${concatStringsSep " " uris}
|
ssl-config = if config.ca == null then ''
|
||||||
|
tls = no
|
||||||
|
tls_require_cert = try
|
||||||
|
'' else ''
|
||||||
|
tls_ca_cert_file = ${config.ca}
|
||||||
|
tls = yes
|
||||||
|
tls_require_cert = try
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
pkgs.writeText filename ''
|
||||||
|
uris = ${concatStringsSep " " config.server-urls}
|
||||||
ldap_version = 3
|
ldap_version = 3
|
||||||
dn = ${cfg.dovecot.ldap-reader-dn}
|
dn = ${config.reader-dn}
|
||||||
dnpass = ${cfg.dovecot.ldap-reader-passwd}
|
dnpass = ${config.reader-passwd}
|
||||||
auth_bind = yes
|
auth_bind = yes
|
||||||
auth_bind_userdn = uid=%u,ou=members,dc=fudo,dc=org
|
auth_bind_userdn = uid=%u,ou=members,dc=fudo,dc=org
|
||||||
base = dc=fudo,dc=org
|
base = dc=fudo,dc=org
|
||||||
# tls_ca_cert_file = ${cfg.dovecot.ldap-ca}
|
${ssl-config}
|
||||||
# FIXME: turn back on when certs work
|
|
||||||
tls = no
|
|
||||||
tls_require_cert = try
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
dovecot-user = config.services.dovecot2.user;
|
ldap-passwd-entry = ldap-config: ''
|
||||||
|
passdb {
|
||||||
|
driver = ldap
|
||||||
|
args = ${ldap-conf "ldap-passdb.conf" ldap-config}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
in {
|
ldapOpts = with types; {
|
||||||
options.fudo.mail-server.dovecot = {
|
ca = mkOption {
|
||||||
ssl-private-key = mkOption {
|
type = str;
|
||||||
type = types.str;
|
|
||||||
description = "Location of the server SSL private key.";
|
|
||||||
};
|
|
||||||
|
|
||||||
ssl-certificate = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "Location of the server SSL certificate.";
|
|
||||||
};
|
|
||||||
|
|
||||||
ldap-ca = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "The path to the CA cert used to sign the LDAP server certificate.";
|
description = "The path to the CA cert used to sign the LDAP server certificate.";
|
||||||
};
|
};
|
||||||
|
|
||||||
ldap-urls = mkOption {
|
server-urls = mkOption {
|
||||||
type = with types; listOf str;
|
type = listOf str;
|
||||||
description = "The urls of LDAP servers.";
|
description = "A list of LDAP server URLs used for authentication.";
|
||||||
};
|
};
|
||||||
|
|
||||||
ldap-reader-dn = mkOption {
|
reader-dn = mkOption {
|
||||||
type = types.str;
|
type = str;
|
||||||
description = ''
|
description = ''
|
||||||
DN to use for reading user information. Needs access to homeDirectory,
|
DN to use for reading user information. Needs access to homeDirectory,
|
||||||
uidNumber, gidNumber, and uid, but not password attributes.
|
uidNumber, gidNumber, and uid, but not password attributes.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
ldap-reader-passwd = mkOption {
|
reader-pw = mkOption {
|
||||||
type = types.str;
|
type = str;
|
||||||
description = ''
|
description = ''
|
||||||
Password for the user specified in ldap-reader-dn.
|
Password for the user specified in ldap-reader-dn.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dovecot-user = config.services.dovecot2.user;
|
||||||
|
|
||||||
|
in {
|
||||||
|
options.fudo.mail-server.dovecot = with types; {
|
||||||
|
ssl-private-key = mkOption {
|
||||||
|
type = str;
|
||||||
|
description = "Location of the server SSL private key.";
|
||||||
|
};
|
||||||
|
|
||||||
|
ssl-certificate = mkOption {
|
||||||
|
type = str;
|
||||||
|
description = "Location of the server SSL certificate.";
|
||||||
|
};
|
||||||
|
|
||||||
|
ldap = mkOption {
|
||||||
|
type = nullOr (submodule ldapOpts);
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
LDAP auth server configuration. If omitted, the server will use local authentication.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
services.prometheus.exporters.dovecot = mkIf cfg.monitoring {
|
services.prometheus.exporters.dovecot = mkIf cfg.monitoring {
|
||||||
|
@ -93,8 +118,7 @@ in {
|
||||||
enableImap = true;
|
enableImap = true;
|
||||||
enableLmtp = true;
|
enableLmtp = true;
|
||||||
enablePop3 = true;
|
enablePop3 = true;
|
||||||
enablePAM = false;
|
enablePAM = cfg.dovecot.ldap == null;
|
||||||
|
|
||||||
|
|
||||||
createMailUser = true;
|
createMailUser = true;
|
||||||
|
|
||||||
|
@ -124,14 +148,16 @@ in {
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
#Extra Config
|
#Extra Config
|
||||||
|
|
||||||
# The prometheus exporter still expects an older style of metrics
|
${optionalString cfg.monitoring ''
|
||||||
mail_plugins = $mail_plugins old_stats
|
# The prometheus exporter still expects an older style of metrics
|
||||||
service old-stats {
|
mail_plugins = $mail_plugins old_stats
|
||||||
unix_listener old-stats {
|
service old-stats {
|
||||||
user = dovecot-exporter
|
unix_listener old-stats {
|
||||||
group = dovecot-exporter
|
user = dovecot-exporter
|
||||||
|
group = dovecot-exporter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
''}
|
||||||
|
|
||||||
${lib.optionalString cfg.debug ''
|
${lib.optionalString cfg.debug ''
|
||||||
mail_debug = yes
|
mail_debug = yes
|
||||||
|
@ -170,15 +196,15 @@ in {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Drop privs, since all mail is owned by one user
|
# Drop privs, since all mail is owned by one user
|
||||||
user = ${cfg.mail-user}
|
# user = ${cfg.mail-user}
|
||||||
group = ${cfg.mail-group}
|
# group = ${cfg.mail-group}
|
||||||
|
user = root
|
||||||
}
|
}
|
||||||
|
|
||||||
auth_mechanisms = login plain
|
auth_mechanisms = login plain
|
||||||
passdb {
|
|
||||||
driver = ldap
|
${optionalString (cfg.dovecot.ldap != null)
|
||||||
args = ${ldap-conf "ldap-passdb.conf" cfg.dovecot.ldap-urls}
|
(ldap-conf cfg.dovecot.ldap)}
|
||||||
}
|
|
||||||
userdb {
|
userdb {
|
||||||
driver = static
|
driver = static
|
||||||
args = uid=${toString cfg.mail-user-id} home=${cfg.mail-directory}/%u
|
args = uid=${toString cfg.mail-user-id} home=${cfg.mail-directory}/%u
|
||||||
|
@ -189,8 +215,18 @@ in {
|
||||||
unix_listener auth {
|
unix_listener auth {
|
||||||
mode = 0660
|
mode = 0660
|
||||||
user = "${config.services.postfix.user}"
|
user = "${config.services.postfix.user}"
|
||||||
group = ${config.services.postfix.group}
|
group = ${cfg.mail-group}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unix_listener auth-userdb {
|
||||||
|
mode = 0660
|
||||||
|
user = "${config.services.postfix.user}"
|
||||||
|
group = ${cfg.mail-group}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service auth-worker {
|
||||||
|
user = root
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace inbox {
|
namespace inbox {
|
||||||
|
@ -236,7 +272,8 @@ in {
|
||||||
done
|
done
|
||||||
chown -R '${dovecot-user}:${cfg.mail-group}' '${state-directory}/imap_sieve'
|
chown -R '${dovecot-user}:${cfg.mail-group}' '${state-directory}/imap_sieve'
|
||||||
|
|
||||||
chown ${cfg.mail-user}:${cfg.mail-group} ${cfg.mail-directory}
|
chown '${cfg.mail-user}:${cfg.mail-group}' ${cfg.mail-directory}
|
||||||
|
chmod g+w ${cfg.mail-directory}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,14 @@ let
|
||||||
|
|
||||||
cfg = config.fudo.mail-server;
|
cfg = config.fudo.mail-server;
|
||||||
|
|
||||||
|
# The final newline is important
|
||||||
|
write-entries = filename: entries:
|
||||||
|
let
|
||||||
|
entries-string = (concatStringsSep "\n" entries);
|
||||||
|
in builtins.toFile filename ''
|
||||||
|
${entries-string}
|
||||||
|
'';
|
||||||
|
|
||||||
make-user-aliases = entries:
|
make-user-aliases = entries:
|
||||||
concatStringsSep "\n"
|
concatStringsSep "\n"
|
||||||
(mapAttrsToList (user: aliases:
|
(mapAttrsToList (user: aliases:
|
||||||
|
@ -39,25 +47,22 @@ let
|
||||||
/^User-Agent:/ IGNORE
|
/^User-Agent:/ IGNORE
|
||||||
/^X-Enigmail:/ IGNORE
|
/^X-Enigmail:/ IGNORE
|
||||||
'');
|
'');
|
||||||
|
|
||||||
blacklist-postfix-entry = sender: "${sender} REJECT";
|
blacklist-postfix-entry = sender: "${sender} REJECT";
|
||||||
blacklist-postfix-file = entries:
|
blacklist-postfix-file = filename: entries:
|
||||||
concatStringsSep "\n" (map blacklist-postfix-entry entries);
|
write-entries filename entries;
|
||||||
sender-blacklist-file = builtins.toFile "reject_senders"
|
sender-blacklist-file = blacklist-postfix-file "reject_senders"
|
||||||
(blacklist-postfix-file cfg.sender-blacklist);
|
(map blacklist-postfix-entry cfg.sender-blacklist);
|
||||||
recipient-blacklist-file = builtins.toFile "reject_recipients"
|
recipient-blacklist-file = blacklist-postfix-file "reject_recipients"
|
||||||
(blacklist-postfix-file cfg.recipient-blacklist);
|
(map blacklist-postfix-entry cfg.recipient-blacklist);
|
||||||
|
|
||||||
# A list of domains for which we accept mail
|
# A list of domains for which we accept mail
|
||||||
virtual-mailbox-map-file = builtins.toFile "virtual_mailbox_map"
|
virtual-mailbox-map-file = write-entries "virtual_mailbox_map"
|
||||||
(concatStringsSep "\n"
|
(map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain]));
|
||||||
(map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain])));
|
|
||||||
|
|
||||||
sender-login-map-file = let
|
sender-login-map-file = let
|
||||||
escapeDot = (str: replaceStrings ["."] ["\\."] str);
|
escapeDot = (str: replaceStrings ["."] ["\\."] str);
|
||||||
in builtins.toFile "sender_login_maps"
|
in write-entries "sender_login_maps"
|
||||||
(concatStringsSep "\n"
|
(map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain]));
|
||||||
(map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain])));
|
|
||||||
|
|
||||||
mapped-file = name: "hash:/var/lib/postfix/conf/${name}";
|
mapped-file = name: "hash:/var/lib/postfix/conf/${name}";
|
||||||
|
|
||||||
|
@ -106,9 +111,8 @@ in {
|
||||||
origin = cfg.domain;
|
origin = cfg.domain;
|
||||||
hostname = cfg.hostname;
|
hostname = cfg.hostname;
|
||||||
destination = ["localhost" "localhost.localdomain"];
|
destination = ["localhost" "localhost.localdomain"];
|
||||||
# destination = ["localhost" "localhost.localdomain"] ++
|
# destination = ["localhost" "localhost.localdomain" cfg.hostname] ++
|
||||||
# (map (domain: "localhost.${domain}") cfg.local-domains) ++
|
# cfg.local-domains;;
|
||||||
# cfg.local-domains;
|
|
||||||
|
|
||||||
enableHeaderChecks = true;
|
enableHeaderChecks = true;
|
||||||
enableSmtp = true;
|
enableSmtp = true;
|
||||||
|
@ -133,7 +137,7 @@ in {
|
||||||
sslKey = cfg.postfix.ssl-private-key;
|
sslKey = cfg.postfix.ssl-private-key;
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
virtual_mailbox_domains = builtins.toFile "domain-list" (concatStringsSep "\n" cfg.local-domains);
|
virtual_mailbox_domains = cfg.local-domains ++ [cfg.domain];
|
||||||
# virtual_mailbox_base = "${cfg.mail-directory}/";
|
# virtual_mailbox_base = "${cfg.mail-directory}/";
|
||||||
virtual_mailbox_maps = mapped-file "virtual_mailbox_map";
|
virtual_mailbox_maps = mapped-file "virtual_mailbox_map";
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ with lib;
|
||||||
./fudo/authentication.nix
|
./fudo/authentication.nix
|
||||||
./fudo/chat.nix
|
./fudo/chat.nix
|
||||||
./fudo/common.nix
|
./fudo/common.nix
|
||||||
|
./fudo/dns.nix
|
||||||
./fudo/git.nix
|
./fudo/git.nix
|
||||||
./fudo/grafana.nix
|
./fudo/grafana.nix
|
||||||
./fudo/kdc.nix
|
./fudo/kdc.nix
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
lshw
|
lshw
|
||||||
mkpasswd
|
mkpasswd
|
||||||
ncurses5
|
ncurses5
|
||||||
|
nix-index
|
||||||
nmap
|
nmap
|
||||||
oidentd
|
oidentd
|
||||||
openldap
|
openldap
|
||||||
|
|
|
@ -51,6 +51,8 @@ in {
|
||||||
config = mkIf (config.fudo.common.profile == "server") {
|
config = mkIf (config.fudo.common.profile == "server") {
|
||||||
environment = {
|
environment = {
|
||||||
systemPackages = with pkgs; [
|
systemPackages = with pkgs; [
|
||||||
|
ldns
|
||||||
|
ldns.examples
|
||||||
test-config
|
test-config
|
||||||
reboot-if-necessary
|
reboot-if-necessary
|
||||||
];
|
];
|
||||||
|
|
|
@ -2,12 +2,7 @@
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
admin = "admin@fudo.org";
|
admin = "admin@informis.land";
|
||||||
|
|
||||||
nameservers = [
|
|
||||||
"1.1.1.1"
|
|
||||||
"2606:4700:4700::1111"
|
|
||||||
];
|
|
||||||
|
|
||||||
hostname = config.networking.hostName;
|
hostname = config.networking.hostName;
|
||||||
|
|
||||||
|
@ -22,29 +17,21 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
domain = "fudo.org";
|
domain = "informis.land";
|
||||||
search = ["fudo.org"];
|
search = ["informis.land" "fudo.org"];
|
||||||
firewall.enable = false;
|
firewall.enable = false;
|
||||||
nameservers = nameservers;
|
|
||||||
|
|
||||||
defaultGateway = gateway;
|
defaultGateway = gateway;
|
||||||
# defaultGateway6 = gateway6;
|
# defaultGateway6 = gateway6;
|
||||||
};
|
};
|
||||||
|
|
||||||
fudo.node-exporter = {
|
fudo.node-exporter = {
|
||||||
enable = true;
|
enable = false;
|
||||||
hostname = hostname;
|
hostname = hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme.certs.${hostname} = {
|
security.acme.certs."${hostname}.informis.land" = {
|
||||||
email = "admin@fudo.org";
|
email = "admin@informis.land";
|
||||||
# plugins = [
|
|
||||||
# "fullchain.pem"
|
|
||||||
# "full.pem"
|
|
||||||
# "key.pem"
|
|
||||||
# "chain.pem"
|
|
||||||
# "cert.pem"
|
|
||||||
# ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
|
|
218
hosts/procul.nix
218
hosts/procul.nix
|
@ -3,8 +3,10 @@
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
hostname = "procul";
|
hostname = "procul";
|
||||||
|
domain = "informis.land";
|
||||||
mail-hostname = hostname;
|
mail-hostname = hostname;
|
||||||
host_ipv4 = "172.86.179.18";
|
host_ipv4 = "172.86.179.18";
|
||||||
|
host-fqdn = "${hostname}.${domain}";
|
||||||
all-hostnames = [];
|
all-hostnames = [];
|
||||||
|
|
||||||
acme-private-key = hostname: "/var/lib/acme/${hostname}/key.pem";
|
acme-private-key = hostname: "/var/lib/acme/${hostname}/key.pem";
|
||||||
|
@ -25,37 +27,20 @@ in {
|
||||||
../hardware-configuration.nix
|
../hardware-configuration.nix
|
||||||
|
|
||||||
../defaults.nix
|
../defaults.nix
|
||||||
|
|
||||||
|
../informis/users.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
fudo.common = {
|
|
||||||
# Sets some server-common settings. See /etc/nixos/fudo/profiles/...
|
|
||||||
profile = "server";
|
|
||||||
|
|
||||||
# Sets some common site-specific settings: gateway, monitoring, etc. See /etc/nixos/fudo/sites/...
|
|
||||||
site = "joes";
|
|
||||||
|
|
||||||
local-networks = [
|
|
||||||
"172.86.179.18/29"
|
|
||||||
"208.81.1.128/28"
|
|
||||||
"208.81.3.112/28"
|
|
||||||
"172.17.0.0/16"
|
|
||||||
"127.0.0.0/8"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
multipath-tools
|
multipath-tools
|
||||||
];
|
];
|
||||||
|
|
||||||
# Not all users need access to procul; don't allow LDAP-user access.
|
|
||||||
fudo.authentication.enable = false;
|
|
||||||
|
|
||||||
# TODO: not used yet
|
|
||||||
fudo.acme.hostnames = all-hostnames;
|
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = hostname;
|
hostName = hostname;
|
||||||
|
|
||||||
|
# provided by secure-dns-proxy
|
||||||
|
nameservers = [ "127.0.0.1" ];
|
||||||
|
|
||||||
dhcpcd.enable = false;
|
dhcpcd.enable = false;
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
|
|
||||||
|
@ -86,4 +71,193 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
hardware.bluetooth.enable = false;
|
hardware.bluetooth.enable = false;
|
||||||
|
|
||||||
|
users = {
|
||||||
|
users = {
|
||||||
|
gituser = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "nogroup";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fudo = {
|
||||||
|
|
||||||
|
common = {
|
||||||
|
# Sets some server-common settings. See /etc/nixos/fudo/profiles/...
|
||||||
|
profile = "server";
|
||||||
|
|
||||||
|
# Sets some common site-specific settings: gateway, monitoring, etc. See /etc/nixos/fudo/sites/...
|
||||||
|
site = "joes";
|
||||||
|
|
||||||
|
domain = domain;
|
||||||
|
|
||||||
|
admin-email = "admin@${domain}";
|
||||||
|
|
||||||
|
local-networks = [
|
||||||
|
"172.86.179.16/29"
|
||||||
|
"208.81.1.128/28"
|
||||||
|
"208.81.3.112/28"
|
||||||
|
"172.17.0.0/16"
|
||||||
|
"127.0.0.0/8"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Not all users need access to procul; don't allow LDAP-user access.
|
||||||
|
authentication.enable = false;
|
||||||
|
|
||||||
|
auth.kdc = {
|
||||||
|
enable = true;
|
||||||
|
database-path = "/var/heimdal/heimdal";
|
||||||
|
realm = "INFORMIS.LAND";
|
||||||
|
mkey-file = "/srv/heimdal/secure/m-key";
|
||||||
|
acl-file = "/etc/heimdal/kdc.acl";
|
||||||
|
bind-addresses = [
|
||||||
|
host_ipv4
|
||||||
|
"127.0.0.1"
|
||||||
|
"127.0.1.1"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
secure-dns-proxy = {
|
||||||
|
enable = true;
|
||||||
|
upstream-dns = [ "https://cloudflare-dns.com/dns-query" ];
|
||||||
|
bootstrap-dns = "1.1.1.1";
|
||||||
|
listen-ips = [ "127.0.0.1" ];
|
||||||
|
port = 53;
|
||||||
|
};
|
||||||
|
|
||||||
|
dns = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
dns-hosts = {
|
||||||
|
"ns1.informis.land" = "172.86.179.18";
|
||||||
|
"ns2.informis.land" = "172.86.179.18";
|
||||||
|
};
|
||||||
|
|
||||||
|
listen-ips = [host_ipv4];
|
||||||
|
|
||||||
|
domains = {
|
||||||
|
"informis.land" = import ../informis/informis.land.nix {
|
||||||
|
inherit host_ipv4 config;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mail-server = {
|
||||||
|
enable = true;
|
||||||
|
debug = true;
|
||||||
|
|
||||||
|
domain = domain;
|
||||||
|
hostname = "${host-fqdn}";
|
||||||
|
monitoring = false;
|
||||||
|
mail-user = "mailuser";
|
||||||
|
mail-user-id = 525;
|
||||||
|
mail-group = "mailgroup";
|
||||||
|
clamav.enable = true;
|
||||||
|
dkim.signing = true;
|
||||||
|
|
||||||
|
dovecot = {
|
||||||
|
ssl-certificate = acme-certificate "imap.${domain}";
|
||||||
|
ssl-private-key = acme-private-key "imap.${domain}";
|
||||||
|
};
|
||||||
|
|
||||||
|
postfix = {
|
||||||
|
ssl-certificate = acme-certificate "smtp.${domain}";
|
||||||
|
ssl-private-key = acme-private-key "smtp.${domain}";
|
||||||
|
};
|
||||||
|
|
||||||
|
# This should NOT include the primary domain
|
||||||
|
local-domains = [
|
||||||
|
host-fqdn
|
||||||
|
"smtp.${domain}"
|
||||||
|
];
|
||||||
|
|
||||||
|
mail-directory = "/srv/mailserver/mail";
|
||||||
|
state-directory = "/srv/mailserver/state";
|
||||||
|
|
||||||
|
trusted-networks = [
|
||||||
|
"172.86.179.16/29"
|
||||||
|
"127.0.0.0/16"
|
||||||
|
];
|
||||||
|
|
||||||
|
alias-users = {
|
||||||
|
root = ["niten"];
|
||||||
|
postmaster = ["niten"];
|
||||||
|
hostmaster = ["niten"];
|
||||||
|
webmaster = ["niten"];
|
||||||
|
system = ["niten"];
|
||||||
|
admin = ["niten"];
|
||||||
|
dmarc-report = ["niten"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ssl-certificate = (acme-certificate host-fqdn);
|
||||||
|
ssl-private-key = (acme-private-key host-fqdn);
|
||||||
|
keytab = "/srv/postgres/secure/postgres.keytab";
|
||||||
|
|
||||||
|
local-networks = [
|
||||||
|
"172.86.179.16/29"
|
||||||
|
"127.0.0.0/16"
|
||||||
|
];
|
||||||
|
|
||||||
|
users = {
|
||||||
|
gituser = {
|
||||||
|
password = fileContents "/srv/git/secure/db.passwd";
|
||||||
|
databases = {
|
||||||
|
git = "ALL PRIVILEGES";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
databases = {
|
||||||
|
git = ["niten"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
git = {
|
||||||
|
enable = true;
|
||||||
|
hostname = "git.informis.land";
|
||||||
|
site-name = "informis git";
|
||||||
|
user = "gituser";
|
||||||
|
repository-dir = /srv/git/repo;
|
||||||
|
state-dir = /srv/git/state;
|
||||||
|
database = {
|
||||||
|
user = "gituser";
|
||||||
|
password-file = /srv/git/secure/db.passwd;
|
||||||
|
hostname = "127.0.0.1";
|
||||||
|
name = "git";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
acme = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
admin-address = "admin@${domain}";
|
||||||
|
|
||||||
|
hostnames = [
|
||||||
|
"imap.informis.land"
|
||||||
|
"smtp.informis.land"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
security.acme.certs.${host-fqdn}.email = "admin@${domain}";
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
recommendedGzipSettings = true;
|
||||||
|
recommendedOptimisation = true;
|
||||||
|
recommendedTlsSettings = true;
|
||||||
|
|
||||||
|
virtualHosts = {
|
||||||
|
"${host-fqdn}" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
{ host_ipv4, config }:
|
||||||
|
|
||||||
|
{
|
||||||
|
dnssec = true;
|
||||||
|
|
||||||
|
mx = ["smtp.informis.land"];
|
||||||
|
|
||||||
|
hosts = {
|
||||||
|
procul = {
|
||||||
|
ip-addresses = [ "172.86.179.18" ];
|
||||||
|
ssh-fingerprints = [
|
||||||
|
"4 1 2a8e086d3589ce50b58c55bc35638af8da23988e"
|
||||||
|
"4 2 55a9f7c0addf08bb24c62ced954574db6e95eff38ee56d6a2cff312d20eb910e"
|
||||||
|
"1 1 d089902f60751b3d35b5329bf7b906df254d5fa7"
|
||||||
|
"1 2 8deebf42bbc40881a327f561bffd5d7bd328a4fc94d4e4ce8c502a9c6cbdfb92"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
default-host = "172.86.179.18";
|
||||||
|
|
||||||
|
srv-records = {
|
||||||
|
tcp = {
|
||||||
|
domain = [{
|
||||||
|
host = "ns1.informis.land";
|
||||||
|
port = 53;
|
||||||
|
}];
|
||||||
|
ssh = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 22;
|
||||||
|
}];
|
||||||
|
submission = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 587;
|
||||||
|
}];
|
||||||
|
kerberos = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 88;
|
||||||
|
}];
|
||||||
|
kerberos-adm = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 749;
|
||||||
|
}];
|
||||||
|
imaps = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 993;
|
||||||
|
priority = 0;
|
||||||
|
}];
|
||||||
|
pop3s = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 995;
|
||||||
|
priority = 10;
|
||||||
|
}];
|
||||||
|
http = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 80;
|
||||||
|
}];
|
||||||
|
https = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 443;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
|
udp = {
|
||||||
|
domain = [{
|
||||||
|
host = "ns1.informis.land";
|
||||||
|
port = 53;
|
||||||
|
}];
|
||||||
|
kerberos = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 88;
|
||||||
|
}];
|
||||||
|
kerberos-master = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 88;
|
||||||
|
}];
|
||||||
|
kpasswd = [{
|
||||||
|
host = "procul.informis.land";
|
||||||
|
port = 464;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
aliases = {
|
||||||
|
smtp = "procul.informis.land.";
|
||||||
|
imap = "procul.informis.land.";
|
||||||
|
gemini = "procul.informis.land.";
|
||||||
|
git = "procul.informis.land.";
|
||||||
|
};
|
||||||
|
|
||||||
|
extra-dns-records = [
|
||||||
|
''_kerberos IN TXT "INFORMIS.LAND"''
|
||||||
|
''@ IN TXT "v=spf1 mx ip4:${host_ipv4}/29 -all"''
|
||||||
|
''@ IN SPF "v=spf1 mx ip4:${host_ipv4}/29 -all"''
|
||||||
|
];
|
||||||
|
|
||||||
|
dmarc-report-address = "dmarc-report@informis.land";
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
config = {
|
||||||
|
users.users = {
|
||||||
|
viator = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "Viator";
|
||||||
|
createHome = true;
|
||||||
|
hashedPassword = "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue