forked from mirrors_public/oddlama_nix-config
391 lines
12 KiB
Nix
391 lines
12 KiB
Nix
{
|
|
config,
|
|
globals,
|
|
lib,
|
|
...
|
|
}:
|
|
let
|
|
smbUsers = config.repo.secrets.local.samba.users;
|
|
smbGroups = config.repo.secrets.local.samba.groups;
|
|
|
|
mkPersistent = persistRoot: directory: owner: {
|
|
${persistRoot}.directories = [
|
|
{
|
|
inherit directory;
|
|
user = owner;
|
|
group = owner;
|
|
mode = "0750";
|
|
}
|
|
];
|
|
};
|
|
|
|
mkShare = id: path: cfg: {
|
|
${id} = {
|
|
inherit path;
|
|
public = "no";
|
|
writable = "yes";
|
|
"create mask" = "0740";
|
|
"directory mask" = "0750";
|
|
"acl allow execute always" = "yes";
|
|
}
|
|
// cfg;
|
|
};
|
|
|
|
mkGroupShares =
|
|
group:
|
|
{
|
|
enableBunker ? false,
|
|
...
|
|
}:
|
|
[
|
|
(mkShare group "/shares/groups/${group}" {
|
|
"valid users" = "@${group}";
|
|
"force user" = group;
|
|
"force group" = group;
|
|
})
|
|
]
|
|
++ lib.optional enableBunker (
|
|
mkShare "${group}-bunker" "/shares/groups/${group}-bunker" {
|
|
"valid users" = "@${group}";
|
|
"force user" = group;
|
|
"force group" = group;
|
|
}
|
|
);
|
|
|
|
mkUserShares =
|
|
user:
|
|
{
|
|
enableBunker ? false,
|
|
enablePaperless ? false,
|
|
...
|
|
}:
|
|
[
|
|
(mkShare user "/shares/users/${user}" {
|
|
"valid users" = user;
|
|
})
|
|
]
|
|
++ lib.optional enableBunker (
|
|
mkShare "${user}-bunker" "/shares/users/${user}-bunker" {
|
|
"valid users" = user;
|
|
}
|
|
)
|
|
++ lib.optional enablePaperless (
|
|
mkShare "${user}-paperless" "/shares/users/${user}-paperless" {
|
|
"valid users" = user;
|
|
"force user" = "paperless";
|
|
"force group" = "paperless";
|
|
}
|
|
);
|
|
in
|
|
{
|
|
age.secrets."samba-passdb.tdb" = {
|
|
rekeyFile = config.node.secretsDir + "/samba-passdb.tdb.age";
|
|
mode = "600";
|
|
};
|
|
|
|
services.openssh = {
|
|
# You really have to hate them. Thanks Brother ADS-4300N.
|
|
settings = {
|
|
Macs = [ "hmac-sha2-512" ];
|
|
HostkeyAlgorithms = "+ssh-rsa";
|
|
PubkeyAcceptedAlgorithms = "+ssh-rsa";
|
|
};
|
|
# We need an RSA key for network attached printers and scanners
|
|
# that fucking can't be bothered to support sensible stuff
|
|
hostKeys = [
|
|
{
|
|
bits = 4096;
|
|
path = "/etc/ssh/ssh_host_rsa_key";
|
|
type = "rsa";
|
|
}
|
|
];
|
|
|
|
# Allow SFTP for scanner in /shares/groups/scanner
|
|
extraConfig = ''
|
|
Match User scanner
|
|
ForceCommand internal-sftp
|
|
AllowTcpForwarding no
|
|
PermitTunnel no
|
|
'';
|
|
};
|
|
|
|
environment.persistence = lib.mkMerge (
|
|
[
|
|
{
|
|
"/persist".files = [
|
|
"/etc/ssh/ssh_host_rsa_key"
|
|
"/etc/ssh/ssh_host_rsa_key.pub"
|
|
];
|
|
}
|
|
]
|
|
++ lib.flatten (
|
|
lib.flip lib.mapAttrsToList smbUsers (
|
|
name:
|
|
{
|
|
enableBunker ? false,
|
|
...
|
|
}:
|
|
[ (mkPersistent "/storage" "/shares/users/${name}" name) ]
|
|
++ lib.optional enableBunker (mkPersistent "/bunker" "/shares/users/${name}-bunker" name)
|
|
)
|
|
++ lib.flip lib.mapAttrsToList smbGroups (
|
|
name:
|
|
{
|
|
enableBunker ? false,
|
|
...
|
|
}:
|
|
[ (mkPersistent "/storage" "/shares/groups/${name}" name) ]
|
|
++ lib.optional enableBunker (mkPersistent "/bunker" "/shares/groups/${name}-bunker" name)
|
|
)
|
|
)
|
|
);
|
|
|
|
services.samba-wsdd = {
|
|
enable = true;
|
|
openFirewall = true;
|
|
};
|
|
|
|
globals.monitoring.tcp.samba = {
|
|
host = globals.net.home-lan.vlans.services.hosts.sire-samba.ipv4;
|
|
port = 445;
|
|
network = "home-lan.vlans.services";
|
|
};
|
|
|
|
services.samba = {
|
|
enable = true;
|
|
openFirewall = true;
|
|
|
|
# Disable Samba's nmbd, because we don't want to reply to NetBIOS over IP
|
|
# requests, since all of our clients hardcode the server shares.
|
|
nmbd.enable = false;
|
|
# Disable Samba's winbindd, which provides a number of services to the Name
|
|
# Service Switch capability found in most modern C libraries, to arbitrary
|
|
# applications via PAM and ntlm_auth and to Samba itself.
|
|
winbindd.enable = false;
|
|
settings = lib.mkMerge (
|
|
[
|
|
{
|
|
global = {
|
|
# Show the server host name in the printer comment box in print manager
|
|
# and next to the IPC connection in net view.
|
|
"server string" = "SambaOelig";
|
|
# Set the NetBIOS name by which the Samba server is known.
|
|
"netbios name" = "SambaOelig";
|
|
# Disable netbios support. We don't need to support browsing since all
|
|
# clients hardcode the host and share names.
|
|
"disable netbios" = "yes";
|
|
# Deny access to all hosts by default.
|
|
"hosts deny" = "0.0.0.0/0";
|
|
# Allow access to local network and TODO: wireguard
|
|
"hosts allow" = lib.concatStringsSep " " [
|
|
globals.net.home-lan.vlans.home.cidrv4
|
|
globals.net.home-lan.vlans.home.cidrv6
|
|
];
|
|
# Don't advertise inaccessible shares to users
|
|
"access based share enum" = "yes";
|
|
|
|
# Set sane logging options
|
|
"log level" = "0 auth:2 passdb:2";
|
|
"log file" = "/dev/null";
|
|
"max log size" = "0";
|
|
"logging" = "systemd";
|
|
|
|
# TODO: allow based on wireguard ip without username and password
|
|
# Users always have to login with an account and are never mapped
|
|
# to a guest account.
|
|
"passdb backend" = "tdbsam:${config.age.secrets."samba-passdb.tdb".path}";
|
|
"server role" = "standalone";
|
|
"guest account" = "nobody";
|
|
"map to guest" = "never";
|
|
|
|
# Clients should only connect using the latest SMB3 protocol (e.g., on
|
|
# clients running Windows 8 and later).
|
|
"server min protocol" = "SMB3_11";
|
|
# Require native SMB transport encryption by default.
|
|
"server smb encrypt" = "required";
|
|
|
|
# Never map anything to the excutable bit.
|
|
"map archive" = "no";
|
|
"map system" = "no";
|
|
"map hidden" = "no";
|
|
|
|
# Disable printer sharing. By default Samba shares printers configured
|
|
# using CUPS.
|
|
"load printers" = "no";
|
|
"printing" = "bsd";
|
|
"printcap name" = "/dev/null";
|
|
"disable spoolss" = "yes";
|
|
"show add printer wizard" = "no";
|
|
|
|
# Load in modules (order is critical!) and enable AAPL extensions.
|
|
"vfs objects" = "catia fruit streams_xattr";
|
|
# Enable Apple's SMB2+ extension.
|
|
"fruit:aapl" = "yes";
|
|
# Clean up unused or empty files created by the OS or Samba.
|
|
"fruit:wipe_intentionally_left_blank_rfork" = "yes";
|
|
"fruit:delete_empty_adfiles" = "yes";
|
|
};
|
|
}
|
|
]
|
|
++ lib.flatten (
|
|
lib.mapAttrsToList mkUserShares smbUsers ++ lib.mapAttrsToList mkGroupShares smbGroups
|
|
)
|
|
);
|
|
};
|
|
|
|
systemd.tmpfiles.settings = lib.mkMerge (
|
|
# Make sure the main paperless structure exists
|
|
[
|
|
{
|
|
"10-smb-paperless" = {
|
|
"/paperless/consume".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0750";
|
|
};
|
|
"/paperless/media".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0750";
|
|
};
|
|
"/paperless/media/documents".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0750";
|
|
};
|
|
"/paperless/media/documents/archive".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0750";
|
|
};
|
|
"/paperless/media/documents/originals".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0750";
|
|
};
|
|
};
|
|
}
|
|
]
|
|
# For each paperless share, make sure the necessary sub-folders for that user are created
|
|
# at boot so we can bind-mount them into the shares.
|
|
++ lib.flatten (
|
|
lib.flip lib.mapAttrsToList smbUsers (
|
|
user: userCfg:
|
|
lib.optional (userCfg.enablePaperless or false) {
|
|
"10-smb-paperless" = {
|
|
"/shares/users/${user}-paperless".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0550";
|
|
};
|
|
"/paperless/consume/${user}".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0750";
|
|
};
|
|
"/paperless/media/documents/archive/${user}".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0750";
|
|
};
|
|
# A .keep file prevents paperless from removing this folder if no documents are present
|
|
"/paperless/media/documents/archive/${user}/.keep".f = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0640";
|
|
};
|
|
"/paperless/media/documents/originals/${user}".d = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0750";
|
|
};
|
|
# A .keep file prevents paperless from removing this folder if no documents are present
|
|
"/paperless/media/documents/originals/${user}/.keep".f = {
|
|
user = "paperless";
|
|
group = "paperless";
|
|
mode = "0640";
|
|
};
|
|
};
|
|
}
|
|
)
|
|
)
|
|
);
|
|
|
|
# For each paperless share, bind-mount create the necessary folders using tmpfiles.
|
|
fileSystems = lib.mkMerge (
|
|
[
|
|
{
|
|
"/storage".neededForBoot = true;
|
|
"/bunker".neededForBoot = true;
|
|
}
|
|
]
|
|
++ lib.flip lib.mapAttrsToList smbUsers (
|
|
user: userCfg:
|
|
lib.optionalAttrs (userCfg.enablePaperless or false) {
|
|
"/shares/users/${user}-paperless/consume" = {
|
|
fsType = "none";
|
|
options = [ "bind" ];
|
|
device = "/paperless/consume/${user}";
|
|
};
|
|
"/shares/users/${user}-paperless/documents" = {
|
|
fsType = "none";
|
|
options = [
|
|
"bind"
|
|
"ro"
|
|
];
|
|
device = "/paperless/media/documents/archive/${user}";
|
|
};
|
|
"/shares/users/${user}-paperless/originals" = {
|
|
fsType = "none";
|
|
options = [
|
|
"bind"
|
|
"ro"
|
|
];
|
|
device = "/paperless/media/documents/originals/${user}";
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
users.users =
|
|
let
|
|
mkUser = name: id: groups: {
|
|
isNormalUser = true;
|
|
uid = id;
|
|
group = name;
|
|
extraGroups = groups;
|
|
createHome = false;
|
|
home = "/var/empty";
|
|
useDefaultShell = false;
|
|
autoSubUidGidRange = false;
|
|
};
|
|
in
|
|
lib.mkMerge [
|
|
(
|
|
{ }
|
|
// lib.mapAttrs (name: cfg: mkUser name cfg.id cfg.groups) smbUsers
|
|
// lib.mapAttrs (name: cfg: mkUser name cfg.id [ ]) smbGroups
|
|
)
|
|
{
|
|
scanner.openssh.authorizedKeys.keys = [
|
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJcWkqM2gXM9MJoKggCMpXLBJvgPP0fuoIO3UNy4h4uFzyDqMKAADjaJHCqyIQPq/s5vATVmuu4GQyajkc7Y3fBg/2rvAACzFx/2ufK2M4dkdDcYOX6kyNZL7XiJRmLfUR2cqda3P3bQxapkdfIOWfPQQJUAnYlVvUaIShoBxYw5HXRTr2jR5UAklfIRWZOmx07WKC6dZG5MIm1Luun5KgvqQmzQ9ErL5tz/Oi5pPdK30kdkS5WdeWD6KwL78Ff4KfC0DVTO0zb/C7WyKk4ZLu+UKCLHXDTzE4lhBAu6mSUfJ5nQhmdLdKg6Gvh1St/vRcsDJOZqEFBVn35/oK974l root@ADS_4300N_BRN000EC691D285"
|
|
];
|
|
|
|
paperless = {
|
|
group = "paperless";
|
|
uid = config.ids.uids.paperless;
|
|
home = "/var/empty";
|
|
};
|
|
}
|
|
];
|
|
|
|
users.groups = {
|
|
paperless.gid = config.ids.gids.paperless;
|
|
}
|
|
// lib.mapAttrs (_: cfg: { gid = cfg.id; }) (smbUsers // smbGroups);
|
|
|
|
backups.storageBoxes.dusk = {
|
|
subuser = "samba";
|
|
paths = [ "/bunker" ];
|
|
};
|
|
}
|