Jump to content

SSH public key authentication: Difference between revisions

From NixOS Wiki
Pigs (talk | contribs)
Refactored and cleaned up page, added opening
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
SSH key authentication uses a [https://en.wikipedia.org/wiki/Public-key_cryptography pair of cryptographic keys]; a private key stored on the client and a public key placed on the server in order to verify identity without transmitting passwords over the network.
On NixOS, SSH key authentication is typically managed using [[SSH|OpenSSH]], which is included by default and can be configured both declaratively in configuration.nix and interactively using standard SSH tools.
== Generating an SSH key pair ==
To setup a public key based SSH connection from <code>your-machine</code> (client) to <code>another-machine</code> (server):
To setup a public key based SSH connection from <code>your-machine</code> (client) to <code>another-machine</code> (server):


<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
[user@your-machine] $ ssh-keygen -f ~/.ssh/another-machine
$ ssh-keygen -f ~/.ssh/another-machine
[user@your-machine] $ ssh-copy-id -i ~/.ssh/another-machine another-machine-host-or-ip
$ ssh-copy-id -i ~/.ssh/another-machine -p22 another-machine-host-or-ip
</syntaxhighlight>
</syntaxhighlight>


In case <code>another-machine</code> uses another port for SSH connections use this command instead:
This copies the public key to <code>another-machine</code>, placing it in the user’s <code>~/.ssh/authorized_keys</code> file.
<syntaxhighlight lang="console">
[user@your-machine] $ ssh-copy-id -i ~/.ssh/another-machine -p1234 another-machine-host-or-ip
</syntaxhighlight>
 
Now the public key is stored on the <code>another-machine</code> in <code>/home/user/.ssh/authorized_keys</code>


On <code>your-machine</code>, we stored the key file in the non-standard path <code>~/.ssh/another-machine</code>, so we must tell the SSH client to use the key file:
On <code>your-machine</code>, we stored the key file in the non-standard path <code>~/.ssh/another-machine</code>, so we must tell the SSH client to use the key file:


<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
[user@clientmachine] $ ssh -i ~/.ssh/another-machine another-machine-host-or-ip
$ ssh -i ~/.ssh/another-machine another-machine-host-or-ip
</syntaxhighlight>
</syntaxhighlight>


The connection should work without password.
The connection should now succeed without prompting for a password.


To make the SSH client automatically use the key file, we add this to <code>/home/user/.ssh/config</code>:
To make the SSH client automatically use the key file, add a host entry to your per-user SSH configuration file:


<syntaxhighlight>
{{file|~/.ssh/config|bash|
<nowiki>
Host another-machine
Host another-machine
   HostName 192.168.1.105 # another-machine-host-or-ip
   HostName 192.168.1.105 # another-machine-host-or-ip
Line 32: Line 34:
   IdentitiesOnly yes
   IdentitiesOnly yes
   IdentityFile ~/.ssh/another-machine
   IdentityFile ~/.ssh/another-machine
</syntaxhighlight>
</nowiki>
}}


== SSH agent ==
== SSH agent ==
A ssh private key, for which a phrase is defined, can be clumsy if you use it multiple times. It is possible to store the private key identity in a ssh-agent. The ssh-agent uses the ssh private key identity when you issue a ssh command, for instance when using ssh to connect.
A ssh private key, for which a phrase is defined, can be clumsy if you use it multiple times. It is possible to store the private key identity in a ssh-agent. The ssh-agent uses the ssh private key identity when you issue a ssh command, for instance when using ssh to connect.


Line 44: Line 48:
NixOS will start a user systemd service with the ssh-agent at login. You can see the service with the command <code>systemctl --user status ssh-agent</code>.
NixOS will start a user systemd service with the ssh-agent at login. You can see the service with the command <code>systemctl --user status ssh-agent</code>.


It provides also the environment variable $SSH_AUTH_SOCK which refers to <code>/run/user/1000/ssh-agent</code> , in this case for user id 1000.
It provides also the environment variable <code>$SSH_AUTH_SOCK</code> which refers to <code>/run/user/1000/ssh-agent</code> , in this case for user id 1000.


If you want to use a ssh key pair for authenticating, you can add this to the ssh-agent using the command ssh-add entering the phrase only once.
If you want to use a ssh key pair for authenticating, you can add this to the ssh-agent using the command ssh-add entering the phrase only once.


<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
[user@your-machine] $ ssh-add .ssh/id_rsa
$ ssh-add .ssh/id_rsa
Enter passphrase for .ssh/id_rsa:  
Enter passphrase for .ssh/id_rsa:  
Identity added: .ssh/id_rsa (myaccounts@mymachine)
Identity added: .ssh/id_rsa (myaccounts@mymachine)
Line 56: Line 60:
If you store the ssh public key with the command ssh-copy-id on <code>another-machine</code> as shown above, you can logon without giving a password or phrase.
If you store the ssh public key with the command ssh-copy-id on <code>another-machine</code> as shown above, you can logon without giving a password or phrase.


== SSH server config ==
== SSH server configuration ==
 
You can manage SSH authorized public keys declaratively by adding them to your system to your system configuration:
 
{{file|/etc/nixos/configuration.nix|nix|
<nowiki>
  users.users."myUser".openssh.authorizedKeys.keys = [
    "ssh-rsa AAAAB3Nz....6OWM= user" # content of authorized_keys file
    # note: ssh-copy-id will add user@your-machine after the public key
    # but we can remove the "@your-machine" part
  ];
</nowiki>
}}
 
Alternatively, you can reference a custom file containing the authorized keys:


Optionally, on the NixOS-based <code>another-machine</code>, we can set <code>passwordAuthentication = false;</code> to require public key authentication for better security.
{{file|/etc/nixos/configuration.nix|nix|
<nowiki>
  users.users."user".openssh.authorizedKeys.keyFiles = [
    /etc/nixos/ssh/authorized_keys
  ];
</nowiki>
}}


<syntaxhighlight lang="nix">
For additional configuration options, see the {{nixos:option|users.users.*.openssh}} module documentation.
services.openssh = {
  enable = true;
  # require public key authentication for better security
  settings.PasswordAuthentication = false;
  settings.KbdInteractiveAuthentication = false;
  #settings.PermitRootLogin = "yes";
};
</syntaxhighlight>


We can also store the public keys in <code>/etc/nixos/configuration.nix</code>:
After configuring user keys, it is recommended to improve server security by disabling password-based authentication and requiring public key authentication. This can be done on a NixOS-based server (e.g. <code>another-machine</code>). For additional security measures, see [[SSH#Security hardening]].


<syntaxhighlight lang="nix">
This can be configured in your system configuration:
users.users."user".openssh.authorizedKeys.keys = [
  "ssh-rsa AAAAB3Nz....6OWM= user" # content of authorized_keys file
  # note: ssh-copy-id will add user@your-machine after the public key
  # but we can remove the "@your-machine" part
];
</syntaxhighlight>


... or use a custom path for the <code>authorized_keys</code> file:
{{file|/etc/nixos/configuration.nix|nix|
<nowiki>
  services.openssh = {
    enable = true;
    # require public key authentication for better security
    settings.PasswordAuthentication = false;
    settings.KbdInteractiveAuthentication = false;
};
</nowiki>
}}


<syntaxhighlight lang="nix">
== Tips and tricks ==
users.users."user".openssh.authorizedKeys.keyFiles = [
  /etc/nixos/ssh/authorized_keys
];
</syntaxhighlight>


== KDE ==
=== KDE ===


By default, KDE prompts you to enter the passwords for your SSH keys to unlock them across session starts. To avoid being asked to unlock your SSH keys every time a session is restarted (e.g., after logging out or rebooting), you can use <code>ksshaskpass</code> to store the passwords. To enable this, make the following changes to your configuration:
By default, KDE prompts you to enter the passwords for your SSH keys to unlock them across session starts. To avoid being asked to unlock your SSH keys every time a session is restarted (e.g., after logging out or rebooting), you can use <code>ksshaskpass</code> to store the passwords. To enable this, make the following changes to your configuration:
Line 96: Line 111:
   startAgent = true;
   startAgent = true;
   enableAskPassword = true;
   enableAskPassword = true;
  askPassword = pkgs.lib.mkForce "${pkgs.ksshaskpass.out}/bin/ksshaskpass";
};
};


Line 103: Line 117:
};
};
</syntaxhighlight>
</syntaxhighlight>
{{Note | It is also possible to add {{ic|SSH_ASKPASS}} to your environment variables, but you will likely encounter complaints when running {{ic|nixos-rebuild}}. You can add {{ic|lib.mkForce}} to {{ic|SSH_ASKPASS}} to circumvent the error, like this:<br />{{ic|1=SSH_ASKPASS = lib.mkForce "${pkgs.ksshaskpass.out}/bin/ksshaskpass";}}.
}}


After applying these changes, either log out (if you used <code>switch</code>) or reboot (if you used <code>boot</code> for the variables to take effect.
After applying these changes, either log out (if you used <code>switch</code>) or reboot (if you used <code>boot</code> for the variables to take effect.
Line 113: Line 124:
== See also ==
== See also ==


* [[SSH]]
* [[Distributed build]]
* [[Distributed build]]
[[Category:Networking]]
[[Category:Server]]

Latest revision as of 17:04, 13 May 2025

SSH key authentication uses a pair of cryptographic keys; a private key stored on the client and a public key placed on the server in order to verify identity without transmitting passwords over the network.

On NixOS, SSH key authentication is typically managed using OpenSSH, which is included by default and can be configured both declaratively in configuration.nix and interactively using standard SSH tools.

Generating an SSH key pair

To setup a public key based SSH connection from your-machine (client) to another-machine (server):

$ ssh-keygen -f ~/.ssh/another-machine
$ ssh-copy-id -i ~/.ssh/another-machine -p22 another-machine-host-or-ip

This copies the public key to another-machine, placing it in the user’s ~/.ssh/authorized_keys file.

On your-machine, we stored the key file in the non-standard path ~/.ssh/another-machine, so we must tell the SSH client to use the key file:

$ ssh -i ~/.ssh/another-machine another-machine-host-or-ip

The connection should now succeed without prompting for a password.

To make the SSH client automatically use the key file, add a host entry to your per-user SSH configuration file:

≡︎ ~/.ssh/config
Host another-machine
  HostName 192.168.1.105 # another-machine-host-or-ip
  #Port 22
  #User user

  # Prevent using ssh-agent or another keyfile, useful for testing
  IdentitiesOnly yes
  IdentityFile ~/.ssh/another-machine

SSH agent

A ssh private key, for which a phrase is defined, can be clumsy if you use it multiple times. It is possible to store the private key identity in a ssh-agent. The ssh-agent uses the ssh private key identity when you issue a ssh command, for instance when using ssh to connect.

To define NixOS to setup a ssh-agent, add this to your configuration:

programs.ssh.startAgent = true;

NixOS will start a user systemd service with the ssh-agent at login. You can see the service with the command systemctl --user status ssh-agent.

It provides also the environment variable $SSH_AUTH_SOCK which refers to /run/user/1000/ssh-agent , in this case for user id 1000.

If you want to use a ssh key pair for authenticating, you can add this to the ssh-agent using the command ssh-add entering the phrase only once.

$ ssh-add .ssh/id_rsa
Enter passphrase for .ssh/id_rsa: 
Identity added: .ssh/id_rsa (myaccounts@mymachine)

If you store the ssh public key with the command ssh-copy-id on another-machine as shown above, you can logon without giving a password or phrase.

SSH server configuration

You can manage SSH authorized public keys declaratively by adding them to your system to your system configuration:

❄︎ /etc/nixos/configuration.nix
  users.users."myUser".openssh.authorizedKeys.keys = [
    "ssh-rsa AAAAB3Nz....6OWM= user" # content of authorized_keys file
    # note: ssh-copy-id will add user@your-machine after the public key
    # but we can remove the "@your-machine" part
  ];

Alternatively, you can reference a custom file containing the authorized keys:

❄︎ /etc/nixos/configuration.nix
  users.users."user".openssh.authorizedKeys.keyFiles = [
    /etc/nixos/ssh/authorized_keys
  ];

For additional configuration options, see the users.users.*.openssh module documentation.

After configuring user keys, it is recommended to improve server security by disabling password-based authentication and requiring public key authentication. This can be done on a NixOS-based server (e.g. another-machine). For additional security measures, see SSH#Security hardening.

This can be configured in your system configuration:

❄︎ /etc/nixos/configuration.nix
  services.openssh = {
    enable = true;
    # require public key authentication for better security
    settings.PasswordAuthentication = false;
    settings.KbdInteractiveAuthentication = false;
};

Tips and tricks

KDE

By default, KDE prompts you to enter the passwords for your SSH keys to unlock them across session starts. To avoid being asked to unlock your SSH keys every time a session is restarted (e.g., after logging out or rebooting), you can use ksshaskpass to store the passwords. To enable this, make the following changes to your configuration:

programs.ssh = {
  startAgent = true;
  enableAskPassword = true;
};

environment.variables = {
  SSH_ASKPASS_REQUIRE = "prefer";
};

After applying these changes, either log out (if you used switch) or reboot (if you used boot for the variables to take effect.

When you use an SSH key for the first time, you will be prompted to enter its passphrase. Be sure to select the "Remember password" checkbox and the passphrase will be securely stored in the KDE Wallet and automatically retrieved across session restarts.

See also