sftpman: add module

This commit is contained in:
Fugi 2023-11-06 20:05:51 +01:00 committed by Robert Helgesson
parent c24c298562
commit 6e2afa5c3b
No known key found for this signature in database
GPG key ID: 96E745BD17AA17ED
10 changed files with 231 additions and 0 deletions

View file

@ -1356,6 +1356,13 @@ in
A new module is available: 'services.osmscout-server'. A new module is available: 'services.osmscout-server'.
''; '';
} }
{
time = "2023-12-28T13:01:15+00:00";
message = ''
A new module is available: 'programs.sftpman'.
'';
}
]; ];
}; };
} }

View file

@ -198,6 +198,7 @@ let
./programs/scmpuff.nix ./programs/scmpuff.nix
./programs/script-directory.nix ./programs/script-directory.nix
./programs/senpai.nix ./programs/senpai.nix
./programs/sftpman.nix
./programs/sioyek.nix ./programs/sioyek.nix
./programs/skim.nix ./programs/skim.nix
./programs/sm64ex.nix ./programs/sm64ex.nix

View file

@ -0,0 +1,118 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.sftpman;
jsonFormat = pkgs.formats.json { };
mountOpts = { config, name, ... }: {
options = {
host = mkOption {
type = types.str;
description = "The host to connect to.";
};
port = mkOption {
type = types.port;
default = 22;
description = "The port to connect to.";
};
user = mkOption {
type = types.str;
description = "The username to authenticate with.";
};
mountOptions = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Options to pass to sshfs.";
};
mountPoint = mkOption {
type = types.str;
description = "The remote path to mount.";
};
authType = mkOption {
type = types.enum [
"password"
"publickey"
"hostbased"
"keyboard-interactive"
"gssapi-with-mic"
];
default = "publickey";
description = "The authentication method to use.";
};
sshKey = mkOption {
type = types.nullOr types.str;
default = cfg.defaultSshKey;
defaultText =
lib.literalExpression "config.programs.sftpman.defaultSshKey";
description = ''
Path to the SSH key to use for authentication.
Only applies if authMethod is `publickey`.
'';
};
beforeMount = mkOption {
type = types.str;
default = "true";
description = "Command to run before mounting.";
};
};
};
in {
meta.maintainers = with maintainers; [ fugi ];
options.programs.sftpman = {
enable = mkEnableOption
"sftpman, an application that handles sshfs/sftp file systems mounting";
package = mkPackageOption pkgs "sftpman" { };
defaultSshKey = mkOption {
type = types.nullOr types.str;
default = null;
description =
"Path to the SSH key to be used by default. Can be overridden per host.";
};
mounts = mkOption {
type = types.attrsOf (types.submodule mountOpts);
default = { };
description = ''
The sshfs mount configurations written to
{file}`$XDG_CONFIG_HOME/sftpman/mounts/`.
'';
};
};
config = mkIf cfg.enable {
assertions = [
(let
hasMissingKey = _: mount:
mount.authType == "publickey" && mount.sshKey == null;
mountsWithMissingKey = attrNames (filterAttrs hasMissingKey cfg.mounts);
mountsWithMissingKeyStr = concatStringsSep ", " mountsWithMissingKey;
in {
assertion = mountsWithMissingKey == [ ];
message = ''
sftpman mounts using authentication type "publickey" but missing 'sshKey': ${mountsWithMissingKeyStr}
'';
})
];
home.packages = [ cfg.package ];
xdg.configFile = mapAttrs' (name: value:
nameValuePair "sftpman/mounts/${name}.json" {
source =
jsonFormat.generate "sftpman-${name}.json" (value // { id = name; });
}) cfg.mounts;
};
}

View file

@ -139,6 +139,7 @@ import nmt {
./modules/programs/sapling ./modules/programs/sapling
./modules/programs/sbt ./modules/programs/sbt
./modules/programs/scmpuff ./modules/programs/scmpuff
./modules/programs/sftpman
./modules/programs/sioyek ./modules/programs/sioyek
./modules/programs/sm64ex ./modules/programs/sm64ex
./modules/programs/ssh ./modules/programs/ssh

View file

@ -0,0 +1,21 @@
{
config = {
programs.sftpman = {
enable = true;
mounts = {
mount1 = {
host = "host1.example.com";
mountPoint = "/path/to/somewhere";
user = "root";
};
};
};
test.stubs.sftpman = { };
test.asserts.assertions.expected = [''
sftpman mounts using authentication type "publickey" but missing 'sshKey': mount1
''];
};
}

View file

@ -0,0 +1,4 @@
{
sftpman-example-settings = ./example-settings.nix;
sftpman-assert-on-no-sshkey = ./assert-on-no-sshkey.nix;
}

View file

@ -0,0 +1,44 @@
{
config = {
programs.sftpman = {
enable = true;
defaultSshKey = "/home/user/.ssh/id_ed25519";
mounts = {
mount1 = {
host = "host1.example.com";
mountPoint = "/path/to/somewhere";
user = "root";
mountOptions = [ "idmap=user" ];
};
mount2 = {
host = "host2.example.com";
mountPoint = "/another/path";
user = "someuser";
authType = "password";
sshKey = null;
};
mount3 = {
host = "host3.example.com";
mountPoint = "/yet/another/path";
user = "user";
sshKey = "/home/user/.ssh/id_rsa";
};
};
};
test.stubs.sftpman = { };
nmt.script = ''
assertFileContent \
home-files/.config/sftpman/mounts/mount1.json \
${./expected-mount1.json}
assertFileContent \
home-files/.config/sftpman/mounts/mount2.json \
${./expected-mount2.json}
assertFileContent \
home-files/.config/sftpman/mounts/mount3.json \
${./expected-mount3.json}
'';
};
}

View file

@ -0,0 +1,13 @@
{
"authType": "publickey",
"beforeMount": "true",
"host": "host1.example.com",
"id": "mount1",
"mountOptions": [
"idmap=user"
],
"mountPoint": "/path/to/somewhere",
"port": 22,
"sshKey": "/home/user/.ssh/id_ed25519",
"user": "root"
}

View file

@ -0,0 +1,11 @@
{
"authType": "password",
"beforeMount": "true",
"host": "host2.example.com",
"id": "mount2",
"mountOptions": [],
"mountPoint": "/another/path",
"port": 22,
"sshKey": null,
"user": "someuser"
}

View file

@ -0,0 +1,11 @@
{
"authType": "publickey",
"beforeMount": "true",
"host": "host3.example.com",
"id": "mount3",
"mountOptions": [],
"mountPoint": "/yet/another/path",
"port": 22,
"sshKey": "/home/user/.ssh/id_rsa",
"user": "user"
}