add nfs and autofs system
This commit is contained in:
parent
27408723d9
commit
73b137dc84
6 changed files with 92 additions and 341 deletions
|
|
@ -7,9 +7,8 @@
|
|||
../../../modules/wireguard.nix
|
||||
../../../modules/podman.nix
|
||||
../../../modules/traefik.nix
|
||||
../../../modules/samba.nix
|
||||
../../../modules/nfs.nix
|
||||
../../../modules/borg-client.nix
|
||||
../../../modules/webdav.nix
|
||||
../../../modules/login-display.nix
|
||||
];
|
||||
|
||||
|
|
@ -197,24 +196,11 @@
|
|||
|
||||
|
||||
|
||||
# Samba file sharing configuration
|
||||
services.samba-custom = { enable = false; };
|
||||
|
||||
# WebDAV file server configuration
|
||||
services.webdav-server = {
|
||||
enable = false;
|
||||
port = 5009;
|
||||
servePath = "/mnt/storage/Media";
|
||||
auth = {
|
||||
username = "yanlin";
|
||||
passwordFile = "/etc/webdav-password";
|
||||
};
|
||||
readOnly = false;
|
||||
allowUpload = true;
|
||||
allowDelete = true;
|
||||
allowSearch = true;
|
||||
allowSymlink = false;
|
||||
hideDotFiles = true;
|
||||
# NFS file sharing configuration
|
||||
services.nfs-custom = {
|
||||
enable = true;
|
||||
exportPath = "/mnt/storage/Media";
|
||||
allowedNetwork = "10.2.2.0/24";
|
||||
};
|
||||
|
||||
# Login display with SMART disk health status
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
./hardware-configuration.nix
|
||||
../system-default.nix # Common NixOS system configuration
|
||||
../../../modules/wireguard.nix
|
||||
../../../modules/autofs.nix
|
||||
../../../modules/login-display.nix
|
||||
];
|
||||
|
||||
|
|
@ -317,4 +318,12 @@
|
|||
showDiskUsage = true;
|
||||
};
|
||||
|
||||
# AutoFS auto-mounting for remote NFS shares
|
||||
services.autofs-custom = {
|
||||
enable = true;
|
||||
remoteHost = "10.2.2.20";
|
||||
remotePath = "/mnt/storage/Media";
|
||||
mountPoint = "/mnt/hs-media";
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
44
modules/autofs.nix
Normal file
44
modules/autofs.nix
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.autofs-custom;
|
||||
in
|
||||
|
||||
{
|
||||
options.services.autofs-custom = {
|
||||
enable = mkEnableOption "AutoFS automatic mounting";
|
||||
|
||||
remoteHost = mkOption {
|
||||
type = types.str;
|
||||
description = "Remote NFS server hostname or IP";
|
||||
};
|
||||
|
||||
remotePath = mkOption {
|
||||
type = types.str;
|
||||
description = "Remote path to mount";
|
||||
};
|
||||
|
||||
mountPoint = mkOption {
|
||||
type = types.str;
|
||||
description = "Local mount point";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.autofs = {
|
||||
enable = true;
|
||||
timeout = 300;
|
||||
autoMaster = ''
|
||||
${cfg.mountPoint} -fstype=nfs4,rw,soft,intr,noatime ${cfg.remoteHost}:${cfg.remotePath}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.mountPoint} 0755 root root -"
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pkgs.nfs-utils ];
|
||||
};
|
||||
}
|
||||
33
modules/nfs.nix
Normal file
33
modules/nfs.nix
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.nfs-custom;
|
||||
in
|
||||
|
||||
{
|
||||
options.services.nfs-custom = {
|
||||
enable = mkEnableOption "NFS server";
|
||||
|
||||
exportPath = mkOption {
|
||||
type = types.str;
|
||||
description = "Path to export via NFS";
|
||||
};
|
||||
|
||||
allowedNetwork = mkOption {
|
||||
type = types.str;
|
||||
default = "10.2.2.0/24";
|
||||
description = "Network allowed to access the export (CIDR)";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.nfs.server = {
|
||||
enable = true;
|
||||
exports = ''
|
||||
${cfg.exportPath} ${cfg.allowedNetwork}(rw,sync,no_subtree_check,no_root_squash)
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.samba-custom;
|
||||
in
|
||||
|
||||
{
|
||||
options.services.samba-custom = {
|
||||
enable = mkEnableOption "Samba file sharing service";
|
||||
|
||||
workgroup = mkOption {
|
||||
type = types.str;
|
||||
default = "WORKGROUP";
|
||||
description = "SMB workgroup name";
|
||||
};
|
||||
|
||||
serverString = mkOption {
|
||||
type = types.str;
|
||||
default = "NixOS Samba Server";
|
||||
description = "Server description string";
|
||||
};
|
||||
|
||||
shares = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
description = "Path to the shared directory";
|
||||
};
|
||||
|
||||
comment = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "Share description comment";
|
||||
};
|
||||
|
||||
browseable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether share is browseable";
|
||||
};
|
||||
|
||||
readOnly = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether share is read-only";
|
||||
};
|
||||
|
||||
guestOk = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Allow guest access";
|
||||
};
|
||||
|
||||
createMask = mkOption {
|
||||
type = types.str;
|
||||
default = "0644";
|
||||
description = "File creation mask";
|
||||
};
|
||||
|
||||
directoryMask = mkOption {
|
||||
type = types.str;
|
||||
default = "0755";
|
||||
description = "Directory creation mask";
|
||||
};
|
||||
|
||||
forceUser = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Force files to be owned by this user";
|
||||
};
|
||||
|
||||
forceGroup = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Force files to be owned by this group";
|
||||
};
|
||||
|
||||
validUsers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "List of valid users for this share";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
description = "Samba share definitions";
|
||||
};
|
||||
|
||||
enableWSDD = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Web Service Discovery (WSD) for SMB discovery";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Open firewall ports for Samba";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Enable Samba service
|
||||
services.samba = {
|
||||
enable = true;
|
||||
|
||||
# Enable SMB protocol versions
|
||||
package = pkgs.samba4Full;
|
||||
|
||||
# Modern Samba configuration using settings
|
||||
settings = {
|
||||
global = {
|
||||
# Server identification
|
||||
workgroup = cfg.workgroup;
|
||||
"server string" = cfg.serverString;
|
||||
|
||||
# Security settings
|
||||
security = "user";
|
||||
"map to guest" = "never";
|
||||
|
||||
# Performance optimizations
|
||||
"socket options" = "TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=524288 SO_SNDBUF=524288";
|
||||
deadtime = "30";
|
||||
"use sendfile" = "yes";
|
||||
|
||||
# Logging
|
||||
"log file" = "/var/log/samba/log.%m";
|
||||
"max log size" = "1000";
|
||||
"log level" = "0";
|
||||
|
||||
# Disable printer sharing
|
||||
"load printers" = "no";
|
||||
printing = "bsd";
|
||||
"printcap name" = "/dev/null";
|
||||
"disable spoolss" = "yes";
|
||||
};
|
||||
|
||||
# Generate share configurations
|
||||
} // (mapAttrs (name: share: {
|
||||
path = share.path;
|
||||
browseable = if share.browseable then "yes" else "no";
|
||||
"read only" = if share.readOnly then "yes" else "no";
|
||||
"guest ok" = if share.guestOk then "yes" else "no";
|
||||
"create mask" = share.createMask;
|
||||
"directory mask" = share.directoryMask;
|
||||
"valid users" = concatStringsSep " " share.validUsers;
|
||||
comment = share.comment;
|
||||
} // (optionalAttrs (share.forceUser != null) {
|
||||
"force user" = share.forceUser;
|
||||
}) // (optionalAttrs (share.forceGroup != null) {
|
||||
"force group" = share.forceGroup;
|
||||
})) cfg.shares);
|
||||
};
|
||||
|
||||
# Enable SMB discovery
|
||||
services.samba-wsdd = mkIf cfg.enableWSDD {
|
||||
enable = true;
|
||||
openFirewall = cfg.openFirewall;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.webdav-server;
|
||||
in
|
||||
{
|
||||
options.services.webdav-server = {
|
||||
enable = mkEnableOption "WebDAV file server using dufs";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 5009;
|
||||
description = "Port to listen on";
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "Address to bind to";
|
||||
};
|
||||
|
||||
servePath = mkOption {
|
||||
type = types.str;
|
||||
description = "Path to serve via WebDAV";
|
||||
};
|
||||
|
||||
auth = mkOption {
|
||||
type = types.nullOr (types.submodule {
|
||||
options = {
|
||||
username = mkOption {
|
||||
type = types.str;
|
||||
description = "Username for authentication";
|
||||
};
|
||||
passwordFile = mkOption {
|
||||
type = types.str;
|
||||
description = "Path to file containing password";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = null;
|
||||
description = "Authentication configuration";
|
||||
};
|
||||
|
||||
readOnly = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Make the WebDAV share read-only";
|
||||
};
|
||||
|
||||
allowUpload = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Allow file uploads";
|
||||
};
|
||||
|
||||
allowDelete = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Allow file deletion";
|
||||
};
|
||||
|
||||
allowSearch = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable search functionality";
|
||||
};
|
||||
|
||||
allowSymlink = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Allow serving symbolic links";
|
||||
};
|
||||
|
||||
hideDotFiles = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Hide dot files from listing";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Install dufs package
|
||||
environment.systemPackages = [ pkgs.dufs ];
|
||||
|
||||
# Set password file permissions if auth is enabled
|
||||
systemd.tmpfiles.rules = mkIf (cfg.auth != null) [
|
||||
"z ${cfg.auth.passwordFile} 0640 yanlin users - -"
|
||||
];
|
||||
|
||||
# Create systemd service for dufs
|
||||
systemd.services.webdav-server = {
|
||||
description = "WebDAV server using dufs";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = let
|
||||
permissionArgs = concatStringsSep " " (
|
||||
(optional cfg.readOnly "--render-index") ++
|
||||
(optional (!cfg.allowUpload) "--no-upload") ++
|
||||
(optional (!cfg.allowDelete) "--no-delete") ++
|
||||
(optional (!cfg.allowSearch) "--no-search") ++
|
||||
(optional cfg.allowSymlink "--allow-symlink") ++
|
||||
(optional cfg.hideDotFiles "--hidden '.*, .*/'")
|
||||
);
|
||||
in {
|
||||
Type = "simple";
|
||||
ExecStart = let
|
||||
startScript = pkgs.writeShellScript "dufs-start" ''
|
||||
${if cfg.auth != null then ''
|
||||
if [ ! -f "${cfg.auth.passwordFile}" ]; then
|
||||
echo "Error: Password file ${cfg.auth.passwordFile} does not exist"
|
||||
exit 1
|
||||
fi
|
||||
AUTH_PASSWORD=$(cat ${cfg.auth.passwordFile} | tr -d '\n')
|
||||
exec ${pkgs.dufs}/bin/dufs \
|
||||
--bind ${cfg.address} \
|
||||
--port ${toString cfg.port} \
|
||||
--auth "${cfg.auth.username}:$AUTH_PASSWORD@/:rw" \
|
||||
${permissionArgs} \
|
||||
"${cfg.servePath}"
|
||||
'' else ''
|
||||
exec ${pkgs.dufs}/bin/dufs \
|
||||
--bind ${cfg.address} \
|
||||
--port ${toString cfg.port} \
|
||||
${permissionArgs} \
|
||||
"${cfg.servePath}"
|
||||
''}
|
||||
'';
|
||||
in "${startScript}";
|
||||
Restart = "always";
|
||||
RestartSec = "10";
|
||||
User = "yanlin";
|
||||
Group = "users";
|
||||
UMask = "0022"; # Creates dirs as 755, files as 644
|
||||
|
||||
# Security hardening
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = if cfg.readOnly then [] else [ cfg.servePath ];
|
||||
ReadOnlyPaths = if cfg.readOnly then [ cfg.servePath ] else [];
|
||||
NoNewPrivileges = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" "AF_NETLINK" ]; # Added AF_UNIX and AF_NETLINK for interface enumeration
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue