hosts/common: port /mnt/servo/* from NFS -> FTP
fuse ftp seems to be easier to debug than kernel nfs so far
This commit is contained in:
parent
701e10b121
commit
e855be4796
|
@ -5,6 +5,31 @@
|
||||||
{ lib, pkgs, sane-lib, ... }:
|
{ lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
curlftpfs = pkgs.curlftpfs.overrideAttrs (upstream: {
|
||||||
|
# apply a timeout not just to the connect operation, but to every operation.
|
||||||
|
# without this, operations will hang for 2*<TCP timeout>, e.g. 4m20s.
|
||||||
|
# better would be to use CURLOPT_LOW_SPEED_TIME/CURLOPT_LOW_SPEED_LIMIT,
|
||||||
|
# but those options don't seem to apply.
|
||||||
|
postPatch = (upstream.postPatch or "") + ''
|
||||||
|
substituteInPlace ftpfs.c --replace-fail \
|
||||||
|
'curl_easy_setopt_or_die(easy, CURLOPT_CONNECTTIMEOUT, ftpfs.connect_timeout);' \
|
||||||
|
'curl_easy_setopt_or_die(easy, CURLOPT_CONNECTTIMEOUT, ftpfs.connect_timeout); curl_easy_setopt_or_die(easy, CURLOPT_TIMEOUT, ftpfs.connect_timeout);'
|
||||||
|
''
|
||||||
|
# fuse mount programs need to ignore certain "meta" keys that could be in /etc/fstab.
|
||||||
|
# see: <https://github.com/libfuse/sshfs/issues/96>
|
||||||
|
+ ''
|
||||||
|
substituteInPlace ftpfs.c --replace-fail \
|
||||||
|
'FUSE_OPT_END' \
|
||||||
|
'/* These may come in from /etc/fstab - we just ignore them */ FUSE_OPT_KEY("auto", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("noauto", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("user", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("nouser", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("users", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("_netdev", FUSE_OPT_KEY_DISCARD), FUSE_OPT_END'
|
||||||
|
'';
|
||||||
|
# `mount` clears PATH before calling the mount helper (see util-linux/lib/env.c),
|
||||||
|
# so the traditional /etc/fstab approach of fstype=fuse and device = curlftpfs#URI doesn't work.
|
||||||
|
# instead, install a `mount.curlftpfs` mount helper. this is what programs like `gocryptfs` do.
|
||||||
|
postInstall = (upstream.postInstall or "") + ''
|
||||||
|
ln -s curlftpfs $out/bin/mount.fuse.curlftpfs
|
||||||
|
ln -s curlftpfs $out/bin/mount.curlftpfs
|
||||||
|
'';
|
||||||
|
});
|
||||||
fsOpts = rec {
|
fsOpts = rec {
|
||||||
common = [
|
common = [
|
||||||
"_netdev"
|
"_netdev"
|
||||||
|
@ -31,8 +56,7 @@ let
|
||||||
"x-systemd.after=wireguard-wg-home.service"
|
"x-systemd.after=wireguard-wg-home.service"
|
||||||
];
|
];
|
||||||
|
|
||||||
ssh = common ++ [
|
fuse = [
|
||||||
"identityfile=/home/colin/.ssh/id_ed25519"
|
|
||||||
"allow_other" # allow users other than the one who mounts it to access it. needed, if systemd is the one mounting this fs (as root)
|
"allow_other" # 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).
|
# 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.
|
# N.B.: if both allow_root and allow_other are specified, then only allow_root takes effect.
|
||||||
|
@ -45,7 +69,18 @@ let
|
||||||
# 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.
|
# 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.
|
||||||
"default_permissions"
|
"default_permissions"
|
||||||
];
|
];
|
||||||
sshColin = ssh ++ [
|
fuseColin = fuse ++ [
|
||||||
|
"uid=1000"
|
||||||
|
"gid=100"
|
||||||
|
];
|
||||||
|
|
||||||
|
ssh = common ++ fuse ++ [
|
||||||
|
"identityfile=/home/colin/.ssh/id_ed25519"
|
||||||
|
# i *think* idmap=user means that `colin` on `localhost` and `colin` on the remote are actually treated as the same user, even if their uid/gid differs?
|
||||||
|
# i.e., local colin's id is translated to/from remote colin's id on every operation?
|
||||||
|
"idmap=user"
|
||||||
|
];
|
||||||
|
sshColin = ssh ++ fuseColin ++ [
|
||||||
# follow_symlinks: remote files which are symlinks are presented to the local system as ordinary files (as the target of the symlink).
|
# 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.
|
# 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`
|
# symlinks which point outside the mount ARE followed. so this is more capable than `transform_symlinks`
|
||||||
|
@ -53,9 +88,6 @@ let
|
||||||
# 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.
|
# 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.
|
# only symlinks which would point inside the mountpoint are translated.
|
||||||
"transform_symlinks"
|
"transform_symlinks"
|
||||||
"idmap=user"
|
|
||||||
"uid=1000"
|
|
||||||
"gid=100"
|
|
||||||
];
|
];
|
||||||
# sshRoot = ssh ++ [
|
# sshRoot = ssh ++ [
|
||||||
# # we don't transform_symlinks because that breaks the validity of remote /nix stores
|
# # we don't transform_symlinks because that breaks the validity of remote /nix stores
|
||||||
|
@ -94,6 +126,14 @@ let
|
||||||
# "nfsvers=3" # NFSv4+ doesn't support UDP at *all*. it's ok to omit nfsvers -- server + client will negotiate v3 based on udp requirement. but omitting causes confusing mount errors when the server is *offline*, because the client defaults to v4 and thinks the udp option is a config error.
|
# "nfsvers=3" # NFSv4+ doesn't support UDP at *all*. it's ok to omit nfsvers -- server + client will negotiate v3 based on udp requirement. but omitting causes confusing mount errors when the server is *offline*, because the client defaults to v4 and thinks the udp option is a config error.
|
||||||
# "x-systemd.idle-timeout=10" # auto-unmount after this much inactivity
|
# "x-systemd.idle-timeout=10" # auto-unmount after this much inactivity
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# manually perform a ftp mount via e.g.
|
||||||
|
# curlftpfs -o ftpfs_debug=2,user=anonymous:anonymous,connect_timeout=10 -f -s ftp://servo-hn /mnt/my-ftp
|
||||||
|
ftp = common ++ fuseColin ++ [
|
||||||
|
# "ftpfs_debug=2"
|
||||||
|
"user=colin:ipauth"
|
||||||
|
"connect_timeout=10"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
remoteHome = host: {
|
remoteHome = host: {
|
||||||
fileSystems."/mnt/${host}/home" = {
|
fileSystems."/mnt/${host}/home" = {
|
||||||
|
@ -142,29 +182,35 @@ lib.mkMerge [
|
||||||
# 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)
|
# 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;
|
zramSwap.memoryPercent = 100;
|
||||||
|
|
||||||
# fileSystems."/mnt/servo-nfs" = {
|
# fileSystems."/mnt/servo/media" = {
|
||||||
# device = "servo-hn:/";
|
# device = "servo-hn:/media";
|
||||||
# noCheck = true;
|
# noCheck = true;
|
||||||
# fsType = "nfs";
|
# fsType = "nfs";
|
||||||
# options = fsOpts.nfs ++ fsOpts.automount ++ fsOpts.wg;
|
# options = fsOpts.nfs ++ fsOpts.lazyMount ++ fsOpts.wg;
|
||||||
|
# };
|
||||||
|
# fileSystems."/mnt/servo/playground" = {
|
||||||
|
# device = "servo-hn:/playground";
|
||||||
|
# noCheck = true;
|
||||||
|
# fsType = "nfs";
|
||||||
|
# options = fsOpts.nfs ++ fsOpts.lazyMount ++ fsOpts.wg;
|
||||||
# };
|
# };
|
||||||
fileSystems."/mnt/servo/media" = {
|
fileSystems."/mnt/servo/media" = {
|
||||||
device = "servo-hn:/media";
|
device = "servo-hn:/media";
|
||||||
noCheck = true;
|
noCheck = true;
|
||||||
fsType = "nfs";
|
fsType = "fuse.curlftpfs";
|
||||||
options = fsOpts.nfs ++ fsOpts.lazyMount ++ fsOpts.wg;
|
options = fsOpts.ftp ++ fsOpts.lazyMount ++ fsOpts.wg;
|
||||||
|
};
|
||||||
|
fileSystems."/mnt/servo/playground" = {
|
||||||
|
device = "servo-hn:/playground";
|
||||||
|
noCheck = true;
|
||||||
|
fsType = "fuse.curlftpfs";
|
||||||
|
options = fsOpts.ftp ++ fsOpts.lazyMount ++ fsOpts.wg;
|
||||||
};
|
};
|
||||||
sane.fs."/mnt/servo/media" = sane-lib.fs.wanted {
|
sane.fs."/mnt/servo/media" = sane-lib.fs.wanted {
|
||||||
dir.acl.user = "colin";
|
dir.acl.user = "colin";
|
||||||
dir.acl.group = "users";
|
dir.acl.group = "users";
|
||||||
dir.acl.mode = "0750";
|
dir.acl.mode = "0750";
|
||||||
};
|
};
|
||||||
fileSystems."/mnt/servo/playground" = {
|
|
||||||
device = "servo-hn:/playground";
|
|
||||||
noCheck = true;
|
|
||||||
fsType = "nfs";
|
|
||||||
options = fsOpts.nfs ++ fsOpts.lazyMount ++ fsOpts.wg;
|
|
||||||
};
|
|
||||||
sane.fs."/mnt/servo/playground" = sane-lib.fs.wanted {
|
sane.fs."/mnt/servo/playground" = sane-lib.fs.wanted {
|
||||||
dir.acl.user = "colin";
|
dir.acl.user = "colin";
|
||||||
dir.acl.group = "users";
|
dir.acl.group = "users";
|
||||||
|
@ -180,6 +226,7 @@ lib.mkMerge [
|
||||||
programs.fuse.userAllowOther = true; #< necessary for `allow_other` or `allow_root` options.
|
programs.fuse.userAllowOther = true; #< necessary for `allow_other` or `allow_root` options.
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
pkgs.sshfs-fuse
|
pkgs.sshfs-fuse
|
||||||
|
curlftpfs
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user