Monday, October 3, 2011

Mounting Remote Directories With SSHFS On Debian Squeeze


This tutorial explains how you can mount a directory from a remote server on the local server securely using SSHFS. SSHFS (Secure SHell FileSystem) is a filesystem that serves files/directories securely over SSH, and local users can use them just as if the were local files/directories. On the local computer, the remote share is mounted via FUSE (Filesystem in Userspace). I will use Debian Squeeze for both the local and the remote server.
I do not issue any guarantee that this will work for you!

1 Preliminary Note

I'm using the following two systems in this tutorial:
  • Local system: server1.example.com, IP address: 192.168.0.100
  • Remote system: server2.example.com, IP address: 192.168.0.101
I will show how to use SSHFS as root and also as a normal user.

2 Installing SSHFS

server1:
On the local system, SSHFS must be installed as follows:
apt-get install sshfs
Afterwards, make sure that the fuse kernel module is loaded:
lsmod | grep fuse
root@server1:~# lsmod | grep fuse
fuse                   50625  1
root@server1:~#

3 Using SSHFS As root

server1:
Now I want to mount the remote directory /home/backup (on server2, owned by server2's root user) to the local /backup directory as the local root user.
First add root to the fuse group:
adduser root fuse
Create the local /backup directory and make sure it's owned by root (it should be anyway as you are running these commands as root):
mkdir /backup
chown root /backup
Then mount the remote /home/backup directory to /backup:
sshfs -o idmap=user root@192.168.0.101:/home/backup /backup
(You can use a full path for the remote system, as sown above, or a relative path, like this:
sshfs -o idmap=user root@192.168.0.101:backup /backup
If you use a relative path, this path is relative to the remote user's home directory, so in this case it would be /root/backup. You can even leave out the remote directory, as follows:
sshfs -o idmap=user root@192.168.0.101: /backup
This would then translate to the remote user's home directory - /root in this case.
)
-o idmap=user makes that it does not matter if the local and the remote system use different user IDs - files owned by the remote user are also owned by the local user. If you don't use this, you might get permission problems.
If you connect to the remote host for the first time, you will see a warning about the authenticity of the remote host (if you have connected to the remote host before using ssh or scp, you will not see the warning). In any case, you will be asked for the root password for server2:
root@server1:~# sshfs -o idmap=user root@192.168.0.101:/home/backup /backup
The authenticity of host '192.168.0.101 (192.168.0.101)' can't be established.
RSA key fingerprint is 25:d8:7a:ee:c2:4b:1d:92:a7:3d:16:26:95:56:62:4e.
Are you sure you want to continue connecting (yes/no)?
<-- yes
root@192.168.0.101's password: <-- server2_root_password
root@server1:~#
Let's check if the remote directory got mounted to /backup:
mount
root@server1:~# mount
/dev/sda1 on / type ext3 (rw,errors=remount-ro)
tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
udev on /dev type tmpfs (rw,mode=0755)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)
fusectl on /sys/fs/fuse/connections type fusectl (rw)
root@192.168.0.101:/home/backup on /backup type fuse.sshfs (rw,nosuid,nodev,max_read=65536)
root@server1:~#
df -h
root@server1:~# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              29G  1.2G   26G   5% /
tmpfs                 249M     0  249M   0% /lib/init/rw
udev                  244M  100K  244M   1% /dev
tmpfs                 249M     0  249M   0% /dev/shm
root@192.168.0.101:/home/backup
                       29G  1.2G   27G   5% /backup
root@server1:~#
Looks good!
To unmount the share, run
fusermount -u /backup

3.1 Creating A Private/Public Key Pair On server1

Of course, we don't want to type in a password every time we try to mount the remote share. Therefore we create a private/public key pair and transfer the public key to server2 so that we will not be asked for a password anymore.
server1:
Create a private/public key pair on server1.example.com:
ssh-keygen
root@server1:~# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
 <-- ENTER
Enter passphrase (empty for no passphrase): <-- ENTER
Enter same passphrase again: <-- ENTER
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
b4:22:48:21:99:72:65:3e:1d:93:6f:9a:5c:5f:70:61 root@server1.example.com
The key's randomart image is:
+--[ RSA 2048]----+
|.o..o o.    E.   |
|+..+ ..o  ...    |
|... o ...  o     |
| . . . .+.  .    |
|  . ...=S. .     |
|     .+.  .      |
|                 |
|                 |
|                 |
+-----------------+
root@server1:~#

It is important that you do not enter a passphrase otherwise mounting will not work without human interaction so simply hit ENTER!
Next, we copy our public key to server2.example.com:
ssh-copy-id -i $HOME/.ssh/id_rsa.pub root@192.168.0.101
Now check on server2 if server1's public key has correctly been transferred:
server2:
cat $HOME/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDVdvyYlzgTkjZhDK8S+EZ1fVU/lvLlayKya/u+NY9w6WerYlCxX6nMN9beTXddmlTXg6uXGYAEEnFA36JlOcXz0cr7D8KEzW1vwRtZFJzZ/oH71aDKgrY7M4yRaCsKdElrF+pbq1JT84pEmlOKluVlqGSGvn1Y0W/vrDgl9/j852tkqqIwUg+RjxRbxf13IwWhNOrIiNAFnxhKT9kMVXl9m5Gv5EYk130JNC/uSKTo8uxk5Z+Rq4m7vaIqx0hk8zfLodZ5h4vDnUpwjIhEH+L+3OogeC5bm4zbAYTf4L/5dfobuSsWF88kO/6jAurKmoHShSA5n1YyJoE6ODAgvbpb root@server1.example.com
Now back on server1, try to mount the remote share again (make sure it's unmounted before you run the command):
server1:
sshfs -o idmap=user root@192.168.0.101:/home/backup /backup
If all goes well, you should not be prompted for a password:
root@server1:~# sshfs -o idmap=user root@192.168.0.101:/home/backup /backup
root@server1:~#

3.2 Mounting The Remote Share Automatically At Boot Time

server1:
If you don't want to mount the remote share manually, it is possible to have it mounted automatically when the system boots (provided you have followed chapter 3.1 because otherwise an automatic mount is not possible because you will be asked for a password). Normally we would modify /etc/fstab to achieve this, but unfortunately the network isn't up yet when /etc/fstab is processed in the boot process, which means that the remote share cannot be mounted.
To circumvent this, we simply add our mount command to /etc/rc.local, which is the last file to be processed in the boot process, and at that time the network is up and running:
vi /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

/usr/bin/sshfs -o idmap=user root@192.168.0.101:/home/backup /backup
exit 0
You can test this by simply rebooting your system:
reboot
After the reboot, you can check with
mount
and
df -h
if the remote share got mounted.


4 Using SSHFS As A Regular User

 
server1:
I want to use the local user falko now and mount the remote directory /home/someuser/backup, owned by someuser, to the local directory /home/falko/backup.
Create the user falko, if it doesn't exist:
adduser falko
server2:
On server2, create the user someuser, if it does not exist:
adduser someuser
Then become someuser...
su someuser
... and go to someuser's home directory where you create the backup (/home/someuser/backup) directory - make sure it's owned by someuser (it should be anyway as you are running these commands as someuser):
cd
mkdir ~/backup
chown someuser ~/backup
You can leave the someuser account if you like:
exit
server1:
First add falko to the fuse group:
adduser falko fuse
Now go to the falko account:
su falko
Create the local /home/falko/backup directory and make sure it's owned by falko (it should be anyway as you are running these commands as falko):
cd
mkdir ~/backup
chown falko ~/backup
Then mount the remote /home/someuser/backup directory to /home/falko/backup (still as user falko) - you can either use a relative or the full path for the remote directory:
sshfs -o idmap=user someuser@192.168.0.101:backup ~/backup
or
sshfs -o idmap=user someuser@192.168.0.101:/home/someuser/backup ~/backup
-o idmap=user makes that it does not matter if the local and the remote system use different user IDs - files owned by the remote user are also owned by the local user. If you don't use this, you might get permission problems.
If you connect to the remote host for the first time, you will see a warning about the authenticity of the remote host (if you have connected to the remote host before using ssh or scp, you will not see the warning). In any case, you will be asked for the someuser password for server2:
falko@server1:~$ sshfs -o idmap=user someuser@192.168.0.101:/home/someuser/backup ~/backup
The authenticity of host '192.168.0.101 (192.168.0.101)' can't be established.
RSA key fingerprint is 25:d8:7a:ee:c2:4b:1d:92:a7:3d:16:26:95:56:62:4e.
Are you sure you want to continue connecting (yes/no)?
<-- yes
someuser@192.168.0.101's password: <-- server2_someuser_password
falko@server1:~$
Let's check if the remote directory got mounted to /home/falko/backup:
mount
falko@server1:~$ mount
/dev/sda1 on / type ext3 (rw,errors=remount-ro)
tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
udev on /dev type tmpfs (rw,mode=0755)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)
fusectl on /sys/fs/fuse/connections type fusectl (rw)
root@192.168.0.101:/home/backup on /backup type fuse.sshfs (rw,nosuid,nodev,max_read=65536)
someuser@192.168.0.101:/home/someuser/backup on /home/falko/backup type fuse.sshfs (rw,nosuid,nodev,max_read=65536,user=falko)
falko@server1:~$
df -h
falko@server1:~$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              29G  1.2G   26G   5% /
tmpfs                 249M     0  249M   0% /lib/init/rw
udev                  244M  100K  244M   1% /dev
tmpfs                 249M     0  249M   0% /dev/shm
someuser@192.168.0.101:/home/someuser/backup
                       29G  1.2G   27G   5% /home/falko/backup
falko@server1:~$
Looks good!
To unmount the share, run
fusermount -u ~/backup
or
fusermount -u /home/falko/backup

4.1 Creating A Private/Public Key Pair On server1

Of course, we don't want to type in a password every time we try to mount the remote share. Therefore we create a private/public key pair and transfer the public key to server2 so that we will not be asked for a password anymore.
server1:
Create a private/public key pair on server1.example.com (still as user falko):
ssh-keygen
falko@server1:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/falko/.ssh/id_rsa):
 <-- ENTER
Enter passphrase (empty for no passphrase): <-- ENTER
Enter same passphrase again: <-- ENTER
Your identification has been saved in /home/falko/.ssh/id_rsa.
Your public key has been saved in /home/falko/.ssh/id_rsa.pub.
The key fingerprint is:
14:14:0b:ba:04:a7:51:1b:67:59:94:d5:01:7e:55:21 falko@server1.example.com
The key's randomart image is:
+--[ RSA 2048]----+
|  o.+ +=*+oo.E.oo|
|   = *...+  ...  |
|  . +   o . .    |
|   . . .   .     |
|    .   S        |
|                 |
|                 |
|                 |
|                 |
+-----------------+
falko@server1:~$

It is important that you do not enter a passphrase otherwise mounting will not work without human interaction so simply hit ENTER!
Next, we copy our public key to server2.example.com:
ssh-copy-id -i $HOME/.ssh/id_rsa.pub someuser@192.168.0.101
Now check on server2 if server1's public key has correctly been transferred:
server2:
cat /home/someuser/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+YpgpAaFYDYV2N0j4xteTx44tsz1pnSSQZPa0GkBi/KTuAJVT8DV4Jzh/HvJnNXvoyT6cEcnJa6p1SQTpn3Xt7b5ItA2ckDYTm78q1HZwX3htrkDUPrKGRwfzovyf/HKop0kHawU+Fox1nmtM9xIEVBCPERBKL0TZjGuqfEo0m6lkatVChI8RIu9+wH9I8VZCHalz+QdjQ8Mp/ckdGfVdAry4SyFicjg4eVzTq7s54yXupcSio7v2Ql95XO6azWzrU+G7VsI3UM0GMH9aXxjikx3dusmvLN9jBkL096Sheik1C7DOGVVsP6upCRVTcY6AB4J8VEmumdI4tnsSsr+x falko@server1.example.com
Now back on server1, try to mount the remote share again as user falko (make sure it's unmounted before you run the command):
server1:
sshfs -o idmap=user someuser@192.168.0.101:/home/someuser/backup ~/backup
If all goes well, you should not be prompted for a password:
falko@server1:~$ sshfs -o idmap=user someuser@192.168.0.101:/home/someuser/backup ~/backup
falko@server1:~$

4.2 Mounting The Remote Share Automatically At Boot Time

server1:
If you don't want to mount the remote share manually, it is possible to have it mounted automatically when the system boots (provided you have followed chapter 4.1 because otherwise an automatic mount is not possible because you will be asked for a password). Normally we would modify /etc/fstab to achieve this, but unfortunately the network isn't up yet when /etc/fstab is processed in the boot process, which means that the remote share cannot be mounted.
To circumvent this, we simply add our mount command to /etc/rc.local, which is the last file to be processed in the boot process, and at that time the network is up and running.
You need root privileges to edit /etc/rc.local, so become root first:
su
vi /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

/usr/bin/sshfs -o idmap=user root@192.168.0.101:/home/backup /backup
cd /home/falko && su -c "/usr/bin/sshfs -o idmap=user someuser@192.168.0.101:/home/someuser/backup /home/falko/backup" falko
exit 0
As you see, I've added the command
cd /home/falko && su -c "/usr/bin/sshfs -o idmap=user someuser@192.168.0.101:/home/someuser/backup /home/falko/backup" falko
instead of just
/usr/bin/sshfs -o idmap=user someuser@192.168.0.101:/home/someuser/backup /home/falko/backup
because the sshfs command must be run by falko, not root!
You can test now by simply rebooting your system:
reboot
After the reboot, you can check with
mount
and
df -h
if the remote share got mounted.

5 Links


No comments:

Post a Comment