Misc changes, add local-network option
This commit is contained in:
parent
5411c53022
commit
c40aba6133
|
@ -46,6 +46,8 @@ with lib; {
|
|||
./users.nix
|
||||
./vpn.nix
|
||||
./webmail.nix
|
||||
# ./wireguard.nix
|
||||
# ./wireguard-client.nix
|
||||
./wireless-networks.nix
|
||||
./zones.nix
|
||||
];
|
||||
|
|
|
@ -91,6 +91,25 @@ let
|
|||
default = null;
|
||||
};
|
||||
|
||||
wireguard = {
|
||||
gateway = mkOption {
|
||||
type = str;
|
||||
description = "Host serving as WireGuard gateway for this domain.";
|
||||
};
|
||||
|
||||
network = mkOption {
|
||||
type = str;
|
||||
description = "IP subnet used for WireGuard clients.";
|
||||
default = "172.16.0.0/16";
|
||||
};
|
||||
|
||||
routed-network = mkOption {
|
||||
type = nullOr str;
|
||||
description = "Subnet of larger network for which we NAT traffic.";
|
||||
default = "172.16.16.0/20";
|
||||
};
|
||||
};
|
||||
|
||||
gssapi-realm = mkOption {
|
||||
type = str;
|
||||
description = "GSSAPI (i.e. Kerberos) realm of this domain.";
|
||||
|
|
|
@ -150,6 +150,8 @@ in {
|
|||
|
||||
nginx = {
|
||||
enable = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
|
||||
virtualHosts = {
|
||||
"${cfg.hostname}" = {
|
||||
|
@ -158,14 +160,6 @@ in {
|
|||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.local-port}";
|
||||
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-By $server_addr:$server_port;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -220,19 +220,35 @@ in {
|
|||
};
|
||||
|
||||
extraOptions = mkIf (cfg.ldap != null) (let
|
||||
base = cfg.ldap.base-dn;
|
||||
|
||||
config-file = pkgs.writeText "grafana-ldap.toml" ''
|
||||
[[servers]]
|
||||
host = "${concatStringsSep " " cfg.ldap.hosts}"
|
||||
port = 389
|
||||
start_tls = true
|
||||
bind_dn = "${cfg.ldap.bind-dn}"
|
||||
bind_password = "''${GRAFANA_LDAP_BIND_PASSWD}"
|
||||
|
||||
bind_dn = "uid=%s,ou=members,${base}"
|
||||
|
||||
search_filter = "(uid=%s)"
|
||||
search_base_dns = [ "${cfg.ldap.base-dn}" ]
|
||||
search_base_dns = [ "ou=members,${base}" ]
|
||||
|
||||
group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))"
|
||||
group_search_base_dns = ["ou=groups,${base}"]
|
||||
group_search_filter_user_attribute = "uid"
|
||||
|
||||
[[servers.group_mappings]]
|
||||
group_dn = "cn=admin,ou=groups,${base}"
|
||||
org_role = "Admin"
|
||||
grafana_admin = true
|
||||
|
||||
[[servers.group_mappings]]
|
||||
group_dn = "cn=*,ou=groups,${base}"
|
||||
org_role = "Viewer"
|
||||
'';
|
||||
in {
|
||||
AUTH_LDAP_ENABLED = "true";
|
||||
AUTH_LDAP_ALLOW_SIGN_UP = "false";
|
||||
AUTH_LDAP_ALLOW_SIGN_UP = "true";
|
||||
AUTH_LDAP_CONFIG_FILE = config-file;
|
||||
});
|
||||
|
||||
|
|
|
@ -392,31 +392,13 @@ in {
|
|||
# olcRootDN = "cn=admin,${cfg.base}";
|
||||
# olcRootPW = FIXME; # NOTE: this should be hashed...
|
||||
olcDbDirectory = "${cfg.state-directory}/database";
|
||||
olcDbIndex = [ "objectClass eq" "uid pres,eq" ];
|
||||
olcDbIndex = [ "objectClass eq" "uid pres,eq" "memberUid eq"];
|
||||
olcAccess = makeAccess {
|
||||
"attrs=userPassword,shadowLastChange" = {
|
||||
# "dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
"dn.exact=cn=auth_reader,${cfg.base}" = "read";
|
||||
"*" = "auth";
|
||||
};
|
||||
# "dn=cn=admin,ou=groups,${cfg.base}" = {
|
||||
# # "dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
# "anonymous" = "auth";
|
||||
# "*" = "read";
|
||||
# };
|
||||
# "dn.subtree=ou=groups,${cfg.base} attrs=memberUid" = {
|
||||
# # "dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
# # "dn.regex=cn=[a-zA-Z][a-zA-Z0-9_]+,ou=hosts,${cfg.base}" = "write";
|
||||
# "anonymous" = "auth";
|
||||
# "*" = "read";
|
||||
# };
|
||||
# "dn.subtree=ou=members,${cfg.base} attrs=cn,sn,homeDirectory,loginShell,gecos,description,homeDirectory,uidNumber,gidNumber" = {
|
||||
# # "dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
# "anonymous" = "auth";
|
||||
# "*" = "read";
|
||||
# };
|
||||
"*" = {
|
||||
# "dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" = "manage";
|
||||
"anonymous" = "auth";
|
||||
"*" = "read";
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@ in rec {
|
|||
# Disable postfix on this host--it'll be run in the container instead
|
||||
services.postfix.enable = false;
|
||||
|
||||
services.nginx = mkIf cfg.monitoring {
|
||||
services.nginx = mkIf cfg.monitoring.enable {
|
||||
enable = true;
|
||||
|
||||
virtualHosts = let
|
||||
|
@ -45,7 +45,7 @@ in rec {
|
|||
forceSSL = true;
|
||||
|
||||
locations."/metrics/postfix" = {
|
||||
proxyPass = "http://127.0.0.1:9154/metrics";
|
||||
proxyPass = "http://127.0.0.1:${cfg.monitoring.postfix-listen-port}/metrics";
|
||||
|
||||
extraConfig = ''
|
||||
${proxy-headers}
|
||||
|
@ -55,7 +55,7 @@ in rec {
|
|||
};
|
||||
|
||||
locations."/metrics/dovecot" = {
|
||||
proxyPass = "http://127.0.0.1:9166/metrics";
|
||||
proxyPass = "http://127.0.0.1:${cfg.monitoring.dovecot-listen-port}/metrics";
|
||||
|
||||
extraConfig = ''
|
||||
${proxy-headers}
|
||||
|
@ -65,7 +65,7 @@ in rec {
|
|||
};
|
||||
|
||||
locations."/metrics/rspamd" = {
|
||||
proxyPass = "http://127.0.0.1:7980/metrics";
|
||||
proxyPass = "http://127.0.0.1:${cfg.monitoring.rspamd-listen-port}/metrics";
|
||||
|
||||
extraConfig = ''
|
||||
${proxy-headers}
|
||||
|
@ -178,7 +178,7 @@ in rec {
|
|||
domain = cfg.domain;
|
||||
|
||||
debug = cfg.debug;
|
||||
monitoring = cfg.monitoring;
|
||||
monitoring = cfg.monitoring.enable;
|
||||
|
||||
state-directory = container-statedir;
|
||||
mail-directory = container-maildir;
|
||||
|
|
|
@ -32,7 +32,27 @@ in {
|
|||
example = "ldaps://auth.fudo.org/";
|
||||
};
|
||||
|
||||
monitoring = mkEnableOption "Enable monitoring for the mail server.";
|
||||
monitoring = {
|
||||
enable = mkEnableOption "Enable monitoring for the mail server.";
|
||||
|
||||
dovecot-listen-port = mkOption {
|
||||
type = port;
|
||||
description = "Port on which to serve Postfix metrics.";
|
||||
default = 9166;
|
||||
};
|
||||
|
||||
postfix-listen-port = mkOption {
|
||||
type = port;
|
||||
description = "Port on which to serve Postfix metrics.";
|
||||
default = 9154;
|
||||
};
|
||||
|
||||
rspamd-listen-port = mkOption {
|
||||
type = port;
|
||||
description = "Port on which to serve Postfix metrics.";
|
||||
default = 7980;
|
||||
};
|
||||
};
|
||||
|
||||
mail-user = mkOption {
|
||||
type = str;
|
||||
|
@ -50,6 +70,7 @@ in {
|
|||
mail-user-id = mkOption {
|
||||
type = int;
|
||||
description = "UID of mail-user.";
|
||||
default = 525;
|
||||
};
|
||||
|
||||
local-domains = mkOption {
|
||||
|
|
|
@ -130,11 +130,11 @@ in {
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
services.prometheus.exporters.dovecot = mkIf cfg.monitoring {
|
||||
services.prometheus.exporters.dovecot = mkIf cfg.monitoring.enable {
|
||||
enable = true;
|
||||
scopes = ["user" "global"];
|
||||
listenAddress = "127.0.0.1";
|
||||
port = 9166;
|
||||
port = cfg.monitoring.dovecot-listen-port;
|
||||
socketPath = "/var/run/dovecot2/old-stats";
|
||||
};
|
||||
|
||||
|
@ -159,13 +159,13 @@ in {
|
|||
|
||||
sieveScripts = {
|
||||
after = builtins.toFile "spam.sieve" ''
|
||||
require "fileinto";
|
||||
require "fileinto";
|
||||
|
||||
if header :is "X-Spam" "Yes" {
|
||||
fileinto "Junk";
|
||||
stop;
|
||||
}
|
||||
'';
|
||||
if header :is "X-Spam" "Yes" {
|
||||
fileinto "Junk";
|
||||
stop;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
mailboxes = cfg.mailboxes;
|
||||
|
@ -173,7 +173,7 @@ in {
|
|||
extraConfig = ''
|
||||
#Extra Config
|
||||
|
||||
${optionalString cfg.monitoring ''
|
||||
${optionalString cfg.monitoring.enable ''
|
||||
# The prometheus exporter still expects an older style of metrics
|
||||
mail_plugins = $mail_plugins old_stats
|
||||
service old-stats {
|
||||
|
|
|
@ -97,12 +97,14 @@ in {
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
services.prometheus.exporters.postfix = mkIf cfg.monitoring {
|
||||
services.prometheus.exporters.postfix = mkIf cfg.monitoring.enable {
|
||||
enable = true;
|
||||
systemd.enable = true;
|
||||
showqPath = "/var/lib/postfix/queue/public/showq";
|
||||
user = config.services.postfix.user;
|
||||
group = config.services.postfix.group;
|
||||
port = cfg.monitoring.postfix-listen-port;
|
||||
listenAddress = "127.0.0.1";
|
||||
};
|
||||
|
||||
services.postfix = {
|
||||
|
|
|
@ -6,7 +6,11 @@ let
|
|||
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
services.prometheus.exporters.rspamd.enable = true;
|
||||
services.prometheus.exporters.rspamd = mkIf cfg.monitoring.enable {
|
||||
enable = true;
|
||||
listenAddress = "127.0.0.1";
|
||||
port = cfg.monitoring.rspamd-listen-port;
|
||||
};
|
||||
|
||||
services.rspamd = {
|
||||
|
||||
|
|
|
@ -135,9 +135,8 @@ in {
|
|||
enable = if (cfg.push-url != null) then true else false;
|
||||
web = {
|
||||
external-url = if cfg.push-url == null then
|
||||
cfg.push-address
|
||||
else
|
||||
cfg.push-url;
|
||||
cfg.push-address else
|
||||
cfg.push-url;
|
||||
listen-address = cfg.push-address;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -22,6 +22,12 @@ let
|
|||
description = "Network to be treated as local.";
|
||||
};
|
||||
|
||||
private-network = mkOption {
|
||||
type = nullOr str;
|
||||
description = "Network of the local site.";
|
||||
default = null;
|
||||
};
|
||||
|
||||
dynamic-network = mkOption {
|
||||
type = nullOr str;
|
||||
description = "Network to be allocated by DHCP.";
|
||||
|
@ -60,9 +66,6 @@ let
|
|||
default = [ ];
|
||||
};
|
||||
|
||||
enable-monitoring =
|
||||
mkEnableOption "Enable site-wide monitoring with prometheus.";
|
||||
|
||||
nameservers = mkOption {
|
||||
type = listOf str;
|
||||
description = "List of nameservers to be used by hosts at this site.";
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
|
||||
in {
|
||||
options.fudo.wireguard-client = with types; {
|
||||
enable = mkEnableOption "Enable WireGuard client on this host.";
|
||||
|
||||
server = {
|
||||
ip = {
|
||||
type = str;
|
||||
description = "IP address of the WireGuard server.";
|
||||
};
|
||||
|
||||
port = {
|
||||
type = port;
|
||||
description = "Port on which to contact WireGuard server.";
|
||||
default = 51820;
|
||||
};
|
||||
|
||||
public-key = {
|
||||
type = str;
|
||||
description = "Server public key.";
|
||||
};
|
||||
};
|
||||
|
||||
assigned-ip = mkOption {
|
||||
type = str;
|
||||
description = "IP assigned to the local host.";
|
||||
};
|
||||
|
||||
private-key-file = mkOption {
|
||||
type = str;
|
||||
description = "Path (on the host) to the host WireGuard private key.";
|
||||
};
|
||||
|
||||
listen-port = mkOption {
|
||||
type = port;
|
||||
description = "Port on which to listen for incoming connections.";
|
||||
default = 51820;
|
||||
};
|
||||
|
||||
wireguard-interface = mkOption {
|
||||
type = str;
|
||||
description = "Name of the created WireGuard interface.";
|
||||
default = "wgclient0";
|
||||
};
|
||||
|
||||
managed-subnet = mkOption {
|
||||
type = str;
|
||||
description = "Subnet to route to WireGuard. 0.0.0.0/0 will send all traffic to it.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
networking = {
|
||||
firewall.allowedUDPPorts = [ cfg.listen-port ];
|
||||
|
||||
wireguard.interfaces.${cfg.wireguard-interface} = {
|
||||
ips = [ "${cfg.assigned-ip}/32" ];
|
||||
listen-port = cfg.listen-port;
|
||||
private-key-file = cfg.private-key-file;
|
||||
peers = [{
|
||||
publicKey = cfg.server.public-key;
|
||||
allowedIPs = [ cfg.managed-subnet ];
|
||||
endpoint = "${cfg.server.ip}:${cfg.server.port}";
|
||||
persistentKeepalive = 25;
|
||||
}];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.fudo.wireguard;
|
||||
|
||||
peerOpts = { name, ... }: {
|
||||
options = {
|
||||
public-key = mkOption {
|
||||
type = str;
|
||||
description = "Peer public key.";
|
||||
};
|
||||
|
||||
assigned-ip = mkOption {
|
||||
type = str;
|
||||
description = "IP assigned to this peer.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in {
|
||||
options.fudo.wireguard = with types; {
|
||||
enable = mkEnableOption "Enable WireGuard server.";
|
||||
|
||||
network = mkOption {
|
||||
type = str;
|
||||
description = "WireGuard managed IP subnet.";
|
||||
default = "172.16.0.0/16";
|
||||
};
|
||||
|
||||
routed-network = mkOption {
|
||||
type = str;
|
||||
description = "Subnet of larger network for which we act as a gateway.";
|
||||
default = "172.16.16.0/20";
|
||||
};
|
||||
|
||||
peers = mkOption {
|
||||
type = attrsOf (submodule peerOpts);
|
||||
description = "Map of peer to peer options.";
|
||||
default = { };
|
||||
};
|
||||
|
||||
listen-port = mkOption {
|
||||
type = port;
|
||||
description = "Port on which to listen for incoming connections.";
|
||||
default = 51820;
|
||||
};
|
||||
|
||||
private-key-file = mkOption {
|
||||
type = str;
|
||||
description = "Path (on the host) to the host WireGuard private key.";
|
||||
};
|
||||
|
||||
wireguard-interface = mkOption {
|
||||
type = str;
|
||||
description = "Name of the created WireGuard interface.";
|
||||
default = "wgnet0";
|
||||
};
|
||||
|
||||
external-interface = mkOption {
|
||||
type = str;
|
||||
description = "Name of the host public-facing interface.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = all (peerOpts:
|
||||
pkgs.lib.ip.ipv4OnNetwork peerOpts.assigned-ip cfg.network)
|
||||
(attrValues cfg.peers);
|
||||
message = "Peer IPs must be on the assigned network.";
|
||||
}
|
||||
];
|
||||
|
||||
networking = {
|
||||
firewall.allowedUDPPorts = [ cfg.listen-port ];
|
||||
wireguard.interfaces.${cfg.wireguard-interface} = {
|
||||
ips = [ cfg.network ];
|
||||
listenPort = cfg.listen-port;
|
||||
postSetup =
|
||||
"${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s ${cfg.network} -o ${cfg.external-interface} -j MASQUERADE";
|
||||
postShutdown =
|
||||
"${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s ${cfg.network} -o ${cfg.external-interface} -j MASQUERADE";
|
||||
|
||||
privateKeyFile = cfg.private-key-file;
|
||||
|
||||
peers = mapAttrs (_: peerOpts: {
|
||||
public-key = peerOpts.public-key;
|
||||
allowedIPs = [ "${peerOpts.assigned-ip}/32" ];
|
||||
}) cfg.peers;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
with pkgs.lib;
|
||||
let
|
||||
get-basename = filename:
|
||||
get-basename-without-hash = filename:
|
||||
head (builtins.match "^[a-zA-Z0-9]+-(.+)$" (baseNameOf filename));
|
||||
|
||||
format-json-file = filename: pkgs.stdenv.mkDerivation {
|
||||
name = "formatted-${get-basename filename}";
|
||||
name = "formatted-${get-basename-without-hash filename}";
|
||||
phases = [ "installPhase" ];
|
||||
buildInputs = with pkgs; [ python ];
|
||||
installPhase = "python -mjson.tool ${filename} > $out";
|
||||
|
|
|
@ -264,6 +264,45 @@ in rec {
|
|||
default = false;
|
||||
};
|
||||
|
||||
wireguard = let
|
||||
clientOpts = {
|
||||
options = {
|
||||
ip = mkOption {
|
||||
type = nullOr str;
|
||||
description = "IP address assigned to this host in the WireGuard network.";
|
||||
};
|
||||
|
||||
bound = mkOption {
|
||||
type = bool;
|
||||
description = "Whether to route all traffic from this host.";
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
wireguardOpts = {
|
||||
options = {
|
||||
private-key-file = mkOption {
|
||||
type = str;
|
||||
description = "WireGuard private key file of the host.";
|
||||
};
|
||||
|
||||
public-key = mkOption {
|
||||
type = str;
|
||||
description = "WireGuard public key.";
|
||||
};
|
||||
|
||||
client = mkOption {
|
||||
type = nullOr (submodule clientOpts);
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
in mkOption {
|
||||
type = nullOr (submodule wireguardOpts);
|
||||
default = null;
|
||||
};
|
||||
|
||||
initrd-network = let
|
||||
keypair-type = { ... }: {
|
||||
options = {
|
||||
|
|
Loading…
Reference in New Issue