From bce262e46e573c031feb968358ff31db77b00e71 Mon Sep 17 00:00:00 2001 From: Christopher League Date: Mon, 8 May 2017 23:30:37 -0400 Subject: [PATCH] ssh: add programs.ssh module This module generates a `.ssh/config` file. This doesn't embed _all_ options for the ssh client, but the most common ones should be there. Example usage: ```nix programs.ssh = { enable = true; forwardAgent = true; controlMaster = "auto"; matchBlocks = [ { host = "something.blah.edu"; port = 1024; user = "cleague"; identitiesOnly = true; } { host = "host1 host2 host2.net host2.com"; port = 7422; hostname = "example.com"; serverAliveInterval = 60; } { host = "lucian"; forwardX11 = true; forwardX11Trusted = true; checkHostIP = false; }; }; }; ``` Each entry in `programs.ssh.matchBlocks` must contain a `host` field, which will be used for the block condition. --- modules/default.nix | 1 + modules/programs/ssh.nix | 158 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 modules/programs/ssh.nix 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)} + ''; + }; +}