diff --git a/modules/default.nix b/modules/default.nix index ebec6c96..e1f6b652 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -20,6 +20,7 @@ let ./programs/git.nix ./programs/gnome-terminal.nix ./programs/lesspipe.nix + ./programs/ssh.nix ./programs/texlive.nix ./services/dunst.nix ./services/gnome-keyring.nix diff --git a/modules/programs/ssh.nix b/modules/programs/ssh.nix new file mode 100644 index 00000000..9f06e8b5 --- /dev/null +++ b/modules/programs/ssh.nix @@ -0,0 +1,158 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.ssh; + + yn = flag: if flag then "yes" else "no"; + + matchBlockModule = types.submodule { + options = { + host = mkOption { + type = types.str; + example = "*.example.org"; + description = '' + The host pattern used by this conditional block. + ''; + }; + + port = mkOption { + type = types.nullOr types.int; + default = null; + description = "Specifies port number to connect on remote host."; + }; + + forwardX11 = mkOption { + type = types.bool; + default = false; + description = '' + Specifies whether X11 connections will be automatically redirected + over the secure channel and DISPLAY set. + ''; + }; + + forwardX11Trusted = mkOption { + type = types.bool; + default = false; + description = '' + Specifies whether remote X11 clients will have full access to the + original X11 display. + ''; + }; + + identitiesOnly = mkOption { + type = types.bool; + default = false; + description = '' + Specifies that ssh should only use the authentication + identity explicitly configured in the + ~/.ssh/config files or passed on the + ssh command-line, even if ssh-agent + offers more identities. + ''; + }; + + identityFile = mkOption { + type = types.nullOr types.string; + default = null; + description = '' + Specifies a file from which the user identity is read. + ''; + }; + + user = mkOption { + type = types.nullOr types.string; + default = null; + description = "Specifies the user to log in as."; + }; + + hostname = mkOption { + type = types.nullOr types.string; + default = null; + description = "Specifies the real host name to log into."; + }; + + serverAliveInterval = mkOption { + type = types.int; + default = 0; + description = + "Set timeout in seconds after which response will be requested."; + }; + + checkHostIP = mkOption { + type = types.bool; + default = true; + description = '' + Check the host IP address in the + known_hosts file. + ''; + }; + }; + }; + + matchBlockStr = cf: concatStringsSep "\n" ( + ["Host ${cf.host}"] + ++ optional (cf.port != null) " Port ${toString cf.port}" + ++ optional cf.forwardX11 " ForwardX11 yes" + ++ optional cf.forwardX11Trusted " ForwardX11Trusted yes" + ++ optional cf.identitiesOnly " IdentitiesOnly yes" + ++ optional (cf.user != null) " User ${cf.user}" + ++ optional (cf.identityFile != null) " IdentityFile ${cf.identityFile}" + ++ optional (cf.hostname != null) " HostName ${cf.hostname}" + ++ optional (cf.serverAliveInterval != 0) + " ServerAliveInterval ${toString cf.serverAliveInterval}" + ++ optional (!cf.checkHostIP) " CheckHostIP no" + ); + +in + +{ + options.programs.ssh = { + enable = mkEnableOption "SSH client configuration"; + + forwardAgent = mkOption { + default = false; + type = types.bool; + description = '' + Whether connection to authentication agent (if any) will be forwarded + to remote machine. + ''; + }; + + controlMaster = mkOption { + default = "no"; + type = types.enum ["yes" "no" "ask" "auto" "autoask"]; + description = '' + Configure sharing of multiple sessions over a single network connection. + ''; + }; + + controlPath = mkOption { + type = types.string; + default = "~/.ssh/master-%r@%h:%p"; + description = '' + Specify path to the control socket used for connection sharing. + ''; + }; + + matchBlocks = mkOption { + type = types.listOf matchBlockModule; + default = []; + description = '' + Specify per-host settings. + ''; + }; + }; + + config = mkIf cfg.enable { + home.file.".ssh/config".text = '' + ForwardAgent ${yn cfg.forwardAgent} + ControlMaster ${cfg.controlMaster} + ControlPath ${cfg.controlPath} + + ${concatStringsSep "\n\n" (map matchBlockStr cfg.matchBlocks)} + ''; + }; +}