How I played with golang to impeach sshfs failures
Tags: sshfs, go, ssh
Published: 2020-04-05 11:16:51

---
title: How I played with golang to impeach sshfs failures
published: true
description:
tags: sshfs, go, ssh, foss
---

Last day, while reading the docker reference, I spotted an `sshfs` container. Finally, I ended up finding [this repo](https://github.com/vieux/docker-volume-sshfs). I said, well, but the repo has not been updated since 3 years and roughly linked with dockers’ api. Finally I just gave up and this is how I spent one day having fun with golang without messing with the docker api.

## It begins with...

Last day, as it happens occasionally, I was reading the docker cli reference. While trying to understand an example, my mind just stopped on `sshfs`. At this moment, I was like : "Really ? all this time rsyncing !".

Excited to learn more about this container image, I found myself dealing with [this repositiry](https://github.com/vieux/docker-volume-sshfs) that sadly has not been updated since 3 years. Fortunately, the [sshfs project](https://github.com/libfuse/sshfs) is still living pretty well. And I still was excited enough to try it out.

From that moment — and I swear this is not coronavirus fever — I wanted to write a small piece of code that will run on the host from where I want to access some directory from a remote ssh server that will suits my needs and do all the preflight checks for my needs.

Some may say let’s write a python script or a bash script. Well, no, but this is how I spent one day having fun with [Golang](https://golang.org). 

Finally the small piece of code ended up with 250 A+ go lines.

Also, that was my first experience and short experience with `.travis.yml`.

If you’re a go enthusiast like me, go to [the github repository](https://github.com/malikbenkirane/mount_sshfs) and just read the code.

With next section, I expose what kind of tool I wanted.

## A tool ? What for ?

My idea was to have a small binary to copy wherever I often need to mount
remote directory accessible from a remote ssh server. And this is how I unfortunately find out about [sshfs](https://github.com/libfuse/sshfs). The hypothetical binary I will carry will either read options from cli or a yaml file and it will check
- if I have the credentials for connecting to the remote host
- if the remote directory I will mount exists
- if the mount point exists

If so, I will be able to run something like the following shell script
without being stopped by a trivial error
```sh
host=#...
local_dir=#...
mnt_dir=#...
docker_uid=#...
docker_gid=#...
# sudo mkdir ${mnt_dir} # not necessarily
sudo sshfs \
  -o idmap=user,uid=${docker_uid},gid=${docker_gid} \
  -o allow_other \
  ${host}:${remote_dir} \
  ${mnt_dir}
```

My host, where I want to port the said binary, is running latest ubuntu server and there is also docker daemon running. I want to remap uid and gid to have read and write permissions on the remote directory. For instance I may have to use this directory inside docker

```sh
docker_mnt_dir=#...
docker run --rm -ti -v ${mnt_dir}:${docker_mnt_dir} # ...
```

Now, it’s time for a demo.

## Action!

We start with removing the leading `#` in `/etc/fuse.conf`
> https://serverfault.com/questions/947182/mount-a-sshfs-volume-into-a-docker-instance
> uncomment user_allow_other in `/etc/fuse.conf`

I start with getting the uid and gid for the user logged in the container
```
docker run --rm <some-image> id
```


Then I write an `sshfs.yml` yaml configuration for `mount_sshfs`
```
uid: 1001
gid: 1001
docker: true
remote: myuser@myhost:/my/remote/dir
mount: /mount/point/dir
```

For the moment, I didn't decided yet, if `mount_sshfs` will make the mount point directory. Actually, if you had already read [mount_sshfs README](github.com/malikbenkirane/mount_sshfs), you may have noticed that nothing is actually done by the tool except for checking that everything is alright before actually calling `sshfs`.

That is, that firs, you’ll run
```sh
mount_sshfs -config sshfs.yml
```
And then, only if it looks alright
```sh
mount_sshfs -config sshfs.yml 2>/dev/null | sh
```

In case `mount_sshfs` exits at step 1 with
```
... invalid mount dir path
```
make sure the directory exists. For example, I can type
```sh
grep mount sshfs.yml | sed -n '/mount/s/mount:/sudo mkdir/p'
```
Then, I will check if output is ok and I will type on the shell prompt (`<up>`, or `<esc>kA` followed with ` | sh`)
```sh
grep mount sshfs.yml | sed -n '/mount/s/mount:/sudo mkdir -p/p' | sh
```

Although, it's not my priority right now to work on a smart tool that will both check and assist shell level error resolution. I would be very happy to use a tool of this kind which actually hooks errors and redirect me to an nice assistant able to solve that kind of error in someway like I just showed. 

Although, I suspect this to be programmatically nicely feasible, this is again not my priority right now. But you may either be interested or not thinking it's nicely feasible. In both cases I'll be very happy you let me know.

Back now with the demo. And let say `mount_sshfs` exits with
```
... key is uknown
```
you may need therefore to
```
ssh-copy-id {user}@{host}
```
And if this may not be ok in your case but I'm sure you will find the right way to do it.

If all tests pass, `mount_sshfs` only prints on standard output the prefilled shell command we wanted so far
```sh
sudo sshfs \
  -o idmap=user,uid=<yaml:uid>,gid=<yaml:gid>\
  -o allow_other \
  <yaml:remote> \
  <yaml:mount>
```

This means step 1 is okay but as any good system adminstrator, you will double check the command before running
```sh
mount_sshfs -config sshfs.yml 2>/dev/null | sh
```
And hopefully
```
$ ls -ln <yaml:mount>
total 112
drwxr-xr-x 1 1001 1001  7904 Apr  3 09:55 node_modules
-rw-r--r-- 1 1001 1001   543 Apr  3 09:55 package.json
drwxrwxr-x 1 1001 1001   160 Apr  3 09:03 public
-rw-r--r-- 1 1001 1001  2424 Feb  2 17:44 README.md
-rw-r--r-- 1 1001 1001  1709 Feb  2 17:44 rollup.config.js
drwxrwxr-x 1 1001 1001   128 Apr  3 09:15 src
-rw-r--r-- 1 1001 1001 83399 Apr  3 09:55 yarn.lock
```

This is the end of this story.

—

Now, I'll be really happy to answer your questions and I'm truly excited for all the amazing improvement or ideas you have.

References
- [mount a sshfs volume into a docker instance (serverfault.com)]
(https://serverfault.com/questions/947182/mount-a-sshfs-volume-into-a-docker-instance)
- [libfuse/sshfs (github.com)](https://github.com/libfuse/sshfs)
- [malikbenkirane/mount_sshfs (github.com)](https://github.com/malikbenkirane/mount_sshfs)