2021-06-22 13:28:29 +02:00
|
|
|
|
<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 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:
|
|
|
|
|
</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
|
|
|
|
|
it’s not well-protected.
|
|
|
|
|
</para>
|
|
|
|
|
<para>
|
|
|
|
|
The file system can be configured in NixOS via the usual
|
2021-07-04 02:24:44 +02:00
|
|
|
|
<link linkend="opt-fileSystems">fileSystems</link> option. Here’s
|
|
|
|
|
a typical setup:
|
2021-06-22 13:28:29 +02:00
|
|
|
|
</para>
|
|
|
|
|
<programlisting language="bash">
|
|
|
|
|
{
|
|
|
|
|
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"
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
</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 =
|
|
|
|
|
[ "ProxyJump=bastion@example.com"
|
|
|
|
|
"Port=22"
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
|
|
|
|
<para>
|
|
|
|
|
It’s 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 [" "] ["\\040"]
|
|
|
|
|
"ssh_command=${pkgs.openssh}/bin/ssh -v -L 8080:localhost:80")
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
</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 you’re having a hard time figuring out why mounting is
|
|
|
|
|
failing, you can add the option
|
|
|
|
|
<literal>"debug"</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 <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.
|
|
|
|
|
</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>
|