multi-ssh/flake.nix
Leonard Steppy 5343ce30a2 Add flake
2025-10-05 22:02:13 +02:00

116 lines
4.5 KiB
Nix

{
description = "Flake of https://dev.stupstech.de/Mr_Steppy/multi-ssh";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
rust-overlay.url = "github:oxalica/rust-overlay";
};
outputs = { self, nixpkgs, rust-overlay, ... }:
let
systems = nixpkgs.lib.systems.flakeExposed;
forAllSystems = nixpkgs.lib.genAttrs systems;
in
{
packages = forAllSystems (system:
let
overlays = [ rust-overlay.overlays.default ];
pkgs = import nixpkgs { inherit system; overlays = overlays; };
rustToolchain = pkgs.rust-bin.stable."1.90.0".minimal;
rustPlatform = pkgs.makeRustPlatform { cargo = rustToolchain; rustc = rustToolchain; };
in {
multiSsh = rustPlatform.buildRustPackage {
pname = "multi-ssh";
version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).package.version;
src = ./.;
cargoLock = {
lockFile = ./Cargo.lock;
};
nativeCheckInputs = [ pkgs.python3 ];
release = true;
};
default = self.packages.${system}.multiSsh;
}
);
apps = forAllSystems (system:
let
pkg = self.packages.${system}.multiSsh;
in {
default = {
type = "app";
program = "${pkg}/bin/multi-ssh";
};
}
);
nixosModules.multiSsh = { lib, pkgs, config, ... }: {
options = {
programs.multiSsh = {
enable = lib.mkEnableOption "multi-ssh";
editor = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = "Editor to forward to multi-ssh (MSSH_EDITOR). If null, the variable is not set.";
default = null;
};
package = lib.mkOption {
type = lib.types.package;
description = "Derivation to install for multi-ssh";
default = self.packages.${pkgs.system}.multiSsh;
};
servers = {
local = {
dir = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''Local server directory, relative to the user's HOME. If set, a local entry ".:<dir>" is added to MSSH_SERVERS.'';
};
};
server = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
options = {
dir = lib.mkOption {
type = lib.types.str;
description = "Server directory for ${name} (remote ssh host), as a string.";
};
};
}));
default = {};
description = "Attribute set of servers where each attribute name is the ssh host and its value provides a 'dir' string.";
};
};
msshAlias = lib.mkOption {
type = lib.types.bool;
default = true;
description = "If true, install an 'mssh' wrapper (alias) that calls 'multi-ssh' and sets env vars.";
};
};
};
config = lib.mkIf config.programs.multiSsh.enable (let
# Build MSSH_SERVERS from options
serverEntries = lib.mapAttrsToList (name: value: "${name}:${value.dir}") config.programs.multiSsh.servers.server;
localEntry = lib.optional (config.programs.multiSsh.servers.local.dir != null) ".:${config.programs.multiSsh.servers.local.dir}";
msshServers = lib.concatStringsSep "," (localEntry ++ serverEntries);
# wrapper that sets env and execs the real binary (installed as 'multi-ssh')
multiSshWrapper = pkgs.writeShellScriptBin "multi-ssh" ''
#!${pkgs.runtimeShell}
${lib.optionalString (config.programs.multiSsh.editor != null) ''export MSSH_EDITOR="${config.programs.multiSsh.editor}"''}
${lib.optionalString (msshServers != "") ''export MSSH_SERVERS="${msshServers}"''}
exec ${config.programs.multiSsh.package}/bin/multi-ssh "$@"
'';
# optional 'mssh' alias that delegates to the wrapped 'multi-ssh'
msshWrapper = pkgs.writeShellScriptBin "mssh" ''
#!${pkgs.runtimeShell}
exec ${multiSshWrapper}/bin/multi-ssh "$@"
'';
in {
environment.systemPackages = [
multiSshWrapper
] ++ lib.optional config.programs.multiSsh.msshAlias msshWrapper;
});
};
};
}