Lots of updates

This commit is contained in:
Niten 2021-03-25 16:40:45 +00:00
parent 8d9f4e247d
commit e2558f6f0f
13 changed files with 311 additions and 175 deletions

View File

@ -12,16 +12,16 @@ let
in { in {
system = { system = {
# Don't do unsupervised upgrades... # Don't do unsupervised upgrades...
autoUpgrade.enable = mkForce false; # autoUpgrade.enable = mkForce false;
# DO force all DNS traffic to use the local server # # DO force all DNS traffic to use the local server
activationScripts.force-local-dns = let # activationScripts.force-local-dns = let
wifi-ip = # wifi-ip =
config.fudo.networks."rus.selby.ca".hosts.google-wifi.ipv4-address; # config.fudo.networks."rus.selby.ca".hosts.google-wifi.ipv4-address;
in '' # in ''
${pkgs.iptables}/bin/iptables -t nat -A OUTPUT -p udp -s ${wifi-ip} --dport 53 -j DNAT --to ${primary-ip}:53 # ${pkgs.iptables}/bin/iptables -t nat -A OUTPUT -p udp -s ${wifi-ip} --dport 53 -j DNAT --to ${primary-ip}:53
${pkgs.iptables}/bin/iptables -t nat -A OUTPUT -p tcp -s ${wifi-ip} --dport 53 -j DNAT --to ${primary-ip}:53 # ${pkgs.iptables}/bin/iptables -t nat -A OUTPUT -p tcp -s ${wifi-ip} --dport 53 -j DNAT --to ${primary-ip}:53
''; # '';
}; };
fudo.local-network = let fudo.local-network = let
@ -77,6 +77,11 @@ in {
enable = true; enable = true;
externalInterface = "enp1s0"; externalInterface = "enp1s0";
internalInterfaces = [ "intif0" ]; internalInterfaces = [ "intif0" ];
forwardPorts = [{
destination = "127.0.0.1:53";
sourcePort = 53;
proto = "udp";
}];
}; };
}; };
@ -89,7 +94,7 @@ in {
auth.kdc = { auth.kdc = {
enable = true; enable = true;
realm = "RUS.SELBY.CA"; realm = "RUS.SELBY.CA";
bind-addresses = [ "10.0.0.1" "127.0.0.1" "[::1]" ]; bind-addresses = [ "10.0.0.1" "127.0.0.1" "::1" ];
acl = { acl = {
"niten" = { perms = [ "add" "change-password" "list" ]; }; "niten" = { perms = [ "add" "change-password" "list" ]; };
"*/root" = { perms = [ "all" ]; }; "*/root" = { perms = [ "all" ]; };

View File

@ -12,6 +12,8 @@ in {
boot.tmpOnTmpfs = true; boot.tmpOnTmpfs = true;
system.autoUpgrade.enable = true;
services.xserver = mkIf enable-gui { services.xserver = mkIf enable-gui {
enable = true; enable = true;

View File

@ -3,7 +3,7 @@
with lib; with lib;
let let
# Available to all users on the system. Keep it minimal. # Available to all users on the system. Keep it minimal.
global-packages = with pkgs; [ bind git openssh_gssapi vim wget ]; global-packages = with pkgs; [ bind git heimdal openssh_gssapi vim wget ];
in { in {
environment = { environment = {
@ -20,8 +20,6 @@ in {
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
security.acme.acceptTerms = true; security.acme.acceptTerms = true;
system.autoUpgrade.enable = true;
krb5 = { krb5 = {
enable = true; enable = true;
@ -59,6 +57,16 @@ in {
}; };
}; };
lshd = {
enable = true;
portNumber = 2112;
rootLogin = true;
srpKeyExchange = true;
tcpForwarding = false;
publicKeyAuthentication = true;
passwordAuthentication = false;
};
fail2ban = { fail2ban = {
enable = true; enable = true;
bantime-increment.enable = true; bantime-increment.enable = true;
@ -74,6 +82,14 @@ in {
# udev.packages = with pkgs; [ yubikey-personalization ]; # udev.packages = with pkgs; [ yubikey-personalization ];
}; };
networking.firewall = {
# Allow mosh connections if the firewall is enabled
allowedUDPPortRanges = [{
from = 60000;
to = 60100;
}];
};
console.useXkbConfig = true; console.useXkbConfig = true;
i18n.defaultLocale = "en_US.UTF-8"; i18n.defaultLocale = "en_US.UTF-8";

View File

@ -59,6 +59,8 @@ in {
# noXlibs = lib.mkForce true; # noXlibs = lib.mkForce true;
}; };
system.autoUpgrade.enable = false;
security = { hideProcessInformation = true; }; security = { hideProcessInformation = true; };
networking.networkmanager.enable = mkForce false; networking.networkmanager.enable = mkForce false;

View File

@ -16,12 +16,13 @@
home-manager-config = home-manager-config =
import ../home-manager/niten.nix { inherit config lib pkgs; }; import ../home-manager/niten.nix { inherit config lib pkgs; };
k5login = [ k5login = [
"niten@FUDO.ORG"
"niten/root@FUDO.ORG" "niten/root@FUDO.ORG"
"niten/admin@FUDO.ORG" "niten/admin@FUDO.ORG"
"niten@INFORMIS.LAND" "niten@INFORMIS.LAND"
"niten/root@INFORMIS.LAND" "niten/root@INFORMIS.LAND"
"niten/admin@INFORMIS.LAND" "niten/admin@INFORMIS.LAND"
"niten@RUS.SELBY.CA"
"niten/root@RUS.SELBY.CA"
]; ];
}; };

View File

@ -88,14 +88,14 @@ in {
onChange = "${pkgs.doomEmacsInit}/bin/doom-emacs-init.sh"; onChange = "${pkgs.doomEmacsInit}/bin/doom-emacs-init.sh";
}; };
".k5login" = { # ".k5login" = {
source = pkgs.writeText "niten-k5login" '' # source = pkgs.writeText "niten-k5login" ''
niten@FUDO.ORG # niten@FUDO.ORG
niten/root@FUDO.ORG # niten/root@FUDO.ORG
niten@INFORMIS.LAND # niten@INFORMIS.LAND
niten/root@INFORMIS.LAND # niten/root@INFORMIS.LAND
''; # '';
}; # };
}; };
sessionVariables = { sessionVariables = {

View File

@ -27,6 +27,7 @@ in {
source = pkgs.writeText "niten-k5login" '' source = pkgs.writeText "niten-k5login" ''
niten/root@FUDO.ORG niten/root@FUDO.ORG
niten/root@INFORMIS.LAND niten/root@INFORMIS.LAND
reaper/root@FUDO.ORG
''; '';
}; };
}; };

View File

@ -36,6 +36,7 @@ with lib; {
./fudo/sites.nix ./fudo/sites.nix
./fudo/slynk.nix ./fudo/slynk.nix
./fudo/system.nix ./fudo/system.nix
./fudo/system-networking.nix
./fudo/users.nix ./fudo/users.nix
./fudo/vpn.nix ./fudo/vpn.nix
./fudo/webmail.nix ./fudo/webmail.nix

View File

@ -28,7 +28,7 @@ let
(get-domain-hosts (toLower realm)))); (get-domain-hosts (toLower realm))));
initialize-db = initialize-db =
realm: user: group: kdc-conf: key-file: db-name: max-lifetime: max-renewal: primary-keytab: kadmin-keytab: local-hostname: realm: user: group: kdc-conf: key-file: db-name: max-lifetime: max-renewal: primary-keytab: kadmin-keytab: kpasswd-keytab: local-hostname:
pkgs.writeShellScript "initialize-kdc-db.sh" '' pkgs.writeShellScript "initialize-kdc-db.sh" ''
if [ ! -e ${key-file} ]; then if [ ! -e ${key-file} ]; then
${pkgs.heimdalFull}/bin/kstash --key-file=${key-file} --random-key ${pkgs.heimdalFull}/bin/kstash --key-file=${key-file} --random-key
@ -36,6 +36,8 @@ let
${add-hosts-principals realm kdc-conf} ${add-hosts-principals realm kdc-conf}
${pkgs.heimdalFull}/bin/kadmin -l -c ${kdc-conf} -- ext_keytab --keytab=${primary-keytab} */${local-hostname}@${realm} ${pkgs.heimdalFull}/bin/kadmin -l -c ${kdc-conf} -- ext_keytab --keytab=${primary-keytab} */${local-hostname}@${realm}
${pkgs.heimdalFull}/bin/kadmin -l -c ${kdc-conf} -- ext_keytab --keytab=${kadmin-keytab} kadmin/admin@${realm} ${pkgs.heimdalFull}/bin/kadmin -l -c ${kdc-conf} -- ext_keytab --keytab=${kadmin-keytab} kadmin/admin@${realm}
${pkgs.heimdalFull}/bin/kadmin -l -c ${kdc-conf} -- ext_keytab --keytab=${kpasswd-keytab} kadmin/changepw@${realm}
${pkgs.heimdalFull}/bin/kadmin -l -c ${kdc-conf} -- ext_keytab --keytab=${kpasswd-keytab} kadmin/changepw@${realm}
#${pkgs.coreutils}/bin/chown ${user}:${group} ${key-file} #${pkgs.coreutils}/bin/chown ${user}:${group} ${key-file}
#${pkgs.coreutils}/bin/chown ${user}:${group} ${db-name} #${pkgs.coreutils}/bin/chown ${user}:${group} ${db-name}
#${pkgs.coreutils}/bin/chown ${user}:${group} ${iprop-log} #${pkgs.coreutils}/bin/chown ${user}:${group} ${iprop-log}
@ -61,7 +63,8 @@ let
} }
[logging] [logging]
default = SYSLOG kdc = FILE:/var/kerberos/kerberos.log
default = FILE:/var/kerberos/kerberos.log
''; '';
aclEntry = { principal, ... }: { aclEntry = { principal, ... }: {
@ -168,6 +171,12 @@ in {
default = "/var/kerberos/kadmind.keytab"; default = "/var/kerberos/kadmind.keytab";
}; };
kpasswdd-keytab = mkOption {
type = str;
description = "Location of keytab for kpasswdd.";
default = "/var/kerberos/kpasswdd.keytab";
};
kdc-internal-port = mkOption { kdc-internal-port = mkOption {
type = port; type = port;
description = description =
@ -175,12 +184,12 @@ in {
default = 4088; default = 4088;
}; };
k5login-directory = mkOption { # k5login-directory = mkOption {
type = str; # type = str;
description = # description =
"Directory in which k5login files are stored for local users (equivalent to ~/.k5login)."; # "Directory in which k5login files are stored for local users (equivalent to ~/.k5login).";
default = "/var/kerberos/k5login"; # default = "/var/kerberos/k5login";
}; # };
max-ticket-lifetime = mkOption { max-ticket-lifetime = mkOption {
type = str; type = str;
@ -208,13 +217,14 @@ in {
krb5 = { krb5 = {
libdefaults = { libdefaults = {
k5login_directory = cfg.k5login-directory; # Stick to ~/.k5login
# k5login_directory = cfg.k5login-directory;
ticket_lifetime = cfg.max-ticket-lifetime; ticket_lifetime = cfg.max-ticket-lifetime;
renew_lifetime = cfg.max-ticket-renewal; renew_lifetime = cfg.max-ticket-renewal;
}; };
realms = { ${cfg.realm} = { enable-http = false; }; }; realms = { ${cfg.realm} = { enable-http = false; }; };
extraConfig = '' extraConfig = ''
default = SYSLOG default = FILE:/var/kerberos/kerberos.log
''; '';
}; };
@ -232,42 +242,41 @@ in {
}; };
}; };
internal-port-map = {
kdc = {
internal-port = cfg.kdc-internal-port;
external-port = 88;
protocols = [ "tcp" "udp" ];
};
};
services = { services = {
heimdal-kdc = { heimdal-kdc = let
listen-addrs = concatStringsSep " "
(map (addr: "--addresses=${addr}") cfg.bind-addresses);
command =
"${pkgs.heimdalFull}/libexec/heimdal/kdc -c ${kdc-conf} --ports=88 ${listen-addrs}";
in {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" ]; after = [ "network.target" ];
description = description =
"Heimdal Kerberos Key Distribution Center (ticket server)."; "Heimdal Kerberos Key Distribution Center (ticket server).";
execStart = execStart = command;
"${pkgs.heimdalFull}/libexec/heimdal/kdc -c ${kdc-conf} --ports=${
toString cfg.kdc-internal-port
} --addresses=127.0.0.1";
environment = { KRB5_CONFIG = "/etc/krb5.conf"; };
user = cfg.user; user = cfg.user;
group = cfg.group; group = cfg.group;
workingDirectory = cfg.state-directory; workingDirectory = cfg.state-directory;
privateNetwork = false; privateNetwork = false;
addressFamilies = [ "AF_INET" "AF_INET6" ]; addressFamilies = [ "AF_INET" "AF_INET6" ];
requiredCapabilities = [ "CAP_NET_BIND_SERVICE" ];
environment = { KRB5_CONFIG = "/etc/krb5.conf"; };
}; };
heimdal-kdc-init = { heimdal-kdc-init = {
requires = [ "heimdal-kdc.service" ]; requires = [ "heimdal-kdc.service" ];
wantedBy = [ "multi-user.target" ];
description = "Initialization script for Heimdal KDC."; description = "Initialization script for Heimdal KDC.";
type = "oneshot"; type = "oneshot";
execStart = "${initialize-db cfg.realm cfg.user cfg.group kdc-conf execStart = "${initialize-db cfg.realm cfg.user cfg.group kdc-conf
cfg.master-key-file database-file cfg.max-ticket-lifetime cfg.master-key-file database-file cfg.max-ticket-lifetime
cfg.max-ticket-renewal cfg.primary-keytab cfg.kadmin-keytab cfg.max-ticket-renewal cfg.primary-keytab cfg.kadmin-keytab
cfg.kpasswdd-keytab
"${config.networking.hostName}.${toLower cfg.realm}"}"; "${config.networking.hostName}.${toLower cfg.realm}"}";
user = cfg.user; user = cfg.user;
group = cfg.group; group = cfg.group;
protectSystem = "full";
addressFamilies = [ "AF_INET" "AF_INET6" ];
workingDirectory = cfg.state-directory; workingDirectory = cfg.state-directory;
environment = { KRB5_CONFIG = "/etc/krb5.conf"; }; environment = { KRB5_CONFIG = "/etc/krb5.conf"; };
}; };
@ -295,7 +304,7 @@ in {
server = "${pkgs.heimdalFull}/libexec/heimdal/kpasswdd"; server = "${pkgs.heimdalFull}/libexec/heimdal/kpasswdd";
protocol = "udp"; protocol = "udp";
serverArgs = serverArgs =
"--config-file=${kdc-conf} --keytab=${cfg.kadmin-keytab}"; "--config-file=${kdc-conf} --keytab=${cfg.kpasswdd-keytab}";
} }
]; ];
}; };

View File

@ -308,10 +308,36 @@ in {
systemd.services.openldap = { systemd.services.openldap = {
environment = { KRB5_KTNAME = cfg.kerberos-keytab; }; environment = { KRB5_KTNAME = cfg.kerberos-keytab; };
# FIXME: THIS IS ALL UNPROVEN
serviceConfig = {
PrivateDevices = true;
PrivateTmp = true;
PrivateMounts = true;
ProtectControlGroups = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectSystem = true;
ProtectHostname = true;
ProtectHome = true;
ProtectClock = true;
ProtectKernelLogs = true;
KeyringMode = "private";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
Restart = "on-failure";
LockPersonality = true;
RestrictRealtime = true;
MemoryDenyWriteExecute = true;
SystemCallFilter =
"~@clock @debug @module @mount @raw-io @reboot @swap @privileged @resources @cpu-emulation @obsolete";
UMask = "7007";
InaccessiblePaths = [ "/home" "/root" ];
LimitNOFILE = 49152;
PermissionsStartOnly = true;
};
}; };
services.openldap = { services.openldap = {
enable = true; enable = true;
suffix = cfg.base; suffix = cfg.base;
rootdn = "cn=admin,${cfg.base}"; rootdn = "cn=admin,${cfg.base}";

View File

@ -0,0 +1,158 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.fudo.system;
portMappingOpts = { name, ... }: {
options = with types; {
internal-port = mkOption {
type = port;
description = "Port on localhost to recieve traffic";
};
external-port = mkOption {
type = port;
description = "External port on which to listen for traffic.";
};
protocols = mkOption {
type = listOf str;
description =
"Protocols for which to forward ports. Default is tcp-only.";
default = [ "tcp" ];
};
};
};
in {
options.fudo.system = with types; {
internal-port-map = mkOption {
type = attrsOf (submodule portMappingOpts);
description =
"Sets of external ports to internal (i.e. localhost) ports to forward.";
default = { };
example = {
sshmap = {
internal-port = 2222;
external-port = 22;
protocol = "udp";
};
};
};
};
config = mkIf (cfg.internal-port-map != { }) {
# FIXME: FUCK ME THIS IS WAY HARDER THAN IT SHOULD BE
# boot.kernel.sysctl = mkIf (cfg.internal-port-map != { }) {
# "net.ipv4.conf.all.route_localnet" = "1";
# };
# fudo.system.services.forward-internal-ports = let
# ip-line = op: src-port: target-port: protocol: ''
# ${ipt} -t nat -${op} PREROUTING -p ${protocol} --dport ${
# toString src-port
# } -j REDIRECT --to-ports ${toString target-port}
# ${ipt} -t nat -${op} OUTPUT -p ${protocol} -s lo --dport ${
# toString src-port
# } -j REDIRECT --to-ports ${toString target-port}
# '';
# ip-forward-line = ip-line "I";
# ip-unforward-line = ip-line "D";
# traceOut = obj: builtins.trace obj obj;
# concatMapAttrsToList = f: attrs: concatLists (mapAttrsToList f attrs);
# portmap-entries = concatMapAttrsToList (name: opts:
# map (protocol: {
# src = opts.external-port;
# target = opts.internal-port;
# protocol = protocol;
# }) opts.protocols) cfg.internal-port-map;
# make-entries = f: { src, target, protocol, ... }: f src target protocol;
# forward-entries = map (make-entries ip-forward-line) portmap-entries;
# unforward-entries = map (make-entries ip-unforward-line) portmap-entries;
# forward-ports-script = pkgs.writeShellScript "forward-internal-ports.sh"
# (concatStringsSep "\n" forward-entries);
# unforward-ports-script =
# pkgs.writeShellScript "unforward-internal-ports.sh"
# (concatStringsSep "\n"
# (map (make-entries ip-unforward-line) portmap-entries));
# in {
# wantedBy = [ "multi-user.target" ];
# after = [ "firewall.service" "nat.service" ];
# type = "oneshot";
# description = "Rules for forwarding external ports to local ports.";
# execStart = "${forward-ports-script}";
# execStop = "${unforward-ports-script}";
# requiredCapabilities =
# [ "CAP_DAC_READ_SEARCH" "CAP_NET_ADMIN" "CAP_NET_RAW" ];
# };
# networking.firewall = let
# iptables = "ip46tables";
# ip-forward-line = protocols: internal: external:
# concatStringsSep "\n" (map (protocol: ''
# ${iptables} -t nat -I PREROUTING -p ${protocol} --dport ${
# toString external
# } -j REDIRECT --to-ports ${toString internal}
# ${iptables} -t nat -I OUTPUT -s lo -p ${protocol} --dport ${
# toString external
# } -j REDIRECT --to-ports ${toString internal}
# '') protocols);
# ip-unforward-line = protocols: internal: external:
# concatStringsSep "\n" (map (protocol: ''
# ${iptables} -t nat -D PREROUTING -p ${protocol} --dport ${
# toString external
# } -j REDIRECT --to-ports ${toString internal}
# ${iptables} -t nat -D OUTPUT -s lo -p ${protocol} --dport ${
# toString external
# } -j REDIRECT --to-ports ${toString internal}
# '') protocols);
# in {
# enable = true;
# extraCommands = concatStringsSep "\n" (mapAttrsToList (name: opts:
# ip-forward-line opts.protocols opts.internal-port opts.external-port)
# cfg.internal-port-map);
# extraStopCommands = concatStringsSep "\n" (mapAttrsToList (name: opts:
# ip-unforward-line opts.protocols opts.internal-port opts.external-port)
# cfg.internal-port-map);
# };
# networking.nat.forwardPorts =
# let portmaps = (attrValues opts.external-port);
# in concatMap (opts:
# map (protocol: {
# destination = "127.0.0.1:${toString opts.internal-port}";
# sourcePort = opts.external-port;
# proto = protocol;
# }) opts.protocols) (attrValues cfg.internal-port-map);
# services.xinetd = mkIf ((length (attrNames cfg.internal-port-map)) > 0) {
# enable = true;
# services = let
# svcs = mapAttrsToList (name: opts: opts // { name = name; })
# cfg.internal-port-map;
# svcs-protocols = concatMap
# (svc: map (protocol: svc // { protocol = protocol; }) svc.protocols)
# svcs;
# in map (opts: {
# name = opts.name;
# unlisted = true;
# port = opts.external-port;
# server = "${pkgs.coreutils}/bin/false";
# extraConfig = "redirect = localhost ${toString opts.internal-port}";
# protocol = opts.protocol;
# }) svcs-protocols;
# };
};
}

View File

@ -154,6 +154,11 @@ let
default = null; default = null;
description = "Command to run to launch the service."; description = "Command to run to launch the service.";
}; };
execStop = mkOption {
type = nullOr str;
default = null;
description = "Command to run to launch the service.";
};
protectSystem = mkOption { protectSystem = mkOption {
type = enum [ "true" "false" "full" "strict" true false ]; type = enum [ "true" "false" "full" "strict" true false ];
default = "full"; default = "full";
@ -355,10 +360,7 @@ let
concatStringsSep " " allowed; concatStringsSep " " allowed;
restrict-address-families = allowed: restrict-address-families = allowed:
if (allowed == [ ]) then if (allowed == [ ]) then [ "~AF_INET" "~AF_INET6" ] else allowed;
"~${concatStringsSep " " address-families}"
else
concatStringsSep " " allowed;
dirOpts = { path, ... }: { dirOpts = { path, ... }: {
options = with types; { options = with types; {
@ -380,25 +382,6 @@ let
}; };
}; };
portMappingOpts = { name, ... }: {
options = with types; {
internal-port = mkOption {
type = port;
description = "Port on localhost to recieve traffic";
};
external-port = mkOption {
type = port;
description = "External port on which to listen for traffic.";
};
protocols = mkOption {
type = listOf str;
description =
"Protocols for which to forward ports. Default is tcp-only.";
default = [ "tcp" ];
};
};
};
in { in {
options.fudo.system = with types; { options.fudo.system = with types; {
services = mkOption { services = mkOption {
@ -418,86 +401,9 @@ in {
description = "A map of required directories to directory properties."; description = "A map of required directories to directory properties.";
default = { }; default = { };
}; };
internal-port-map = mkOption {
type = attrsOf (submodule portMappingOpts);
description =
"Sets of external ports to internal (i.e. localhost) ports to forward.";
default = { };
example = {
sshmap = {
internal-port = 2222;
external-port = 22;
protocol = "udp";
};
};
};
}; };
config = { config = {
boot.kernel.sysctl = mkIf (cfg.internal-port-map != { }) {
"net.ipv4.conf.all.route_localnet" = "1";
};
# networking.firewall = let
# iptables = "ip46tables";
# ip-forward-line = protocols: internal: external:
# concatStringsSep "\n" (map (protocol: ''
# ${iptables} -t nat -I PREROUTING -p ${protocol} --dport ${
# toString external
# } -j REDIRECT --to-ports ${toString internal}
# ${iptables} -t nat -I OUTPUT -s lo -p ${protocol} --dport ${
# toString external
# } -j REDIRECT --to-ports ${toString internal}
# '') protocols);
# ip-unforward-line = protocols: internal: external:
# concatStringsSep "\n" (map (protocol: ''
# ${iptables} -t nat -D PREROUTING -p ${protocol} --dport ${
# toString external
# } -j REDIRECT --to-ports ${toString internal}
# ${iptables} -t nat -D OUTPUT -s lo -p ${protocol} --dport ${
# toString external
# } -j REDIRECT --to-ports ${toString internal}
# '') protocols);
# in {
# enable = true;
# extraCommands = concatStringsSep "\n" (mapAttrsToList (name: opts:
# ip-forward-line opts.protocols opts.internal-port opts.external-port)
# cfg.internal-port-map);
# extraStopCommands = concatStringsSep "\n" (mapAttrsToList (name: opts:
# ip-unforward-line opts.protocols opts.internal-port opts.external-port)
# cfg.internal-port-map);
# };
networking.nat.forwardPorts =
let portmaps = (attrValues opts.external-port);
in concatMap (opts:
map (protocol: {
destination = "127.0.0.1:${toString opts.internal-port}";
sourcePort = opts.external-port;
proto = protocol;
}) opts.protocols) (attrValues cfg.internal-port-map);
# Services.xinetd = mkIf ((length (attrNames cfg.internal-port-map)) > 0) {
# enable = true;
# services = let
# svcs = mapAttrsToList (name: opts: opts // { name = name; })
# cfg.internal-port-map;
# svcs-protocols = concatMap
# (svc: map (protocol: svc // { protocol = protocol; }) svc.protocols)
# svcs;
# in map (opts: {
# name = opts.name;
# unlisted = true;
# port = opts.external-port;
# server = "${pkgs.coreutils}/bin/false";
# extraConfig = "redirect = localhost ${toString opts.internal-port}";
# protocol = opts.protocol;
# }) svcs-protocols;
# };
systemd.timers = mapAttrs (name: opts: { systemd.timers = mapAttrs (name: opts: {
enable = true; enable = true;
@ -533,7 +439,7 @@ in {
path = opts.path; path = opts.path;
serviceConfig = { serviceConfig = {
PrivateNetwork = opts.privateNetwork; PrivateNetwork = opts.privateNetwork;
PrivateUsers = opts.privateUsers; PrivateUsers = mkIf (opts.user == null) opts.privateUsers;
PrivateDevices = opts.privateDevices; PrivateDevices = opts.privateDevices;
PrivateTmp = opts.privateTmp; PrivateTmp = opts.privateTmp;
PrivateMounts = opts.privateMounts; PrivateMounts = opts.privateMounts;
@ -546,11 +452,12 @@ in {
ProtectClock = opts.protectClock; ProtectClock = opts.protectClock;
ProtectKernelLogs = opts.protectKernelLogs; ProtectKernelLogs = opts.protectKernelLogs;
KeyringMode = opts.keyringMode; KeyringMode = opts.keyringMode;
EnvironmentFile = opts.environment-file; EnvironmentFile =
mkIf (opts.environment-file != null) opts.environment-file;
# This is more complicated than it looks... # This is more complicated than it looks...
CapabilityBoundingSet = restrict-capabilities opts.requiredCapabilities; # CapabilityBoundingSet = restrict-capabilities opts.requiredCapabilities;
Capabilities = opts.requiredCapabilities; AmbientCapabilities = concatStringsSep " " opts.requiredCapabilities;
SecureBits = mkIf ((length opts.requiredCapabilities) > 0) "keep-caps"; SecureBits = mkIf ((length opts.requiredCapabilities) > 0) "keep-caps";
DynamicUser = mkIf (opts.user == null) opts.dynamicUser; DynamicUser = mkIf (opts.user == null) opts.dynamicUser;
@ -568,6 +475,7 @@ in {
LockPersonality = opts.lockPersonality; LockPersonality = opts.lockPersonality;
RestrictRealtime = opts.restrictRealtime; RestrictRealtime = opts.restrictRealtime;
ExecStart = mkIf (opts.execStart != null) opts.execStart; ExecStart = mkIf (opts.execStart != null) opts.execStart;
ExecStop = mkIf (opts.execStop != null) opts.execStop;
MemoryDenyWriteExecute = opts.memoryDenyWriteExecute; MemoryDenyWriteExecute = opts.memoryDenyWriteExecute;
SystemCallFilter = restrict-syscalls opts.allowedSyscalls; SystemCallFilter = restrict-syscalls opts.allowedSyscalls;
UMask = opts.maximumUmask; UMask = opts.maximumUmask;

View File

@ -3,20 +3,20 @@
with lib; with lib;
let let
systemUserOpts = { username, ... }: { systemUserOpts = { username, ... }: {
options = { options = with types; {
username = mkOption { username = mkOption {
type = types.str; type = str;
description = "The system user's login name."; description = "The system user's login name.";
default = username; default = username;
}; };
description = mkOption { description = mkOption {
type = types.str; type = str;
description = "Description of this system user's purpose or role"; description = "Description of this system user's purpose or role";
}; };
ldap-hashed-password = mkOption { ldap-hashed-password = mkOption {
type = types.str; type = str;
description = description =
"LDAP-formatted hashed password for this user. Generate with slappasswd."; "LDAP-formatted hashed password for this user. Generate with slappasswd.";
}; };
@ -24,67 +24,67 @@ let
}; };
userOpts = { username, ... }: { userOpts = { username, ... }: {
options = { options = with types; {
username = mkOption { username = mkOption {
type = types.str; type = str;
description = "The user's login name."; description = "The user's login name.";
default = username; default = username;
}; };
uid = mkOption { uid = mkOption {
type = types.int; type = int;
description = "Unique UID number for the user."; description = "Unique UID number for the user.";
}; };
common-name = mkOption { common-name = mkOption {
type = types.str; type = str;
description = "The user's common or given name."; description = "The user's common or given name.";
}; };
primary-group = mkOption { primary-group = mkOption {
type = types.str; type = str;
description = "Primary group to which the user belongs."; description = "Primary group to which the user belongs.";
}; };
login-shell = mkOption { login-shell = mkOption {
type = with types; nullOr shellPackage; type = nullOr shellPackage;
description = "The user's preferred shell."; description = "The user's preferred shell.";
}; };
description = mkOption { description = mkOption {
type = types.str; type = str;
default = "Fudo Member"; default = "Fudo Member";
description = "A description of this user's role."; description = "A description of this user's role.";
}; };
ldap-hashed-passwd = mkOption { ldap-hashed-passwd = mkOption {
type = with types; nullOr str; type = nullOr str;
description = description =
"LDAP-formatted hashed password, used for email and other services. Use slappasswd to generate the properly-formatted password."; "LDAP-formatted hashed password, used for email and other services. Use slappasswd to generate the properly-formatted password.";
default = null; default = null;
}; };
login-hashed-passwd = mkOption { login-hashed-passwd = mkOption {
type = with types; nullOr str; type = nullOr str;
description = description =
"Hashed password for shell, used for shell access to hosts. Use mkpasswd to generate the properly-formatted password."; "Hashed password for shell, used for shell access to hosts. Use mkpasswd to generate the properly-formatted password.";
default = null; default = null;
}; };
ssh-authorized-keys = mkOption { ssh-authorized-keys = mkOption {
type = with types; listOf str; type = listOf str;
description = "SSH public keys this user can use to log in."; description = "SSH public keys this user can use to log in.";
default = [ ]; default = [ ];
}; };
home-manager-config = mkOption { home-manager-config = mkOption {
type = with types; nullOr attrs; type = nullOr attrs;
description = "Home Manager configuration for the given user."; description = "Home Manager configuration for the given user.";
default = null; default = null;
}; };
home-directory = mkOption { home-directory = mkOption {
type = with types; nullOr str; type = nullOr str;
description = "Default home directory for the given user."; description = "Default home directory for the given user.";
default = null; default = null;
}; };
@ -98,26 +98,26 @@ let
}; };
groupOpts = { group-name, ... }: { groupOpts = { group-name, ... }: {
options = { options = with types; {
group-name = mkOption { group-name = mkOption {
type = with types; nullOr str; type = nullOr str;
default = group-name; default = group-name;
description = "Group name."; description = "Group name.";
}; };
description = mkOption { description = mkOption {
type = types.str; type = str;
description = "Description of the group or it's purpose."; description = "Description of the group or it's purpose.";
}; };
members = mkOption { members = mkOption {
type = with types; listOf str; type = listOf str;
default = [ ]; default = [ ];
description = "A list of users who are members of the current group."; description = "A list of users who are members of the current group.";
}; };
gid = mkOption { gid = mkOption {
type = types.int; type = int;
description = "GID number of the group."; description = "GID number of the group.";
}; };
}; };
@ -225,8 +225,15 @@ in {
home-manager-users = home-manager-users =
filterAttrs (username: userOpts: userOpts.home-manager-config != null) filterAttrs (username: userOpts: userOpts.home-manager-config != null)
local-users; local-users;
common-user-config = username: {
in mapAttrs (username: userOpts: userOpts.home-manager-config) home.file.".k5login" = {
source = pkgs.writeText "${username}-k5login" ''
${concatStringsSep "\n" config.fudo.users.${username}.k5login}
'';
};
};
in mapAttrs (username: userOpts:
userOpts.home-manager-config // (common-user-config username))
home-manager-users; home-manager-users;
}; };
} }