summary refs log tree commit diff
path: root/nixos/doc/manual/from_md/configuration/sshfs-file-systems.section.xml
blob: 5d74712f35dc3aaf7408674f5994bf74bd7d0e9a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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 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
      <link linkend="opt-fileSystems">fileSystems</link> option. Here’s
      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>
      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 [&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 you’re 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>