Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Permission denied" error when uploading to volume mounted as subdirectory inside user's home directory #37

Closed
TylerRick opened this issue Apr 1, 2016 · 5 comments

Comments

@TylerRick
Copy link

Given this docker-compose.yml file:

version: '2'

services:
  sftp:
    image: atmoz/sftp:latest
    volumes:
      - assets:/home/mi/assets
    command: "mi:pass"
    ports:
      - "2222:22"

volumes:
  assets: {}

I would expect to be able to upload a file to my mounted subdirectory like this:

sftp -P 2222 mi@localhost:/assets
mi@localhost's password: pass
Connected to localhost.
Changing to: /assets
sftp> put Readme.md 
Uploading Readme.md to /assets/Readme.md

but it fails with this:

remote open("/assets/Readme.md"): Permission denied

I'm pretty sure the problem is that the directory I'm uploading is owned by root (uid 0) and not by the user who's trying to upload (mi (uid 1000))...

root@2eac25e867f1:/# ls -an /home/mi/assets/
total 8
drwxr-xr-x 2 0 0 4096 Apr  1 01:29 .
drwxr-xr-x 3 0 0 4096 Apr  1 01:35 ..

root@2eac25e867f1:/# id mi
uid=1000(mi) gid=100(users) groups=100(users)

Problem statement

My question/problem is: How do I get my docker-compose up to start things up so that they work out of the box?

I understand how the user's home directory needs to owned by root for the chroot jail to work and that you have to make docker mount volumes in separate directories inside the user's home directory.

What I don't understand is who the owner of those subdirectories is supposed to be or how you're supposed to get them to be owned by the right person so that things work out of the box.

I know I could mount a host directory as a volume like in the Readme examples and manually change the owner of that host directory.

But,

  1. This should be possible with normal, named volumes. (I shouldn't have to mount a specific directory from the host as a volume to get this working.)
  2. I shouldn't have to manually change/set the owner of anything on the host in order to be able to use a docker image

I want to be able to just give someone a docker-compose.yml file (like the one above) and have them be able to just docker-compose up (or docker run) and immediately be able to start uploading, without any special config on the host. In other words, have it "just work" out of the box. :) Is this possible?

I'm hoping this can be fixed or the documentation can be updated to show how this is possible.

Further details

docker volumes are all owned by root. I'm not sure that there's any (safe) way to change that (?)...

docker volume inspect project_assets
[
    {
        "Name": "project_assets",
        "Driver": "local",
        "Mountpoint": "/var/lib/docker/volumes/project_assets/_data"
    }
]
sudo ls -nd /var/lib/docker/volumes/project_assets/_data
drwxr-xr-x 2 0 0 4096 Mar 31 18:29 /var/lib/docker/volumes/project_assets/_data

Things I've tried: using uid 0 for sftp user

I saw this in the documentation:

You must set custom UID for your users if you want them to make changes to your mounted volumes with permissions matching your host filesystem.

So I tried this:

    command: "mi:pass:0"

and /etc/password showed this (as if it had worked):

mi:x:0:100::/home/mi:/bin/sh

but I was unable to log in when I did that:

sftp -P 2222 mi@localhost:/assets
mi@localhost's password: pass
Permission denied, please try again.
@TylerRick
Copy link
Author

I figured out a workaround involving adding a file to /etc/sftp.d/...

vim -S .local/vim/docker.vim

version: '2'

services:
  sftp:
    image: atmoz/sftp:latest
    volumes:
      - assets:/home/mi/assets
      - ./images/sftp/sftp.d/fix_owner:/etc/sftp.d/fix_owner
    command: "mi:pass"
    ports:
      - "2222:22"

volumes:
  assets: {}

images/sftp/sftp.d/fix_owner:

#!/bin/bash
set -e

userConfFinalPath="/var/run/sftp-users.conf"

function fix_ownership_for_user() {
  IFS=':' read -a param <<< $@
  user="${param[0]}"
  pass="${param[1]}"

  # If there are any files in the dir (otherwise the chown will give error)
  if [ "$(ls -A /home/$user/)" ]; then
    shopt -s dotglob
    echo chown -R $user /home/$user/*
    chown -R $user /home/$user/*
    shopt -u dotglob
  fi
}

if [ -f "$userConfFinalPath" ]; then
  # Fix ownership of each user's home directory subdirectories every time the container is started.
  # (The home directory itself must continue to be owned by root for the chroot to work.)
  while IFS= read -r user_line || [[ -n "$user_line" ]]; do
    fix_ownership_for_user "$user_line"
  done < "$userConfFinalPath"
fi

Would this cause problems for anyone if it were added as part of the entrypoint itself?

It seems like the subdirs would need to be owned by the user who is connecting in order for uploads to work at all. Right? Am I missing anything?

@cthiebault
Copy link

See my #16 (comment) for same kind of problems...

@TylerRick
Copy link
Author

Cool, glad to know I'm not the only one who ran into this. Would be nice if this could be automatically handled in the entrypoint instead of having to add a script to /etc/sftp.d/ ... but at least there's a workaround for now.

@ashleymichaelwilliams
Copy link

Would it be desirable to have a parameter to create a subfolder within the user's home directory?

I forked off of atmoz's master branch to pass a user folder parameter. I also added some logic to the entrypoint file which detects if the folder already exists and if so, not create it which would cause the container to fail to start. You can find it under my public github repository 'ashleymichaelwilliams/sftp'.

@atmoz What do you think about doing something like this where it gives people the ability to have write permissions without modifying their host's underlying file-system's ownership/permissions. Maybe you can handle this for a configuration file like previously mentioned. Either way, I think it would be much better to not be hassled.

Cheers!

@atmoz
Copy link
Owner

atmoz commented Aug 12, 2016

Thanks for bringing this issue up and finding a solution and a workaround.

I've now added a directory parameter to the entrypoint/user syntax. I hope this will solve the issue and make the docker image even easier to use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants