259 lines
8.5 KiB
Nix
259 lines
8.5 KiB
Nix
{ lib, ... }:
|
|
{
|
|
_class = "clan.service";
|
|
manifest.name = "samba";
|
|
manifest.description = "Samba configuration for NAS";
|
|
manifest.readme = "Samba configuration for NAS";
|
|
manifest.categories = [ "System" ];
|
|
|
|
roles.server = {
|
|
description = "A server role that host files";
|
|
|
|
interface =
|
|
{ lib, ... }:
|
|
let
|
|
userOptions = {
|
|
readPerm = lib.mkOption {
|
|
type = with lib.types; bool;
|
|
description = "Permission to read";
|
|
default = false;
|
|
};
|
|
writePerm = lib.mkOption {
|
|
type = with lib.types; bool;
|
|
description = "Permission to write";
|
|
default = false;
|
|
};
|
|
};
|
|
in
|
|
{
|
|
options = {
|
|
|
|
globalUsers = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
attrsOf (submodule {
|
|
options = userOptions;
|
|
});
|
|
description = "List of global users with permissions, this will be applied to all the folders.";
|
|
default = {
|
|
admin = {
|
|
readPerm = true;
|
|
writePerm = true;
|
|
};
|
|
};
|
|
};
|
|
|
|
sharedFolders = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
attrsOf (submodule {
|
|
options = {
|
|
users = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
attrsOf (submodule {
|
|
options = userOptions;
|
|
});
|
|
description = "List of users with permissions, this will only applied to this particular folder.";
|
|
default = { };
|
|
};
|
|
allowedGuest = lib.mkOption {
|
|
type = with lib.types; bool;
|
|
description = "Whether to allow guest access to this folder.";
|
|
default = false;
|
|
};
|
|
};
|
|
});
|
|
description = "List of folders with users permissions.";
|
|
default = [
|
|
{
|
|
name = "DEFAULT";
|
|
}
|
|
];
|
|
|
|
};
|
|
|
|
dataDir = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
oneOf [
|
|
str
|
|
path
|
|
];
|
|
description = "A directory where all samba folders will be.";
|
|
};
|
|
|
|
};
|
|
};
|
|
perInstance =
|
|
{ settings, ... }:
|
|
let
|
|
allUsernameList = lib.uniqueStrings (
|
|
lib.flatten (
|
|
(lib.mapAttrsToList (name: share: builtins.attrNames share.users) settings.sharedFolders)
|
|
++ builtins.attrNames settings.globalUsers
|
|
)
|
|
);
|
|
in
|
|
{
|
|
nixosModule =
|
|
{
|
|
lib,
|
|
config,
|
|
pkgs,
|
|
...
|
|
}:
|
|
{
|
|
|
|
users.users = builtins.listToAttrs (
|
|
map (
|
|
username:
|
|
lib.nameValuePair username {
|
|
isSystemUser = true;
|
|
group = username;
|
|
}
|
|
) (allUsernameList ++ builtins.attrNames settings.sharedFolders)
|
|
);
|
|
|
|
users.groups = builtins.listToAttrs (
|
|
map (username: lib.nameValuePair username { }) (
|
|
allUsernameList ++ builtins.attrNames settings.sharedFolders
|
|
)
|
|
);
|
|
|
|
clan.core.vars.generators = builtins.listToAttrs (
|
|
map (
|
|
username:
|
|
lib.nameValuePair "${username}-smb-password" {
|
|
files.password = { };
|
|
runtimeInputs = with pkgs; [
|
|
coreutils
|
|
xkcdpass
|
|
mkpasswd
|
|
];
|
|
script = ''
|
|
xkcdpass --numwords 3 --delimiter - --count 1 > $out/password
|
|
'';
|
|
}
|
|
) allUsernameList
|
|
);
|
|
|
|
systemd.services.samba-smbd.postStart =
|
|
lib.concatMapStrings (
|
|
user:
|
|
let
|
|
passwordPath = config.clan.core.vars.generators."${user}-smb-password".files.password.path;
|
|
userDir = "${settings.dataDir}/${user}";
|
|
in
|
|
''
|
|
mkdir -p ${userDir}
|
|
chown ${user}:users ${userDir}
|
|
# if a password is unchanged, this will error
|
|
(echo $(<${passwordPath}); echo $(<${passwordPath})) | ${config.services.samba.package}/bin/smbpasswd -s -a ${user}
|
|
''
|
|
) allUsernameList
|
|
+ lib.concatMapStrings (
|
|
share:
|
|
let
|
|
shareDir = "${settings.dataDir}/${share}";
|
|
in
|
|
''
|
|
mkdir -p ${shareDir}
|
|
chown ${share}:${share} ${shareDir}
|
|
''
|
|
) (builtins.attrNames settings.sharedFolders);
|
|
|
|
services.samba = {
|
|
enable = true;
|
|
openFirewall = true;
|
|
settings = {
|
|
global = {
|
|
security = "user";
|
|
workgroup = "WORKGROUP";
|
|
"server string" = "WhiteHouse NAS";
|
|
"max log size" = "50";
|
|
"dns proxy" = false;
|
|
"syslog only" = true;
|
|
"map to guest" = "Bad User";
|
|
"guest account" = "nobody";
|
|
};
|
|
}
|
|
// lib.mapAttrs (
|
|
shareName: value:
|
|
{
|
|
path = "${settings.dataDir}/${shareName}";
|
|
comment = shareName;
|
|
"force user" = shareName;
|
|
"force group" = shareName;
|
|
"create mask" = "0640";
|
|
"directory mask" = "0750";
|
|
"read only" = "yes";
|
|
browseable = "yes";
|
|
printable = "no";
|
|
"read list" = lib.concatStringsSep " " (
|
|
lib.uniqueStrings (
|
|
lib.flatten (
|
|
(builtins.attrNames (lib.filterAttrs (n: v: v.readPerm) value.users))
|
|
++ (builtins.attrNames (lib.filterAttrs (n: v: v.readPerm) settings.globalUsers))
|
|
)
|
|
)
|
|
);
|
|
"write list" = lib.concatStringsSep " " (
|
|
lib.uniqueStrings (
|
|
lib.flatten (
|
|
(builtins.attrNames (lib.filterAttrs (n: v: v.writePerm) value.users))
|
|
++ (builtins.attrNames (lib.filterAttrs (n: v: v.writePerm) settings.globalUsers))
|
|
)
|
|
)
|
|
);
|
|
"valid users" = lib.concatStringsSep " " (
|
|
lib.uniqueStrings (
|
|
lib.flatten ((builtins.attrNames (value.users)) ++ (builtins.attrNames (settings.globalUsers)))
|
|
)
|
|
);
|
|
}
|
|
// lib.optionalAttrs (value.allowedGuest) {
|
|
public = "yes";
|
|
"guest ok" = "yes";
|
|
}
|
|
) settings.sharedFolders
|
|
// builtins.listToAttrs (
|
|
map (
|
|
user:
|
|
lib.nameValuePair user {
|
|
comment = user;
|
|
path = "${settings.dataDir}/${user}";
|
|
"force user" = user;
|
|
"force group" = "users";
|
|
public = "yes";
|
|
"guest ok" = "no";
|
|
"create mask" = "0640";
|
|
"directory mask" = "0750";
|
|
writable = "yes";
|
|
browseable = "yes";
|
|
printable = "no";
|
|
"valid users" = user;
|
|
}
|
|
) allUsernameList
|
|
);
|
|
};
|
|
|
|
services.samba-wsdd = {
|
|
enable = true;
|
|
openFirewall = true;
|
|
};
|
|
|
|
services.avahi = {
|
|
publish.enable = true;
|
|
publish.userServices = true;
|
|
# ^^ Needed to allow samba to automatically register mDNS records (without the need for an `extraServiceFile`
|
|
nssmdns4 = true;
|
|
# ^^ Not one hundred percent sure if this is needed- if it aint broke, don't fix it
|
|
enable = true;
|
|
openFirewall = true;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|