nixos/doc: add section on sshfs file systems

This documents how to use sshfs a bit and how to set up an automatically
mounted sshfs filesystem in NixOS. Also it closes #125905.
This commit is contained in:
rnhmjoj 2021-06-22 13:28:29 +02:00 committed by Ryan Mulligan
parent 7c38644d4c
commit 21a5268b26
3 changed files with 244 additions and 0 deletions

View file

@ -54,4 +54,5 @@
</para>
</note>
<xi:include href="luks-file-systems.xml" />
<xi:include href="../from_md/configuration/sshfs-file-systems.section.xml" />
</chapter>

View file

@ -0,0 +1,104 @@
# SSHFS File Systems {#sec-sshfs-file-systems}
[SSHFS][sshfs] is a [FUSE][fuse] filesystem that allows easy access to directories on a remote machine using the SSH File Transfer Protocol (SFTP).
It means that if you have SSH access to a machine, no additional setup is needed to mount a directory.
[sshfs]: https://github.com/libfuse/sshfs
[fuse]: https://en.wikipedia.org/wiki/Filesystem_in_Userspace
## Interactive mounting {#sec-sshfs-interactive}
In NixOS, SSHFS is packaged as <package>sshfs</package>.
Once installed, mounting a directory interactively is simple as running:
```ShellSession
$ sshfs my-user@example.com:/my-dir /mnt/my-dir
```
Like any other FUSE file system, the directory is unmounted using:
```ShellSession
$ fusermount -u /mnt/my-dir
```
## Non-interactive mounting {#sec-sshfs-non-interactive}
Mounting non-interactively requires some precautions because `sshfs` will run at boot and under a different user (root).
For obvious reason, you can't input a password, so public key authentication using an unencrypted key is needed.
To create a new key without a passphrase you can do:
```ShellSession
$ ssh-keygen -t ed25519 -P '' -f example-key
Generating public/private ed25519 key pair.
Your identification has been saved in test-key
Your public key has been saved in test-key.pub
The key fingerprint is:
SHA256:yjxl3UbTn31fLWeyLYTAKYJPRmzknjQZoyG8gSNEoIE my-user@workstation
```
To keep the key safe, change the ownership to `root:root` and make sure the permissions are `600`:
OpenSSH normally refuses to use the key if it's not well-protected.
The file system can be configured in NixOS via the usual [fileSystems](options.html#opt-fileSystems) option.
Here's a typical setup:
```nix
{
system.fsPackages = [ pkgs.sshfs ];
fileSystems."/mnt/my-dir" = {
device = "my-user@example.com:/my-dir/";
fsType = "sshfs";
options =
[ # Filesystem options
"allow_other" # for non-root access
"_netdev" # this is a network fs
"x-systemd.automount" # mount on demand
# SSH options
"reconnect" # handle connection drops
"ServerAliveInterval=15" # keep connections alive
"IdentityFile=/var/secrets/example-key"
];
};
}
```
More options from `ssh_config(5)` can be given as well, for example you can change the default SSH port or specify a jump proxy:
```nix
{
options =
[ "ProxyJump=bastion@example.com"
"Port=22"
];
}
```
It's also possible to change the `ssh` command used by SSHFS to connect to the server.
For example:
```nix
{
options =
[ (builtins.replaceStrings [" "] ["\\040"]
"ssh_command=${pkgs.openssh}/bin/ssh -v -L 8080:localhost:80")
];
}
```
::: {.note}
The escaping of spaces is needed because every option is written to the `/etc/fstab` file, which is a space-separated table.
:::
### Troubleshooting {#sec-sshfs-troubleshooting}
If you're having a hard time figuring out why mounting is failing, you can add the option `"debug"`.
This enables a verbose log in SSHFS that you can access via:
```ShellSession
$ journalctl -u $(systemd-escape -p /mnt/my-dir/).mount
Jun 22 11:41:18 workstation mount[87790]: SSHFS version 3.7.1
Jun 22 11:41:18 workstation mount[87793]: executing <ssh> <-x> <-a> <-oClearAllForwardings=yes> <-oServerAliveInterval=15> <-oIdentityFile=/var/secrets/wrong-key> <-2> <my-user@example.com> <-s> <sftp>
Jun 22 11:41:19 workstation mount[87793]: my-user@example.com: Permission denied (publickey).
Jun 22 11:41:19 workstation mount[87790]: read: Connection reset by peer
Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Mount process exited, code=exited, status=1/FAILURE
Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Failed with result 'exit-code'.
Jun 22 11:41:19 workstation systemd[1]: Failed to mount /mnt/my-dir.
Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Consumed 54ms CPU time, received 2.3K IP traffic, sent 2.7K IP traffic.
```
::: {.note}
If the mount point contains special characters it needs to be escaped using `systemd-escape`.
This is due to the way systemd converts paths into unit names.
:::

View file

@ -0,0 +1,139 @@
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-sshfs-file-systems">
<title>SSHFS File Systems</title>
<para>
<link xlink:href="https://github.com/libfuse/sshfs">SSHFS</link> is
a
<link xlink:href="https://en.wikipedia.org/wiki/Filesystem_in_Userspace">FUSE</link>
filesystem that allows easy access to directories on a remote
machine using the SSH File Transfer Protocol (SFTP). It means that
if you have SSH access to a machine, no additional setup is needed
to mount a directory.
</para>
<section xml:id="sec-sshfs-interactive">
<title>Interactive mounting</title>
<para>
In NixOS, SSHFS is packaged as <package>sshfs</package>. Once
installed, mounting a directory interactively is simple as
running:
</para>
<programlisting>
$ sshfs my-user@example.com:/my-dir /mnt/my-dir
</programlisting>
<para>
Like any other FUSE file system, the directory is unmounted using:
</para>
<programlisting>
$ fusermount -u /mnt/my-dir
</programlisting>
</section>
<section xml:id="sec-sshfs-non-interactive">
<title>Non-interactive mounting</title>
<para>
Mounting non-interactively requires some precautions because
<literal>sshfs</literal> will run at boot and under a different
user (root). For obvious reason, you cant input a password, so
public key authentication using an unencrypted key is needed. To
create a new key without a passphrase you can do:
</para>
<programlisting>
$ ssh-keygen -t ed25519 -P '' -f example-key
Generating public/private ed25519 key pair.
Your identification has been saved in test-key
Your public key has been saved in test-key.pub
The key fingerprint is:
SHA256:yjxl3UbTn31fLWeyLYTAKYJPRmzknjQZoyG8gSNEoIE my-user@workstation
</programlisting>
<para>
To keep the key safe, change the ownership to
<literal>root:root</literal> and make sure the permissions are
<literal>600</literal>: OpenSSH normally refuses to use the key if
its not well-protected.
</para>
<para>
The file system can be configured in NixOS via the usual
<link xlink:href="options.html#opt-fileSystems">fileSystems</link>
option. Heres a typical setup:
</para>
<programlisting language="bash">
{
system.fsPackages = [ pkgs.sshfs ];
fileSystems.&quot;/mnt/my-dir&quot; = {
device = &quot;my-user@example.com:/my-dir/&quot;;
fsType = &quot;sshfs&quot;;
options =
[ # Filesystem options
&quot;allow_other&quot; # for non-root access
&quot;_netdev&quot; # this is a network fs
&quot;x-systemd.automount&quot; # mount on demand
# SSH options
&quot;reconnect&quot; # handle connection drops
&quot;ServerAliveInterval=15&quot; # keep connections alive
&quot;IdentityFile=/var/secrets/example-key&quot;
];
};
}
</programlisting>
<para>
More options from <literal>ssh_config(5)</literal> can be given as
well, for example you can change the default SSH port or specify a
jump proxy:
</para>
<programlisting language="bash">
{
options =
[ &quot;ProxyJump=bastion@example.com&quot;
&quot;Port=22&quot;
];
}
</programlisting>
<para>
Its also possible to change the <literal>ssh</literal> command
used by SSHFS to connect to the server. For example:
</para>
<programlisting language="bash">
{
options =
[ (builtins.replaceStrings [&quot; &quot;] [&quot;\\040&quot;]
&quot;ssh_command=${pkgs.openssh}/bin/ssh -v -L 8080:localhost:80&quot;)
];
}
</programlisting>
<note>
<para>
The escaping of spaces is needed because every option is written
to the <literal>/etc/fstab</literal> file, which is a
space-separated table.
</para>
</note>
<section xml:id="sec-sshfs-troubleshooting">
<title>Troubleshooting</title>
<para>
If youre having a hard time figuring out why mounting is
failing, you can add the option
<literal>&quot;debug&quot;</literal>. This enables a verbose log
in SSHFS that you can access via:
</para>
<programlisting>
$ journalctl -u $(systemd-escape -p /mnt/my-dir/).mount
Jun 22 11:41:18 workstation mount[87790]: SSHFS version 3.7.1
Jun 22 11:41:18 workstation mount[87793]: executing &lt;ssh&gt; &lt;-x&gt; &lt;-a&gt; &lt;-oClearAllForwardings=yes&gt; &lt;-oServerAliveInterval=15&gt; &lt;-oIdentityFile=/var/secrets/wrong-key&gt; &lt;-2&gt; &lt;my-user@example.com&gt; &lt;-s&gt; &lt;sftp&gt;
Jun 22 11:41:19 workstation mount[87793]: my-user@example.com: Permission denied (publickey).
Jun 22 11:41:19 workstation mount[87790]: read: Connection reset by peer
Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Mount process exited, code=exited, status=1/FAILURE
Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Failed with result 'exit-code'.
Jun 22 11:41:19 workstation systemd[1]: Failed to mount /mnt/my-dir.
Jun 22 11:41:19 workstation systemd[1]: mnt-my\x2ddir.mount: Consumed 54ms CPU time, received 2.3K IP traffic, sent 2.7K IP traffic.
</programlisting>
<note>
<para>
If the mount point contains special characters it needs to be
escaped using <literal>systemd-escape</literal>. This is due
to the way systemd converts paths into unit names.
</para>
</note>
</section>
</section>
</section>