mirror of
https://github.com/nix-community/home-manager.git
synced 2026-06-05 21:02:51 +00:00
ssh: add RFC 42 settings option
Add programs.ssh.settings as a freeform DAG for OpenSSH client configuration blocks. Render Host and Match blocks directly from the new settings option while preserving ordering support. Render known ssh_config comma-list directives from Nix lists as single comma-separated lines and known space-list directives as single whitespace-separated lines. This keeps directives like KexAlgorithms, Ciphers, MACs, HostKeyAlgorithms, ProxyJump, SendEnv, GlobalKnownHostsFile, and PermitRemoteOpen from being emitted as duplicate directives where OpenSSH may only use the first value. Migrate legacy matchBlocks into settings, keep root SSH option redirects pointed at the new option names, and hide the deprecated matchBlocks option from generated docs. Update SSH tests, docs references, and news coverage for the new option.
This commit is contained in:
@@ -2,9 +2,14 @@
|
||||
ssh-old-defaults = ./old-defaults.nix;
|
||||
ssh-old-defaults-extra-config = ./old-defaults-extra-config.nix;
|
||||
ssh-extra-config-no-default-host = ./extra-config-no-default-host.nix;
|
||||
ssh-extra-option-overrides = ./extra-option-overrides.nix;
|
||||
ssh-renamed-options = ./renamed-options.nix;
|
||||
ssh-includes = ./includes.nix;
|
||||
ssh-settings = ./settings.nix;
|
||||
ssh-settings-extra-options-assertion = ./settings-extra-options-assertion.nix;
|
||||
ssh-settings-raw-forwards = ./settings-raw-forwards.nix;
|
||||
ssh-match-blocks = ./match-blocks-attrs.nix;
|
||||
ssh-match-blocks-extra-options-duplicates = ./match-blocks-extra-options-duplicates.nix;
|
||||
ssh-match-blocks-match-and-hosts = ./match-blocks-match-and-hosts.nix;
|
||||
ssh-forwards-dynamic-valid-bind-no-asserts = ./forwards-dynamic-valid-bind-no-asserts.nix;
|
||||
ssh-forwards-dynamic-bind-path-with-port-asserts = ./forwards-dynamic-bind-path-with-port-asserts.nix;
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
};
|
||||
|
||||
test.asserts.assertions.expected = [
|
||||
''Cannot set `programs.ssh.extraConfig` if `programs.ssh.matchBlocks."*"` (default host config) is not declared.''
|
||||
''Cannot set `programs.ssh.extraConfig` if `programs.ssh.settings."*"` (default host config) is not declared.''
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
ForwardAgent no
|
||||
GlobalKnownHostsFile /etc/ssh/ssh_known_hosts ~/.ssh/global_known_hosts
|
||||
|
||||
Host space-list
|
||||
CanonicalDomains example.org corp.example
|
||||
ChannelTimeout session=5m direct-tcpip=30s
|
||||
GlobalKnownHostsFile ~/.ssh/known_hosts ~/.ssh/known_hosts2
|
||||
PermitRemoteOpen localhost:8080 example.org:443
|
||||
UserKnownHostsFile ~/.ssh/user_known_hosts ~/.ssh/user_known_hosts2
|
||||
42
tests/modules/programs/ssh/extra-option-overrides.nix
Normal file
42
tests/modules/programs/ssh/extra-option-overrides.nix
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
extraOptionOverrides = {
|
||||
ForwardAgent = false;
|
||||
GlobalKnownHostsFile = [
|
||||
"/etc/ssh/ssh_known_hosts"
|
||||
"~/.ssh/global_known_hosts"
|
||||
];
|
||||
};
|
||||
settings.space-list = {
|
||||
CanonicalDomains = [
|
||||
"example.org"
|
||||
"corp.example"
|
||||
];
|
||||
ChannelTimeout = [
|
||||
"session=5m"
|
||||
"direct-tcpip=30s"
|
||||
];
|
||||
GlobalKnownHostsFile = [
|
||||
"~/.ssh/known_hosts"
|
||||
"~/.ssh/known_hosts2"
|
||||
];
|
||||
UserKnownHostsFile = [
|
||||
"~/.ssh/user_known_hosts"
|
||||
"~/.ssh/user_known_hosts2"
|
||||
];
|
||||
PermitRemoteOpen = [
|
||||
"localhost:8080"
|
||||
"example.org:443"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.ssh/config
|
||||
assertFileContent \
|
||||
home-files/.ssh/config \
|
||||
${./extra-option-overrides-expected.conf}
|
||||
'';
|
||||
}
|
||||
@@ -3,9 +3,9 @@
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
settings = {
|
||||
dynamicBindPathWithPort = {
|
||||
dynamicForwards = [
|
||||
DynamicForward = [
|
||||
{
|
||||
# Error:
|
||||
address = "/run/user/1000/gnupg/S.gpg-agent.extra";
|
||||
|
||||
@@ -3,7 +3,3 @@ Host dynamicBindAddressWithPort
|
||||
|
||||
Host dynamicBindPathNoPort
|
||||
DynamicForward /run/user/1000/gnupg/S.gpg-agent.extra
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
settings = {
|
||||
dynamicBindPathNoPort = {
|
||||
dynamicForwards = [
|
||||
DynamicForward = [
|
||||
{
|
||||
# OK:
|
||||
address = "/run/user/1000/gnupg/S.gpg-agent.extra";
|
||||
@@ -15,7 +15,7 @@
|
||||
};
|
||||
|
||||
dynamicBindAddressWithPort = {
|
||||
dynamicForwards = [
|
||||
DynamicForward = [
|
||||
{
|
||||
# OK:
|
||||
address = "127.0.0.1";
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
settings = {
|
||||
localBindPathWithPort = {
|
||||
localForwards = [
|
||||
LocalForward = [
|
||||
{
|
||||
# OK:
|
||||
host.address = "127.0.0.1";
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
settings = {
|
||||
localHostPathWithPort = {
|
||||
localForwards = [
|
||||
LocalForward = [
|
||||
{
|
||||
# OK:
|
||||
bind.address = "127.0.0.1";
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
settings = {
|
||||
remoteBindPathWithPort = {
|
||||
remoteForwards = [
|
||||
RemoteForward = [
|
||||
{
|
||||
# OK:
|
||||
host.address = "127.0.0.1";
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
settings = {
|
||||
remoteHostPathWithPort = {
|
||||
remoteForwards = [
|
||||
RemoteForward = [
|
||||
{
|
||||
# OK:
|
||||
bind.address = "127.0.0.1";
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
Host * !github.com
|
||||
Port 516
|
||||
IdentityFile file1
|
||||
IdentityFile file2
|
||||
Port 516
|
||||
|
||||
Host abc
|
||||
ProxyJump jump-host
|
||||
|
||||
Host xyz
|
||||
SetEnv BAR="_bar_ 42" FOO="foo12"
|
||||
ServerAliveInterval 60
|
||||
ServerAliveCountMax 10
|
||||
DynamicForward [localhost]:2839
|
||||
IdentityFile file
|
||||
KexAlgorithms sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,mlkem768x25519-sha256
|
||||
LocalForward [localhost]:8080 [10.0.0.1]:80
|
||||
RemoteForward [localhost]:8081 [10.0.0.2]:80
|
||||
RemoteForward /run/user/1000/gnupg/S.gpg-agent.extra /run/user/1000/gnupg/S.gpg-agent
|
||||
DynamicForward [localhost]:2839
|
||||
KexAlgorithms sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,mlkem768x25519-sha256
|
||||
ServerAliveCountMax 10
|
||||
ServerAliveInterval 60
|
||||
SetEnv BAR="_bar_ 42" BAZ="with \" some \\ very \\\" fun \\\\ escapes" FOO="foo12"
|
||||
|
||||
Host ordered
|
||||
Port 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
{
|
||||
config = {
|
||||
programs.ssh = {
|
||||
@@ -43,6 +48,7 @@
|
||||
setEnv = {
|
||||
FOO = "foo12";
|
||||
BAR = "_bar_ 42";
|
||||
BAZ = ''with " some \ very \" fun \\ escapes'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -60,6 +66,12 @@
|
||||
map (a: a.message) (lib.filter (a: !a.assertion) config.assertions)
|
||||
);
|
||||
|
||||
test.asserts.warnings.expected = [
|
||||
''
|
||||
`programs.ssh.matchBlocks` defined in ${lib.showFiles options.programs.ssh.matchBlocks.files} is deprecated. Use `programs.ssh.settings`.
|
||||
''
|
||||
];
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.ssh/config
|
||||
assertFileContent \
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
Host legacy
|
||||
HostName example.org
|
||||
User typed-user
|
||||
ForwardAgent yes
|
||||
HostName extra.example.org
|
||||
User extra-user
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
{
|
||||
config = {
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks.legacy = {
|
||||
user = "typed-user";
|
||||
hostname = "example.org";
|
||||
extraOptions = {
|
||||
ForwardAgent = "yes";
|
||||
HostName = "extra.example.org";
|
||||
User = "extra-user";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home.file.assertions.text = builtins.toJSON (
|
||||
map (a: a.message) (lib.filter (a: !a.assertion) config.assertions)
|
||||
);
|
||||
|
||||
test.asserts.warnings.expected = [
|
||||
''
|
||||
`programs.ssh.matchBlocks` defined in ${lib.showFiles options.programs.ssh.matchBlocks.files} is deprecated. Use `programs.ssh.settings`.
|
||||
''
|
||||
''
|
||||
`programs.ssh.matchBlocks.legacy.extraOptions` defined in ${lib.showFiles options.programs.ssh.matchBlocks.files} is deprecated. Move these OpenSSH options to `programs.ssh.settings.legacy` using upstream directive names.
|
||||
''
|
||||
];
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.ssh/config
|
||||
assertFileContent \
|
||||
home-files/.ssh/config \
|
||||
${./match-blocks-extra-options-duplicates-expected.conf}
|
||||
assertFileContent home-files/assertions ${./no-assertions.json}
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -6,7 +6,3 @@ Host abc
|
||||
|
||||
Match host xyz canonical
|
||||
Port 2223
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
{
|
||||
config = {
|
||||
programs.ssh = {
|
||||
@@ -24,6 +29,12 @@
|
||||
map (a: a.message) (lib.filter (a: !a.assertion) config.assertions)
|
||||
);
|
||||
|
||||
test.asserts.warnings.expected = [
|
||||
''
|
||||
`programs.ssh.matchBlocks` defined in ${lib.showFiles options.programs.ssh.matchBlocks.files} is deprecated. Use `programs.ssh.settings`.
|
||||
''
|
||||
];
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.ssh/config
|
||||
assertFileContent \
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
|
||||
|
||||
Host *
|
||||
ForwardAgent no
|
||||
ServerAliveInterval 0
|
||||
ServerAliveCountMax 3
|
||||
Compression no
|
||||
AddKeysToAgent no
|
||||
HashKnownHosts no
|
||||
UserKnownHostsFile ~/.ssh/known_hosts
|
||||
Compression no
|
||||
ControlMaster no
|
||||
ControlPath ~/.ssh/master-%r@%n:%p
|
||||
ControlPersist no
|
||||
|
||||
|
||||
ForwardAgent no
|
||||
HashKnownHosts no
|
||||
ServerAliveCountMax 3
|
||||
ServerAliveInterval 0
|
||||
UserKnownHostsFile ~/.ssh/known_hosts
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
|
||||
|
||||
Host *
|
||||
ForwardAgent no
|
||||
ServerAliveInterval 0
|
||||
ServerAliveCountMax 3
|
||||
Compression no
|
||||
AddKeysToAgent no
|
||||
HashKnownHosts no
|
||||
UserKnownHostsFile ~/.ssh/known_hosts
|
||||
Compression no
|
||||
ControlMaster no
|
||||
ControlPath ~/.ssh/master-%r@%n:%p
|
||||
ControlPersist no
|
||||
ForwardAgent no
|
||||
HashKnownHosts no
|
||||
ServerAliveCountMax 3
|
||||
ServerAliveInterval 0
|
||||
UserKnownHostsFile ~/.ssh/known_hosts
|
||||
|
||||
MyExtraOption no
|
||||
AnotherOption 3
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
`programs.ssh` default values will be removed in the future.
|
||||
Consider setting `programs.ssh.enableDefaultConfig` to false,
|
||||
and manually set the default values you want to keep at
|
||||
`programs.ssh.matchBlocks."*"`.
|
||||
`programs.ssh.settings."*"`.
|
||||
''
|
||||
];
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
`programs.ssh` default values will be removed in the future.
|
||||
Consider setting `programs.ssh.enableDefaultConfig` to false,
|
||||
and manually set the default values you want to keep at
|
||||
`programs.ssh.matchBlocks."*"`.
|
||||
`programs.ssh.settings."*"`.
|
||||
''
|
||||
];
|
||||
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
|
||||
|
||||
Host *
|
||||
ForwardAgent yes
|
||||
ServerAliveInterval 1
|
||||
ServerAliveCountMax 2
|
||||
Compression yes
|
||||
AddKeysToAgent yes
|
||||
HashKnownHosts yes
|
||||
UserKnownHostsFile ~/.ssh/my_known_hosts
|
||||
Compression yes
|
||||
ControlMaster yes
|
||||
ControlPath ~/.ssh/myfile-%r@%n:%p
|
||||
ControlPersist 10m
|
||||
|
||||
|
||||
ForwardAgent yes
|
||||
HashKnownHosts yes
|
||||
ServerAliveCountMax 2
|
||||
ServerAliveInterval 1
|
||||
UserKnownHostsFile ~/.ssh/my_known_hosts
|
||||
|
||||
@@ -18,7 +18,19 @@
|
||||
|
||||
test.asserts.warnings.expected =
|
||||
let
|
||||
renamedOptions = [
|
||||
renamedOptions = {
|
||||
forwardAgent = "ForwardAgent";
|
||||
addKeysToAgent = "AddKeysToAgent";
|
||||
compression = "Compression";
|
||||
serverAliveInterval = "ServerAliveInterval";
|
||||
serverAliveCountMax = "ServerAliveCountMax";
|
||||
hashKnownHosts = "HashKnownHosts";
|
||||
userKnownHostsFile = "UserKnownHostsFile";
|
||||
controlMaster = "ControlMaster";
|
||||
controlPath = "ControlPath";
|
||||
controlPersist = "ControlPersist";
|
||||
};
|
||||
renamedOptionOrder = [
|
||||
"controlPersist"
|
||||
"controlPath"
|
||||
"controlMaster"
|
||||
@@ -32,11 +44,14 @@
|
||||
];
|
||||
in
|
||||
map (
|
||||
o:
|
||||
"The option `programs.ssh.${o}' defined in ${
|
||||
lib.showFiles options.programs.ssh.${o}.files
|
||||
} has been renamed to `programs.ssh.matchBlocks.*.${o}'."
|
||||
) renamedOptions;
|
||||
old:
|
||||
let
|
||||
new = renamedOptions.${old};
|
||||
in
|
||||
"The option `programs.ssh.${old}' defined in ${
|
||||
lib.showFiles options.programs.ssh.${old}.files
|
||||
} has been renamed to `programs.ssh.settings.*.${new}'."
|
||||
) renamedOptionOrder;
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.ssh/config
|
||||
|
||||
31
tests/modules/programs/ssh/settings-expected.conf
Normal file
31
tests/modules/programs/ssh/settings-expected.conf
Normal file
@@ -0,0 +1,31 @@
|
||||
Host *.corp !bastion.corp
|
||||
ProxyJump bastion-a.corp,bastion-b.corp
|
||||
SendEnv LANG LC_*
|
||||
User corp
|
||||
|
||||
Host github
|
||||
CertificateFile ~/.ssh/github-cert.pub
|
||||
CertificateFile ~/.ssh/github-alt-cert.pub
|
||||
HostName github.com
|
||||
IdentitiesOnly yes
|
||||
IdentityAgent ~/.ssh/agent
|
||||
IdentityAgent SSH_AUTH_SOCK
|
||||
IdentityFile ~/.ssh/github
|
||||
User git
|
||||
|
||||
Match host *.corp exec "test -f ~/.corp"
|
||||
IgnoreUnknown PubkeyAcceptedAlgorithms,PubkeyAcceptedKeyTypes
|
||||
CASignatureAlgorithms ssh-ed25519,rsa-sha2-512
|
||||
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
|
||||
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512
|
||||
HostbasedAcceptedAlgorithms ssh-ed25519,rsa-sha2-512
|
||||
HostbasedKeyTypes ssh-ed25519,rsa-sha2-512
|
||||
KbdInteractiveDevices bsdauth,pam
|
||||
KexAlgorithms sntrup761x25519-sha512,mlkem768x25519-sha256
|
||||
LocalForward [localhost]:8080 [10.0.0.1]:80
|
||||
LocalForward 9000 10.0.0.2:90
|
||||
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
|
||||
PreferredAuthentications publickey,keyboard-interactive
|
||||
PubkeyAcceptedAlgorithms ssh-ed25519,rsa-sha2-512
|
||||
PubkeyAcceptedKeyTypes ssh-ed25519,rsa-sha2-512
|
||||
SetEnv BAR="bar baz" BAZ="with \" some \\ very \\\" fun \\\\ escapes" FOO="foo"
|
||||
@@ -0,0 +1,17 @@
|
||||
{ lib, options, ... }:
|
||||
{
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
settings.legacy.extraOptions = {
|
||||
AddKeysToAgent = "yes";
|
||||
HostName = "example.org";
|
||||
};
|
||||
};
|
||||
|
||||
test.asserts.assertions.expected = [
|
||||
''
|
||||
`programs.ssh.settings.*.extraOptions` defined in ${lib.showFiles options.programs.ssh.settings.files} is not supported. Move these OpenSSH options directly into `programs.ssh.settings.*` using upstream directive names.
|
||||
''
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Host raw
|
||||
DynamicForward 127.0.0.1:1080
|
||||
LocalForward 9000 10.0.0.2:90
|
||||
RemoteForward 9001 10.0.0.3:91
|
||||
26
tests/modules/programs/ssh/settings-raw-forwards.nix
Normal file
26
tests/modules/programs/ssh/settings-raw-forwards.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config = {
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
settings.raw = {
|
||||
LocalForward = "9000 10.0.0.2:90";
|
||||
RemoteForward = [ "9001 10.0.0.3:91" ];
|
||||
DynamicForward = "127.0.0.1:1080";
|
||||
};
|
||||
};
|
||||
|
||||
home.file.assertions.text = builtins.toJSON (
|
||||
map (a: a.message) (lib.filter (a: !a.assertion) config.assertions)
|
||||
);
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.ssh/config
|
||||
assertFileContent \
|
||||
home-files/.ssh/config \
|
||||
${./settings-raw-forwards-expected.conf}
|
||||
assertFileContent home-files/assertions ${./no-assertions.json}
|
||||
'';
|
||||
};
|
||||
}
|
||||
113
tests/modules/programs/ssh/settings.nix
Normal file
113
tests/modules/programs/ssh/settings.nix
Normal file
@@ -0,0 +1,113 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config = {
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
enableDefaultConfig = false;
|
||||
settings = {
|
||||
github = {
|
||||
HostName = "github.com";
|
||||
User = "git";
|
||||
IdentityFile = "~/.ssh/github";
|
||||
IdentityAgent = [
|
||||
"~/.ssh/agent"
|
||||
"SSH_AUTH_SOCK"
|
||||
];
|
||||
CertificateFile = [
|
||||
"~/.ssh/github-cert.pub"
|
||||
"~/.ssh/github-alt-cert.pub"
|
||||
];
|
||||
IdentitiesOnly = true;
|
||||
};
|
||||
|
||||
"Host *.corp !bastion.corp" = lib.hm.dag.entryBefore [ "github" ] {
|
||||
User = "corp";
|
||||
ProxyJump = [
|
||||
"bastion-a.corp"
|
||||
"bastion-b.corp"
|
||||
];
|
||||
SendEnv = [
|
||||
"LANG"
|
||||
"LC_*"
|
||||
];
|
||||
};
|
||||
|
||||
"Match host *.corp exec \"test -f ~/.corp\"" = lib.hm.dag.entryAfter [ "github" ] {
|
||||
SetEnv = {
|
||||
FOO = "foo";
|
||||
BAR = "bar baz";
|
||||
BAZ = ''with " some \ very \" fun \\ escapes'';
|
||||
};
|
||||
IgnoreUnknown = [
|
||||
"PubkeyAcceptedAlgorithms"
|
||||
"PubkeyAcceptedKeyTypes"
|
||||
];
|
||||
Ciphers = [
|
||||
"chacha20-poly1305@openssh.com"
|
||||
"aes256-gcm@openssh.com"
|
||||
];
|
||||
CASignatureAlgorithms = [
|
||||
"ssh-ed25519"
|
||||
"rsa-sha2-512"
|
||||
];
|
||||
HostbasedAcceptedAlgorithms = [
|
||||
"ssh-ed25519"
|
||||
"rsa-sha2-512"
|
||||
];
|
||||
HostbasedKeyTypes = [
|
||||
"ssh-ed25519"
|
||||
"rsa-sha2-512"
|
||||
];
|
||||
HostKeyAlgorithms = [
|
||||
"ssh-ed25519"
|
||||
"rsa-sha2-512"
|
||||
];
|
||||
KbdInteractiveDevices = [
|
||||
"bsdauth"
|
||||
"pam"
|
||||
];
|
||||
KexAlgorithms = [
|
||||
"sntrup761x25519-sha512"
|
||||
"mlkem768x25519-sha256"
|
||||
];
|
||||
MACs = [
|
||||
"hmac-sha2-256-etm@openssh.com"
|
||||
"hmac-sha2-512-etm@openssh.com"
|
||||
];
|
||||
PreferredAuthentications = [
|
||||
"publickey"
|
||||
"keyboard-interactive"
|
||||
];
|
||||
PubkeyAcceptedAlgorithms = [
|
||||
"ssh-ed25519"
|
||||
"rsa-sha2-512"
|
||||
];
|
||||
PubkeyAcceptedKeyTypes = [
|
||||
"ssh-ed25519"
|
||||
"rsa-sha2-512"
|
||||
];
|
||||
LocalForward = [
|
||||
{
|
||||
bind.port = 8080;
|
||||
host.address = "10.0.0.1";
|
||||
host.port = 80;
|
||||
}
|
||||
"9000 10.0.0.2:90"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home.file.assertions.text = builtins.toJSON (
|
||||
map (a: a.message) (lib.filter (a: !a.assertion) config.assertions)
|
||||
);
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.ssh/config
|
||||
assertFileContent \
|
||||
home-files/.ssh/config \
|
||||
${./settings-expected.conf}
|
||||
assertFileContent home-files/assertions ${./no-assertions.json}
|
||||
'';
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user