2023-06-15 10:08:54 +00:00
# docs
# - x-systemd options: <https://www.freedesktop.org/software/systemd/man/systemd.mount.html>
2024-02-23 02:29:12 +00:00
# - fuse options: `man mount.fuse`
2023-06-15 10:08:54 +00:00
2023-08-20 06:20:04 +00:00
{ lib , pkgs , sane-lib , . . . }:
2022-06-02 10:40:14 +00:00
2023-08-20 06:20:04 +00:00
let
fsOpts = rec {
common = [
" _ n e t d e v "
" n o a t i m e "
2024-02-23 02:29:12 +00:00
# user: allow any user with access to the device to mount the fs.
# note that this requires a suid `mount` binary; see: <https://zameermanji.com/blog/2022/8/5/using-fuse-without-root-on-linux/>
" u s e r "
2023-08-20 06:20:04 +00:00
" x - s y s t e m d . r e q u i r e s = n e t w o r k - o n l i n e . t a r g e t "
" x - s y s t e m d . a f t e r = n e t w o r k - o n l i n e . t a r g e t "
" x - s y s t e m d . m o u n t - t i m e o u t = 1 0 s " # how long to wait for mount **and** how long to wait for unmount
] ;
2024-02-24 16:04:04 +00:00
# x-systemd.automount: mount the fs automatically *on first access*.
# creates a `path-to-mount.automount` systemd unit.
automount = [ " x - s y s t e m d . a u t o m o u n t " ] ;
# noauto: don't mount as part of remote-fs.target.
# N.B.: `remote-fs.target` is a dependency of multi-user.target, itself of graphical.target.
# hence, omitting `noauto` can slow down boots.
noauto = [ " n o a u t o " ] ;
# lazyMount: defer mounting until first access from userspace
lazyMount = noauto ++ automount ;
2023-08-20 06:20:04 +00:00
wg = [
" x - s y s t e m d . r e q u i r e s = w i r e g u a r d - w g - h o m e . s e r v i c e "
" x - s y s t e m d . a f t e r = w i r e g u a r d - w g - h o m e . s e r v i c e "
] ;
2023-06-15 09:25:48 +00:00
2023-08-20 06:20:04 +00:00
ssh = common ++ [
" i d e n t i t y f i l e = / h o m e / c o l i n / . s s h / i d _ e d 2 5 5 1 9 "
2024-02-24 16:04:04 +00:00
" a l l o w _ o t h e r " # allow users other than the one who mounts it to access it. needed, if systemd is the one mounting this fs (as root)
# allow_root: allow root to access files on this fs (if mounted by non-root, else it can always access them).
# N.B.: if both allow_root and allow_other are specified, then only allow_root takes effect.
# "allow_root"
# default_permissions: enforce local permissions check. CRUCIAL if using `allow_other`.
# w/o this, permissions mode of sshfs is like:
# - sshfs runs all remote commands as the remote user.
# - if a local user has local permissions to the sshfs mount, then their file ops are sent blindly across the tunnel.
# - `allow_other` allows *any* local user to access the mount, and hence any local user can now freely become the remote mapped user.
# with default_permissions, sshfs doesn't tunnel file ops from users until checking that said user could perform said op on an equivalent local fs.
2023-08-20 06:20:04 +00:00
" d e f a u l t _ p e r m i s s i o n s "
] ;
sshColin = ssh ++ [
2024-02-24 16:04:04 +00:00
# follow_symlinks: remote files which are symlinks are presented to the local system as ordinary files (as the target of the symlink).
# if the symlink target does not exist, the presentation is unspecified.
# symlinks which point outside the mount ARE followed. so this is more capable than `transform_symlinks`
" f o l l o w _ s y m l i n k s "
# symlinks on the remote fs which are absolute paths are presented to the local system as relative symlinks pointing to the expected data on the remote fs.
# only symlinks which would point inside the mountpoint are translated.
2023-08-20 06:20:04 +00:00
" t r a n s f o r m _ s y m l i n k s "
" i d m a p = u s e r "
" u i d = 1 0 0 0 "
" g i d = 1 0 0 "
] ;
2024-02-25 05:12:44 +00:00
# sshRoot = ssh ++ [
# # we don't transform_symlinks because that breaks the validity of remote /nix stores
# "sftp_server=/run/wrappers/bin/sudo\\040/run/current-system/sw/libexec/sftp-server"
# ];
2023-08-20 06:20:04 +00:00
# in the event of hunt NFS mounts, consider:
# - <https://unix.stackexchange.com/questions/31979/stop-broken-nfs-mounts-from-locking-a-directory>
2023-06-15 09:25:48 +00:00
2023-08-20 06:20:04 +00:00
# NFS options: <https://linux.die.net/man/5/nfs>
# actimeo=n = how long (in seconds) to cache file/dir attributes (default: 3-60s)
# bg = retry failed mounts in the background
# retry=n = for how many minutes `mount` will retry NFS mount operation
# soft = on "major timeout", report I/O error to userspace
# retrans=n = how many times to retry a NFS request before giving userspace a "server not responding" error (default: 3)
# timeo=n = number of *deciseconds* to wait for a response before retrying it (default: 600)
# note: client uses a linear backup, so the second request will have double this timeout, then triple, etc.
nfs = common ++ [
# "actimeo=10"
" b g "
" r e t r a n s = 4 "
" r e t r y = 0 "
" s o f t "
" t i m e o = 1 5 "
" n o f a i l " # don't fail remote-fs.target when this mount fails (not an option for sshfs else would be common)
] ;
} ;
remoteHome = host : {
2024-02-06 05:48:11 +00:00
fileSystems . " / m n t / ${ host } / h o m e " = {
2023-08-20 06:20:04 +00:00
device = " c o l i n @ ${ host } : / h o m e / c o l i n " ;
fsType = " f u s e . s s h f s " ;
2024-02-24 16:04:04 +00:00
options = fsOpts . sshColin ++ fsOpts . lazyMount ;
2023-08-20 06:20:04 +00:00
noCheck = true ;
} ;
2024-02-23 02:29:12 +00:00
sane . fs . " / m n t / ${ host } / h o m e " = sane-lib . fs . wanted {
dir . acl . user = " c o l i n " ;
dir . acl . group = " u s e r s " ;
dir . acl . mode = " 0 7 0 0 " ;
} ;
2023-08-20 06:20:04 +00:00
} ;
2022-06-10 07:38:02 +00:00
in
2023-08-20 06:20:04 +00:00
lib . mkMerge [
{
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
sane . fs . " / v a r / l i b / p r i v a t e " . dir . acl . mode = " 0 7 0 0 " ;
2023-07-13 23:37:30 +00:00
2023-08-20 06:20:04 +00:00
# in-memory compressed RAM
# defaults to compressing at most 50% size of RAM
# claimed compression ratio is about 2:1
# - but on moby w/ zstd default i see 4-7:1 (ratio lowers as it fills)
# note that idle overhead is about 0.05% of capacity (e.g. 2B per 4kB page)
# docs: <https://www.kernel.org/doc/Documentation/blockdev/zram.txt>
#
# to query effectiveness:
# `cat /sys/block/zram0/mm_stat`. whitespace separated fields:
# - *orig_data_size* (bytes)
# - *compr_data_size* (bytes)
# - mem_used_total (bytes)
# - mem_limit (bytes)
# - mem_used_max (bytes)
# - *same_pages* (pages which are e.g. all zeros (consumes no additional mem))
# - *pages_compacted* (pages which have been freed thanks to compression)
# - huge_pages (incompressible)
#
# see also:
# - `man zramctl`
zramSwap . enable = true ;
# how much ram can be swapped into the zram device.
# this shouldn't be higher than the observed compression ratio.
# the default is 50% (why?)
# 100% should be "guaranteed" safe so long as the data is even *slightly* compressible.
# but it decreases working memory under the heaviest of loads by however much space the compressed memory occupies (e.g. 50% if 2:1; 25% if 4:1)
zramSwap . memoryPercent = 100 ;
2023-06-15 02:14:42 +00:00
2023-08-20 06:20:04 +00:00
# fileSystems."/mnt/servo-nfs" = {
# device = "servo-hn:/";
# noCheck = true;
# fsType = "nfs";
2024-02-24 16:04:04 +00:00
# options = fsOpts.nfs ++ fsOpts.automount ++ fsOpts.wg;
2023-08-20 06:20:04 +00:00
# };
2024-02-06 05:48:11 +00:00
fileSystems . " / m n t / s e r v o / m e d i a " = {
2023-08-20 06:20:04 +00:00
device = " s e r v o - h n : / m e d i a " ;
noCheck = true ;
fsType = " n f s " ;
2024-02-24 16:04:04 +00:00
options = fsOpts . nfs ++ fsOpts . lazyMount ++ fsOpts . wg ;
2023-08-20 06:20:04 +00:00
} ;
2024-02-23 02:29:12 +00:00
sane . fs . " / m n t / s e r v o / m e d i a " = sane-lib . fs . wanted {
dir . acl . user = " c o l i n " ;
dir . acl . group = " u s e r s " ;
dir . acl . mode = " 0 7 5 0 " ;
} ;
2024-02-06 05:48:11 +00:00
fileSystems . " / m n t / s e r v o / p l a y g r o u n d " = {
2023-09-01 10:10:28 +00:00
device = " s e r v o - h n : / p l a y g r o u n d " ;
noCheck = true ;
fsType = " n f s " ;
2024-02-24 16:04:04 +00:00
options = fsOpts . nfs ++ fsOpts . lazyMount ++ fsOpts . wg ;
2023-09-01 10:10:28 +00:00
} ;
2024-02-23 02:29:12 +00:00
sane . fs . " / m n t / s e r v o / p l a y g r o u n d " = sane-lib . fs . wanted {
dir . acl . user = " c o l i n " ;
dir . acl . group = " u s e r s " ;
dir . acl . mode = " 0 7 5 0 " ;
} ;
2022-06-14 05:25:38 +00:00
2024-02-25 05:12:44 +00:00
# environment.pathsToLink = [
# # needed to achieve superuser access for user-mounted filesystems (see sshRoot above)
# # we can only link whole directories here, even though we're only interested in pkgs.openssh
# "/libexec"
# ];
2023-08-14 08:10:17 +00:00
2024-02-23 02:29:12 +00:00
programs . fuse . userAllowOther = true ; #< necessary for `allow_other` or `allow_root` options.
2023-08-20 06:20:04 +00:00
environment . systemPackages = [
pkgs . sshfs-fuse
] ;
}
2023-06-15 10:08:54 +00:00
2023-08-20 06:20:04 +00:00
( remoteHome " d e s k o " )
2023-08-20 06:26:20 +00:00
( remoteHome " l a p p y " )
2023-08-20 06:20:04 +00:00
( remoteHome " m o b y " )
]
2022-06-02 10:40:14 +00:00