45

I know sshfs is used to mount remote directory to local, but I need to mount local directory to remote fs.

I would like to mount a local folder such as:

/home/username/project_directory

onto a remote machine which I have ssh access to, such as:

/var/www/project_directory

The goal being that edits made locally are reflected on the remote filesystem.

5
  • @quinn is it working solution?
    – kongaraju
    Apr 18, 2014 at 4:29
  • Yes, I'm using it currently, seems to work fine
    – quinn
    Apr 18, 2014 at 5:14
  • Actually, I have one issue: superuser.com/questions/743316/…
    – quinn
    Apr 18, 2014 at 11:31
  • @quinn you should post the solution in that blog as an answer here. It works for me.
    – brismuth
    May 22, 2015 at 16:08
  • the really poor mans alternative: rsync -au --delete remote:path/ . && inotifywait -r -q -m -e close_write . | while read -r filename event; do rsync -au -r "$filename" remote:path/; done. This assumes "remote" is configured in .ssh/config. When ran, it first updates local to match what's in the remote. Then, every time you make a change to a file, it syncs to the remote. This will not automatically resync when change are made in remote server. It's not really mounting, so not a real answer to the question. However, I don't want to install a new tool 'sshfs' for this. which is orphaned now Jul 19, 2023 at 2:36

7 Answers 7

32

How to do it? You set up ssh forwarding by using port 10000 on the machine you log in on to port 22 on your local machine and use sshfs to mount in on the other side.

F.ex. to mount /home/username/mywwwdevelstuff on your local machine to /var/www on the server side:

localusername@localmachine: ssh username@server -R 10000:localmachine:22
username@server: cd /var
username@server: sshfs -p 10000 -o idmap=user,nonempty \
                 [email protected]:~/mywwwdevelstuff www
2
  • 9
    Its worth mentioning that the local machine must be running the ssh server. Apr 19, 2017 at 0:10
  • 4
    It's also worth mentioning that this isn't actually a reverse mount because it requires the remote user to be able to log in to the local machine. That's not what you want in a reverse mount. With a proper reverse mount you would have a local user that has access to a remote machine but the remote user does not need access the local machine.
    – CR.
    Apr 19, 2022 at 20:36
11

In order to avoid extra authentication and double encryption, you can reverse-forward the port to another port than 22 and run the /usr/libexec/openssh/sftp-server via the -e option of ncat on that port locally first. Then on the remote end use the 'directport' option of sshfs via the ssh command.

ncat -l -p 34567 -e /usr/libexec/openssh/sftp-server &
ssh -t -R 34568:localhost:34567 $REMOTE "sshfs localhost: $MPOINT -o directport=34568; bash"

You will get a remote shell with your local files in the $MPOINT directory and you don't need to log-in twice. How convenient is that. As a bonus, it allows mounting only once, so if someone else on the remote machine tries to open the port 34568, she will not get access to your files. Make sure the port number 34567 is not in use locally and 34568 is not in use remotely, else choose some other numbers >1024. And make sure the $MPOINT directory exists on the remote end.

3

No.

In order to do this "all" you need to do is reverse your logic. You could, for example, set up a 1 liner which would ssh into the remote machine and then use sshfs to mount the remote directory on the local machine on that box. Of-course this might be simplistic what with NAT, firewall rules etc, but you did not describe your usage case.

There are other protocols like SMB and, even better, NFS - but they will suffer similar issues.

The core of the problem you have is that a machine needs to trust the source of the data, and if you can remotely mount a file system that would break one of the core tenets of internet security.

1
  • 8
    I don't know what you are trying to say. I think for the purpose of the question you can safely assume that the server/client can log on to each other via SSH with keys, i.e. trust each other. The way I understand the question (and the problem I also have) is that creating an SSH connection from the client (dynamic IP, behind NAT which also has a dynamic IP, or possibly even more horrible cases) to the (permanently accessible) server is much easier than the other way round.
    – Nobody
    Nov 29, 2016 at 15:34
2

Based on @Nobody's script, I generalized it with some useful comment. Below is my script.

https://gist.github.com/allenyllee/ddf9be045810572cd809ae3587a23658

#!/bin/bash

##/*
## * @Author: AllenYL 
## * @Date: 2017-11-08 11:37:31 
## * @Last Modified by:   [email protected] 
## * @Last Modified time: 2017-11-08 11:37:31 
## */

#
# mount local directory to remote through reverse sshfs
# 
# usage:
#       ./reverse_sshfs.sh [remote_addr] [remote_ssh_port] [remote_user] [local_dir]
# 
# [local_dir] is a path relative to this script
# 
# This script will automatcally create a directory named "project_$LOCAL_USER" in remote user's home dir,
# and mount [local_dir] to this point. When exit, will umount "project_$LOCAL_USER" and deleted it.
# 

##
## linux - how to mount local directory to remote like sshfs? - Super User 
## https://superuser.com/questions/616182/how-to-mount-local-directory-to-remote-like-sshfs
##

# source directory of this script
SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

LOCAL_USER=$(whoami)
REMOTE_USER="$3"

LOCAL_DIR="$SOURCE_DIR/$4"
REMOTE_DIR="./project_$LOCAL_USER"

LOCAL_ADDR="localhost"
REMOTE_ADDR="$1"

LOCAL_PORT="22"
FORWARD_PORT="10000"
REMOTE_PORT="$2"

LOCAL_SSH="-p $FORWARD_PORT $LOCAL_USER@$LOCAL_ADDR"
REMOTE_SSH="-p $REMOTE_PORT $REMOTE_USER@$REMOTE_ADDR"

SSHFS_OPTION="-o NoHostAuthenticationForLocalhost=yes"

###############
## With ssh, how can you run a command on the remote machine without exiting? - Super User 
## https://superuser.com/questions/261617/with-ssh-how-can-you-run-a-command-on-the-remote-machine-without-exiting
##
## Here I use -t to force the allocation of a pseudo-terminal, which is required for an interactive shell. 
## Then I execute two commands on the server: first the thing I wanted to do prior to opening the interactive shell 
## (in my case, changing directory to a specific folder), and then the interactive shell itself. 
## bash sees that it has a pseudo-terminal and responds interactively.
##
###############
## Why does an SSH remote command get fewer environment variables then when run manually? - Stack Overflow 
## https://stackoverflow.com/questions/216202/why-does-an-ssh-remote-command-get-fewer-environment-variables-then-when-run-man
##
## sourcing the profile before running the command
## ssh user@host "source /etc/profile; /path/script.sh"
##
## usage:
##      ssh -t -p 88 [email protected] -R 10000:localhost:22 \
##      "source /etc/profile; sshfs  -p 10000 allenyllee@localhost:/media/allenyllee/Project/Project/server_setup/nvidia_docker/project ./project2;bash"
## options:
##       -v Verbose 
##       -X X11 forwarding
##       -t pseudo-terminal for an interactive shell
##
ssh -X -t $REMOTE_SSH -R $FORWARD_PORT:localhost:$LOCAL_PORT \
"source /etc/profile;mkdir $REMOTE_DIR; \
sshfs $SSHFS_OPTION $LOCAL_SSH:$LOCAL_DIR $REMOTE_DIR; bash; \
umount $REMOTE_DIR; rm -r $REMOTE_DIR"
2

I really like @Ronald Hoogenboom's solution, but I've tweaked it to work with an ssh_config (~/.ssh/config) file so that it sets everything up transparently when I run "ssh $HOSTNAME" normally:

Host $HOSTNAME
    RequestTTY yes
    ProxyCommand ncat -l -p 34567 -e /usr/lib/sftp-server & nc %h %p
    RemoteForward 34568 localhost:34567
    RemoteCommand sshfs localhost:$MY_DIR $MPOINT -o directport=34568; /bin/bash -li; fusermount -u $MPOINT

(replace $HOSTNAME, $MY_DIR, and $MPOINT as appropriate)

1
  • I like idea, this way you can bring your toolkit to every host you logging in, by just create temp directory and clear it after !
    – zb'
    May 31, 2023 at 20:20
1

In principle it's the same as quinn's answer, but as a working script instead of separate commands which need adaption for each machine/usage.

I don't know about the overhead in this, it seems to me like it encrypts/decrypts everything twice.

#!/bin/bash
# Reverse sshfs. You need ssh servers on both ends, the script logs first
# onto the remote end and then back into the local one
# Usage: sshfsr dir [user@]host:mountpoint  [options]
# [options] are passed on to the remote sshfs

set -e

LOCALPATH=$1
REMOTE=$(echo $2 | grep -o '^[^:]*')
REMOTEPATH=$(echo $2 | grep -o '[^:]*$')
ARGS=${@:3}

LOCALUSER=$(whoami)
PORT=10000

ssh $REMOTE -R $PORT:localhost:22 "sshfs -o NoHostAuthenticationForLocalhost=yes -p $PORT $ARGS $LOCALUSER@localhost:$LOCALPATH $REMOTEPATH" &

I disable HostAuthenticationForLocalhost because obviously localhost can be anything. This is perfectly safe with public key authentication. You shouldn't use passwords anyway, but even with passwords you are connecting to a host you know you control.

0

Following on from Compholio's answer:

Here's a simple one-liner which does everything and runs in the foreground:

ssh -o ProxyCommand='ncat -l -p 34567 -e /usr/libexec/openssh/sftp-server & nc %h %p' \
   -R 34568:localhost:34567 \
   $TARGET_HOST \
   sshfs localhost:$LOCAL_FOLDER $TARGET_FOLDER -o directport=34568 -f

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .