refactor(samba): kyuuto

This commit is contained in:
arcnmx 2024-02-09 09:03:57 -08:00
parent 602eda1012
commit 5dcd5a5be0
14 changed files with 379 additions and 125 deletions

192
modules/nixos/samba.nix Normal file
View file

@ -0,0 +1,192 @@
{
config,
lib,
pkgs,
...
}: let
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
inherit (lib.attrsets) mapAttrs' mapAttrsToList nameValuePair;
inherit (lib.strings) hasPrefix concatMapStringsSep;
inherit (config.services) samba-wsdd;
cfg = config.services.samba;
settingValue = value:
if builtins.isList value then concatMapStringsSep ", " settingValue value
else if value == true then "yes"
else if value == false then "no"
else toString value;
in {
options.services.samba = with lib.types; let
settingPrimitive = oneOf [ str int bool ];
settingType = oneOf [ settingPrimitive (listOf settingPrimitive) ];
in {
ldap = {
enable = mkEnableOption "LDAP";
idmapDomain = mkOption {
type = str;
default = "*";
};
url = mkOption {
type = str;
};
baseDn = mkOption {
type = str;
};
adminDn = mkOption {
type = str;
default = "name=anonymous,${cfg.ldap.baseDn}";
};
adminPasswordPath = mkOption {
type = nullOr path;
default = null;
};
};
usershare = {
enable = mkEnableOption "usershare";
group = mkOption {
type = str;
default = "users";
};
path = mkOption {
type = path;
default = "/var/lib/samba/usershares";
};
templateShare = mkOption {
type = str;
default = "usershare-template";
};
};
idmap = let
idmapModule = { config, name, ... }: {
options = {
backend = mkOption {
type = str;
};
domain = mkOption {
type = str;
default = name;
};
range = {
min = mkOption {
type = int;
default = 1000;
};
max = mkOption {
type = int;
default = 10000;
};
};
readOnly = mkOption {
type = bool;
default = true;
};
settings = mkOption {
type = attrsOf settingType;
default = { };
};
};
config = {
settings = {
backend = mkOptionDefault config.backend;
"read only" = mkOptionDefault config.readOnly;
range = mkOptionDefault "${toString config.range.min} - ${toString config.range.max}";
};
};
};
in {
domains = mkOption {
type = attrsOf (submodule idmapModule);
default = {
nss = {
backend = "nss";
domain = "*";
};
};
};
};
passdb.smbpasswd.path = mkOption {
type = nullOr path;
default = null;
};
settings = mkOption {
type = attrsOf settingType;
default = { };
};
};
config = {
services.samba = {
package = mkIf cfg.ldap.enable (mkDefault (pkgs.samba.override {
enableLDAP = true;
}));
ldap = {
adminPasswordPath = mkIf (hasPrefix "name=anonymous," cfg.ldap.adminDn) (mkDefault (
pkgs.writeText "smb-ldap-anonymous" "anonymous"
));
};
idmap.domains = mkMerge [
(mkIf cfg.ldap.enable {
ldap = {
domain = mkDefault cfg.ldap.idmapDomain;
};
})
];
settings = mkMerge ([
(mkIf (cfg.passdb.smbpasswd.path != null) {
"passdb backend" = "smbpasswd:${cfg.passdb.smbpasswd.path}";
})
(mkIf cfg.ldap.enable {
"passdb backend" = mkOptionDefault ''ldapsam:"${cfg.ldap.url}"'';
"ldap ssl" = mkIf (hasPrefix "ldaps://" cfg.ldap.url) (mkOptionDefault "off");
"ldap admin dn" = mkOptionDefault "name=anonymous,${cfg.ldap.baseDn}";
"ldap suffix" = mkOptionDefault cfg.ldap.baseDn;
})
(mkIf (cfg.ldap.enable && true) {
"ntlm auth" = mkOptionDefault "disabled";
"encrypt passwords" = mkOptionDefault false;
})
(mkIf cfg.usershare.enable {
"usershare allow guests" = mkOptionDefault true;
"usershare max shares" = mkOptionDefault 16;
"usershare owner only" = mkOptionDefault true;
"usershare template share" = mkOptionDefault cfg.usershare.templateShare;
"usershare path" = mkOptionDefault cfg.usershare.path;
"usershare prefix allow list" = mkOptionDefault [ cfg.usershare.path ];
})
] ++ mapAttrsToList (_: idmap: mapAttrs' (key: value: nameValuePair "idmap config ${idmap.domain} : ${key}" (mkOptionDefault value)) idmap.settings) cfg.idmap.domains);
extraConfig = mkMerge (mapAttrsToList (key: value: ''${key} = ${settingValue value}'') cfg.settings);
shares.${cfg.usershare.templateShare} = mkIf cfg.usershare.enable {
"-valid" = false;
};
};
systemd.services.samba-smbd = mkIf cfg.enable {
serviceConfig = let
ldap-pass = pkgs.writeShellScript "samba-ldap-pass" ''
${cfg.package}/bin/smbpasswd -c /etc/samba/smb.conf -w $(cat ${cfg.ldap.adminPasswordPath})
'';
in {
ExecStartPre = mkMerge [
(mkIf (cfg.ldap.enable && cfg.ldap.adminPasswordPath != null) [
"${ldap-pass}"
])
];
};
};
systemd.tmpfiles.rules = mkIf (cfg.enable && cfg.usershare.enable) [
"d ${cfg.usershare.path} 1770 root ${cfg.usershare.group}"
];
networking.firewall.interfaces.local = {
allowedTCPPorts = mkMerge [
(mkIf (cfg.enable && !cfg.openFirewall) [ 139 445 ])
(mkIf (samba-wsdd.enable && !samba-wsdd.openFirewall) [ 5357 ])
];
allowedUDPPorts = mkMerge [
(mkIf (cfg.enable && !cfg.openFirewall) [ 137 138 ])
(mkIf (samba-wsdd.enable && !samba-wsdd.openFirewall) [ 3702 ])
];
};
};
}

View file

@ -8,4 +8,5 @@ in {
enable = mkDefault true;
listenPort = mkDefault 6767;
};
users.users.bazarr.extraGroups = [ "kyuuto" ];
}

View file

@ -57,4 +57,7 @@ in {
download
(mkIf (completedDir != null && !hasCompletedSubdir) completed)
]);
users.users.deluge = mkIf cfg.enable {
extraGroups = [ "kyuuto" ];
};
}

62
nixos/kyuuto/mount.nix Normal file
View file

@ -0,0 +1,62 @@
{
config,
lib,
...
}: let
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge;
cfg = config.kyuuto;
in {
options.kyuuto = with lib.types; {
setup = mkEnableOption "directory and permission setup";
mountDir = mkOption {
type = path;
default = "/mnt/kyuuto-media";
};
libraryDir = mkOption {
type = path;
default = cfg.mountDir + "/library";
};
transferDir = mkOption {
type = path;
default = cfg.mountDir + "/transfer";
};
};
config = {
systemd.tmpfiles.rules = mkIf cfg.setup [
"d ${cfg.transferDir} 3775 root kyuuto"
"d ${cfg.libraryDir} 3775 root kyuuto"
"d ${cfg.libraryDir}/unsorted 3775 root kyuuto"
"d ${cfg.libraryDir}/music 7775 sonarr kyuuto"
"d ${cfg.libraryDir}/anime 7775 sonarr kyuuto"
"d ${cfg.libraryDir}/tv 7775 sonarr kyuuto"
"d ${cfg.libraryDir}/movies 7775 radarr kyuuto"
];
users = let
mapId = id: if config.proxmoxLXC.privileged or true then 100000 + id else id;
mkDummyUsers = {
name,
group ? name,
enable ? !config.services.${serviceName}.enable, serviceName ? name,
uid ? config.ids.uids.${name},
gid ? config.ids.gids.${group}
}: mkIf enable {
users.${name} = {
group = mkIf (group != null) group;
uid = mapId uid;
isSystemUser = true;
};
groups.${group} = {
gid = mapId gid;
};
};
in mkMerge [
(mkDummyUsers { name = "deluge"; })
(mkDummyUsers { name = "radarr"; })
(mkDummyUsers { name = "sonarr"; })
(mkDummyUsers { name = "lidarr"; })
];
};
}

26
nixos/kyuuto/nfs.nix Normal file
View file

@ -0,0 +1,26 @@
{
config,
lib,
...
}: let
inherit (lib.lists) optionals;
inherit (lib.strings) concatStringsSep;
inherit (config.networking.access) cidrForNetwork;
inherit (config) kyuuto;
in {
services.nfs.server.exports = let
mapPerm = perm: map (addr: "${addr}(${perm})");
toPerms = concatStringsSep " ";
localAddrs = cidrForNetwork.loopback.all ++ cidrForNetwork.local.all;
tailAddrs = optionals config.services.tailscale.enable cidrForNetwork.tail.all;
allAddrs = localAddrs ++ tailAddrs;
kyuutoPerms =
mapPerm "ro" localAddrs
++ mapPerm "rw" tailAddrs;
transferPerms = mapPerm "rw" allAddrs;
in ''
${kyuuto.mountDir} ${toPerms kyuutoPerms}
${kyuuto.transferDir} ${toPerms transferPerms}
'';
}

49
nixos/kyuuto/samba.nix Normal file
View file

@ -0,0 +1,49 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkDefault;
inherit (lib.lists) optionals;
inherit (config.networking.access) cidrForNetwork;
inherit (config) kyuuto;
cfg = config.services.samba;
localAddrs = cidrForNetwork.loopback.all ++ cidrForNetwork.local.all
++ optionals config.services.tailscale.enable cidrForNetwork.tail.all;
in {
services.samba = {
usershare = {
enable = mkDefault true;
path = mkDefault (kyuuto.mountDir + "/usershares");
};
shares = mkIf cfg.enable {
kyuuto-transfer = {
path = kyuuto.transferDir;
writeable = true;
browseable = true;
public = true;
"acl group control" = true;
#"guest only" = true;
comment = "Kyuuto Media Transfer Area";
"hosts allow" = localAddrs;
};
kyuuto-access = {
path = kyuuto.libraryDir;
writeable = false;
browseable = true;
public = true;
comment = "Kyuuto Media Access";
"hosts allow" = localAddrs;
};
kyuuto-media = {
path = kyuuto.mountDir;
writeable = true;
browseable = true;
public = false;
comment = "Kyuuto Media";
"valid users" = [ "@kyuuto" ];
};
};
};
}

View file

@ -2,4 +2,5 @@ _: {
services.lidarr = {
enable = true;
};
users.users.lidarr.extraGroups = [ "kyuuto" ];
}

View file

@ -2,4 +2,6 @@ _: {
services.radarr = {
enable = true;
};
users.users.radarr.extraGroups = [ "kyuuto" ];
}

View file

@ -2,4 +2,5 @@ _: {
services.readarr = {
enable = true;
};
users.users.readarr.extraGroups = [ "kyuuto" ];
}

View file

@ -7,7 +7,7 @@
}: let
inherit (lib.modules) mkIf mkMerge mkDefault;
inherit (lib.lists) any;
inherit (lib.strings) hasInfix;
inherit (lib.strings) hasInfix concatMapStringsSep splitString;
inherit (config.services) samba samba-wsdd;
system = access.systemFor "tei";
inherit (system.services) kanidm;
@ -19,55 +19,29 @@ in {
enableWinbindd = mkDefault false;
enableNmbd = mkDefault hasIpv4;
securityType = mkDefault "user";
package = mkIf enableLdap (mkDefault (pkgs.samba.override {
enableLDAP = true;
}));
extraConfig = mkMerge [
''
workgroup = GENSOKYO
local master = no
preferred master = no
winbind offline logon = yes
winbind scan trusted domains = no
winbind use default domain = yes
domain master = no
valid users = nobody, arc, kat, @nfs
map to guest = Bad User
guest account = nobody
''
(mkIf hasIpv4 ''
remote announce = 10.1.1.255/GENSOKYO
'')
(mkIf enableLdap ''
idmap config * : backend = ldap
idmap config * : range = 1000 - 2000
idmap config * : read only = yes
idmap config * : ldap_url = ldaps://ldap.local.${config.networking.domain}
idmap config * : ldap_base_dn = ${kanidm.server.ldap.baseDn}
passdb backend = ldapsam:"ldaps://ldap.local.${config.networking.domain}"
ldap ssl = off
ldap admin dn = name=anonymous,${kanidm.server.ldap.baseDn}
ldap suffix = ${kanidm.server.ldap.baseDn}
ntlm auth = disabled
encrypt passwords = no
'')
(mkIf (!enableLdap) ''
passdb backend = smbpasswd:${config.sops.secrets.smbpasswd.path}
idmap config * : backend = nss
idmap config * : range = 1000 - 2000
idmap config * : read only = yes
'')
ldap = {
url = mkDefault "ldaps://ldap.local.${config.networking.domain}";
baseDn = mkDefault (concatMapStringsSep "," (part: "dc=${part}") (splitString "." config.networking.domain));
};
usershare = {
group = mkDefault "peeps";
};
passdb.smbpasswd.path = mkDefault config.sops.secrets.smbpasswd.path;
settings = {
workgroup = "GENSOKYO";
"local master" = false;
"preferred master" = false;
"winbind offline logon" = true;
"winbind scan trusted domains" = false;
"winbind use default domain" = true;
"domain master" = false;
"valid users" = [ "nobody" "@peeps" ];
"map to guest" = "Bad User";
"guest account" = "nobody";
"remote announce" = mkIf hasIpv4 [
"10.1.1.255/${samba.settings.workgroup}"
];
};
systemd.services.samba-smbd = mkIf samba.enable {
serviceConfig.ExecStartPre = let
ldap-pass = pkgs.writeShellScript "smb-ldap-pass" ''
${samba.package}/bin/smbpasswd -c /etc/samba/smb.conf -w anonymous
'';
in mkIf enableLdap [
"${ldap-pass}"
];
};
services.samba-wsdd = mkIf samba.enable {
@ -75,17 +49,6 @@ in {
hostname = mkDefault config.networking.hostName;
};
networking.firewall.interfaces.local = {
allowedTCPPorts = mkMerge [
(mkIf samba.enable [ 139 445 ])
(mkIf samba-wsdd.enable [ 5357 ])
];
allowedUDPPorts = mkMerge [
(mkIf samba.enable [ 137 138 ])
(mkIf samba-wsdd.enable [ 3702 ])
];
};
sops.secrets.smbpasswd = {
sopsFile = mkDefault ./secrets/samba.yaml;
#path = "/var/lib/samba/private/smbpasswd";

View file

@ -2,4 +2,5 @@ _: {
services.sonarr = {
enable = true;
};
users.users.sonarr.extraGroups = [ "kyuuto" ];
}

View file

@ -9,13 +9,12 @@
inherit (lib.attrsets) mapAttrs mapAttrsToList;
inherit (lib.strings) removePrefix;
inherit (config.services) deluge plex tautulli ombi sonarr radarr bazarr lidarr readarr prowlarr cloudflared;
kyuuto = "/mnt/kyuuto-media";
kyuuto-library = kyuuto + "/library";
inherit (config) kyuuto;
plexLibrary = {
"/mnt/Anime".hostPath = kyuuto-library + "/anime";
"/mnt/Shows".hostPath = kyuuto-library + "/tv";
"/mnt/Movies".hostPath = kyuuto-library + "/movies";
"/mnt/Music".hostPath = kyuuto-library + "/music";
"/mnt/Anime".hostPath = kyuuto.libraryDir + "/anime";
"/mnt/Shows".hostPath = kyuuto.libraryDir + "/tv";
"/mnt/Movies".hostPath = kyuuto.libraryDir + "/movies";
"/mnt/Music".hostPath = kyuuto.libraryDir + "/music";
};
in {
imports = let
@ -29,6 +28,7 @@ in {
./cloudflared.nix
# media
nixos.kyuuto
nixos.plex
nixos.tautulli
nixos.ombi
@ -48,16 +48,16 @@ in {
serverName = "tewi";
mediaDirectories = let
mkLibraryDir = dir: {
path = kyuuto-library + "/${dir}";
mountPoint = kyuuto-library;
path = kyuuto.libraryDir + "/${dir}";
mountPoint = kyuuto.libraryDir;
};
libraryDir = {
path = kyuuto-library;
mountPoint = kyuuto-library;
path = kyuuto.libraryDir;
mountPoint = kyuuto.libraryDir;
subdirectories =
mapAttrsToList (
_: {hostPath, ...}:
removePrefix "${kyuuto-library}/" hostPath
removePrefix "${kyuuto.libraryDir}/" hostPath
)
plexLibrary
++ ["tlmc" "music-raw"];
@ -88,7 +88,7 @@ in {
"${deluge.downloadDir}" = mkIf deluge.enable (mkMerge [
bind
{
device = kyuuto + "/downloads/deluge/download";
device = kyuuto.mountDir + "/downloads/deluge/download";
}
]);
};

View file

@ -1,51 +0,0 @@
{
config,
lib,
...
}: let
kyuuto = "/mnt/kyuuto-media";
kyuuto-transfer = kyuuto + "/transfer";
inherit (lib.lists) optionals;
inherit (lib.strings) concatStringsSep;
inherit (config.networking.access) cidrForNetwork;
in {
services.nfs.server.exports = let
mapPerm = perm: map (addr: "${addr}(${perm})");
toPerms = concatStringsSep " ";
localAddrs = cidrForNetwork.loopback.all ++ cidrForNetwork.local.all;
tailAddrs = optionals config.services.tailscale.enable cidrForNetwork.tail.all;
allAddrs = localAddrs ++ tailAddrs;
kyuutoPerms =
mapPerm "ro" localAddrs
++ mapPerm "rw" tailAddrs;
transferPerms = mapPerm "rw" allAddrs;
in ''
${kyuuto} ${toPerms kyuutoPerms}
${kyuuto-transfer} ${toPerms transferPerms}
'';
services.samba.shares = {
kyuuto-transfer = {
path = kyuuto-transfer;
writeable = "yes";
browseable = "yes";
public = "yes";
"guest only" = "yes";
comment = "Kyuuto Media Transfer Area";
};
kyuuto-access = {
path = kyuuto;
writeable = false;
browseable = "yes";
public = "yes";
comment = "Kyuuto Media Access";
};
kyuuto-media = {
path = kyuuto;
writeable = "yes";
browseable = "yes";
public = "no";
comment = "Kyuuto Media";
};
};
}

View file

@ -8,12 +8,16 @@
nixos.sops
nixos.base
nixos.reisen-ct
nixos.kyuuto
nixos.tailscale
nixos.nfs
nixos.samba
./nfs.nix
];
kyuuto.setup = true;
proxmoxLXC.privileged = true;
systemd.network.networks.eth0 = {
name = "eth0";
matchConfig = {