2023-06-15 01:38:09 +00:00
|
|
|
# docs:
|
|
|
|
# - <https://nixos.wiki/wiki/NFS>
|
|
|
|
# - <https://wiki.gentoo.org/wiki/Nfs-utils>
|
2023-09-01 10:08:29 +00:00
|
|
|
# system files:
|
|
|
|
# - /etc/exports
|
|
|
|
# system services:
|
|
|
|
# - nfs-server.service
|
|
|
|
# - nfs-idmapd.service
|
|
|
|
# - nfs-mountd.service
|
|
|
|
# - nfsdcld.service
|
|
|
|
# - rpc-statd.service
|
|
|
|
# - rpcbind.service
|
|
|
|
#
|
|
|
|
# TODO: force files to be 755, or 750.
|
|
|
|
# - could maybe be done with some mount option?
|
2023-06-15 01:38:09 +00:00
|
|
|
|
2023-09-01 10:08:29 +00:00
|
|
|
{ config, lib, ... }:
|
2023-06-15 01:38:09 +00:00
|
|
|
{
|
|
|
|
services.nfs.server.enable = true;
|
|
|
|
|
|
|
|
# see which ports NFS uses with:
|
|
|
|
# - `rpcinfo -p`
|
|
|
|
sane.ports.ports."111" = {
|
|
|
|
protocol = [ "tcp" "udp" ];
|
|
|
|
visibleTo.lan = true;
|
|
|
|
description = "NFS server portmapper";
|
|
|
|
};
|
|
|
|
sane.ports.ports."2049" = {
|
|
|
|
protocol = [ "tcp" ];
|
|
|
|
visibleTo.lan = true;
|
|
|
|
description = "NFS server";
|
|
|
|
};
|
|
|
|
sane.ports.ports."4000" = {
|
|
|
|
protocol = [ "udp" ];
|
|
|
|
visibleTo.lan = true;
|
|
|
|
description = "NFS server status daemon";
|
|
|
|
};
|
|
|
|
sane.ports.ports."4001" = {
|
|
|
|
protocol = [ "tcp" "udp" ];
|
|
|
|
visibleTo.lan = true;
|
|
|
|
description = "NFS server lock daemon";
|
|
|
|
};
|
|
|
|
sane.ports.ports."4002" = {
|
|
|
|
protocol = [ "tcp" "udp" ];
|
|
|
|
visibleTo.lan = true;
|
|
|
|
description = "NFS server mount daemon";
|
|
|
|
};
|
|
|
|
|
|
|
|
# NFS4 allows these to float, but NFS3 mandates specific ports, so fix them for backwards compat.
|
|
|
|
services.nfs.server.lockdPort = 4001;
|
|
|
|
services.nfs.server.mountdPort = 4002;
|
|
|
|
services.nfs.server.statdPort = 4000;
|
|
|
|
|
|
|
|
# format:
|
|
|
|
# fspoint visibility(options)
|
|
|
|
# options:
|
|
|
|
# - see: <https://wiki.gentoo.org/wiki/Nfs-utils#Exports>
|
|
|
|
# - see [man 5 exports](https://linux.die.net/man/5/exports)
|
|
|
|
# - insecure: require clients use src port > 1024
|
|
|
|
# - rw, ro (default)
|
|
|
|
# - async, sync (default)
|
|
|
|
# - no_subtree_check (default), subtree_check: verify not just that files requested by the client live
|
|
|
|
# in the expected fs, but also that they live under whatever subdirectory of that fs is exported.
|
2023-06-15 01:52:15 +00:00
|
|
|
# - no_root_squash, root_squash (default): map requests from uid 0 to user `nobody`.
|
2023-06-15 01:38:09 +00:00
|
|
|
# - crossmnt: reveal filesystems that are mounted under this endpoint
|
|
|
|
# - fsid: must be zero for the root export
|
2023-09-01 10:08:29 +00:00
|
|
|
# - fsid=root is alias for fsid=0
|
2023-06-15 01:38:09 +00:00
|
|
|
# - mountpoint[=/path]: only export the directory if it's a mountpoint. used to avoid exporting failed mounts.
|
2023-09-01 10:08:29 +00:00
|
|
|
# - all_squash: rewrite all client requests such that they come from anonuid/anongid
|
|
|
|
# - any files a user creates are owned by local anonuid/anongid.
|
|
|
|
# - users can read any local file which anonuid/anongid would be able to read.
|
|
|
|
# - users can't chown to/away from anonuid/anongid.
|
|
|
|
# - users can chmod files they own, to anything (making them unreadable to non-`nfsuser` export users, like FTP).
|
|
|
|
# - `stat` remains unchanged, returning the real UIDs/GIDs to the client.
|
|
|
|
# - thus programs which check `uid` or `gid` before trying an operation may incorrectly conclude they can't perform some op.
|
2023-06-15 01:38:09 +00:00
|
|
|
#
|
2023-09-01 03:37:33 +00:00
|
|
|
# 10.0.0.0/8 to export both to LAN (readonly, unencrypted) and wg vpn (read-write, encrypted)
|
2023-09-01 10:08:29 +00:00
|
|
|
services.nfs.server.exports =
|
|
|
|
let
|
|
|
|
fmtExport = { export, baseOpts, extraLanOpts ? [], extraVpnOpts ? [] }:
|
|
|
|
let
|
|
|
|
always = [ "subtree_check" ];
|
|
|
|
lanOpts = always ++ baseOpts ++ extraLanOpts;
|
|
|
|
vpnOpts = always ++ baseOpts ++ extraVpnOpts;
|
|
|
|
in "${export} 10.78.79.0/22(${lib.concatStringsSep "," lanOpts}) 10.0.10.0/24(${lib.concatStringsSep "," vpnOpts})";
|
|
|
|
in lib.concatStringsSep "\n" [
|
|
|
|
(fmtExport {
|
|
|
|
export = "/var/export";
|
|
|
|
baseOpts = [ "crossmnt" "fsid=root" ];
|
|
|
|
extraLanOpts = [ "ro" ];
|
|
|
|
extraVpnOpts = [ "rw" "no_root_squash" ];
|
|
|
|
})
|
|
|
|
(fmtExport {
|
|
|
|
export = "/var/export/playground";
|
|
|
|
baseOpts = [
|
|
|
|
"mountpoint"
|
|
|
|
"all_squash"
|
|
|
|
"rw"
|
|
|
|
"anonuid=${builtins.toString config.users.users.nfsuser.uid}"
|
|
|
|
"anongid=${builtins.toString config.users.groups.export.gid}"
|
|
|
|
];
|
|
|
|
})
|
|
|
|
];
|
|
|
|
|
|
|
|
users.users.nfsuser = {
|
|
|
|
description = "virtual user for anonymous NFS operations";
|
|
|
|
group = "export";
|
|
|
|
isSystemUser = true;
|
|
|
|
};
|
2023-06-15 01:38:09 +00:00
|
|
|
}
|