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

remote open("/file"): Permission denied #16

Closed
stefanocog opened this issue Nov 10, 2015 · 24 comments
Closed

remote open("/file"): Permission denied #16

stefanocog opened this issue Nov 10, 2015 · 24 comments
Labels

Comments

@stefanocog
Copy link

I login correctly to container with the command sftp -P 2222 user@ip_container
To sftp shell i get this error:

sftp> put file.sh 
Uploading file.sh to /file.sh
remote open("/file.sh"): Permission denied

I have run the container with docker-compose:

sftp:
 image: atmoz/sftp
 volumes:
  - /host/sftpdata:/home/sftp/share
 ports:
  - "2222:22"
 command: sftp:password:1001
@atmoz
Copy link
Owner

atmoz commented Nov 16, 2015

Each user is jailed in their home directory (for security). That means root is owning the home directory, and the user can not modify it's content. The user can only do changes inside sub-directories.

You have to create a directory (i.e. mount a volume) inside the user's home directory, and then you can upload files there. In your case, this will be the "share" directory.

@atmoz atmoz closed this as completed Nov 16, 2015
@atmoz atmoz added the question label Nov 16, 2015
@cthiebault
Copy link

Here is a way to configure automatically the creation & permissions for a share folder:
it will create a share folder for every users with a home folder and change ownership to the proper user.

docker-compose.yml

  sftp:
    image: atmoz/sftp
    volumes:
      - ./users.conf:/etc/sftp-users.conf:ro
      - ./init.sh:/etc/sftp.d/init.sh:ro

init.sh

#!/bin/bash
for user_home in /home/* ; do
  if [ -d "$user_home" ]; then
    username=`basename $user_home`
    echo "Setup $user_home/share folder for $username"
    mkdir -p $user_home/share
    chown -R $username:users $user_home/share
  fi
done

@knutole
Copy link

knutole commented May 30, 2016

I'm having the same problem. I find the documentation a bit lacking. Why is this not enough:

docker run \
    -v /home/SFTP/malnes/share:/home/malnes/share \
    -p 2222:22 -d atmoz/sftp \
    malnes:randompassword:1001

Logging into the SFTP account, the user is not allowed to put files in either / or /share. Shouldn't this work out of the box?

Should the /home/SFTP/malnes/share folder be created on host? (I have, with 666 permissions.)

Intuition fails me here.

@atmoz
Copy link
Owner

atmoz commented May 30, 2016

This is the nature of file permissions and volumes. They have to match if you want it to work as you expect. I will have a closer look at this challenge soon, and will add more to the documentation, so fewer people fall into this pit.

@knutole
Copy link

knutole commented May 30, 2016

Thanks @atmoz, I think that would be great.

@ianlshaw
Copy link

ianlshaw commented Jul 24, 2017

I ran into this also. For me, it was failing to pass in the subdirectory name as an argument to the container COMMAND.

In the above examples I see malnes:randompassword:1001
Which does not reference the subdirectory.

Here's the line which sorted out the permissions issue for me.
command: foo:pass:::upload

I'm using a shared volume, so have omitted the group identification mapping.

For reference, here's my volume line from the sftp service declaration:

 volumes:
        - data-volume:/home/foo/upload

@Vizy-CC

This comment has been minimized.

1 similar comment
@Vizy-CC

This comment has been minimized.

@Vizy-CC

This comment has been minimized.

@Drachenfels
Copy link

I will allow myself to note that part about permissions is yet to be clarified in main README.md. From perspective of semi-noob as a devops it easy to fail on that front I would suggest modyfing following paragraph of README.md:

Let's mount a directory and set UID:

docker run \
    -v /host/upload:/home/foo/upload \
    -p 2222:22 -d atmoz/sftp \
    foo:pass:1001

Into:

Let's mount a directory and set UID:

docker run \
    -v /host/upload:/home/foo/upload \
    -p 2222:22 -d atmoz/sftp \
    foo:pass:1001

NOTE: If upload fails due to "No such file or director" or "Permission denied" make sure that /host/upload is owned by same user as docker container is run by. Common scenario is that this directory is owned by root while docker is run by current $USER.

With sentence like that it will save a noob or two out there. ;-)

@Marcopolox13
Copy link

I still have the same problem.
The user name is identical, I ran chown -R 1000:1000 SFTP and chmod -R 777 SFTP and started the docker with UID and GID 1000:1000, but still I can not access the files or create ones. I also tried it with 953:953 and 1000:953 (953 is GID from docker)

Can someone help me?

@atmoz atmoz pinned this issue Jul 14, 2020
@2hoursleep
Copy link

2hoursleep commented Feb 24, 2021

To anyone who is still experience the problem. Provided that the directory or volume exists.
I modified the command line from the docker-compose example with foo as username.

command: foo:pass:1001:::upload

No additional permissions or scripts required to run (other than ensuring that Docker has got access on Mac etc).

so the Docker version of it on cli.

docker run \
    -v /host/upload:/home/foo/upload \
    -p 2222:22 -d atmoz/sftp \
    foo:pass:1001:::upload

@tommyjcarpenter
Copy link

tommyjcarpenter commented Apr 28, 2021

I am completely stuck on this issue and I have tried everything in this thread.

Docker compose config:

version: "3.9"
services:
  web:
    build: .
    ports:
      - "6666:8080"
  sftp:
    image: atmoz/sftp
    volumes:
        - /tmp/upload:/home/testuser/upload
        - ./ssh_host_ed25519_key:/etc/ssh/ssh_host_ed25519_key
        - ./ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key
    ports:
        - "22:22"
    hostname: myftpserver
    # https://github.com/atmoz/sftp/issues/16
    command: testuser:abc123:::upload

just as @2hoursleep suggested.

In my code, I use:

with pysftp.Connection(host=hostname, username=username, port=port, cnopts=cnopts, **kwargs) as sftp:
        subdir = "/home/testuser/upload"
        logger.debug(subdir)
        for filename in filenames:
            _head, tail = os.path.split(filename)
            remote_filepath = os.path.join(subdir, tail)
            pwd = sftp.pwd
            logger.debug(f"SFTPing {filename} to {remote_filepath}; remote server pwd is {pwd}")
            sftp.put(filename, remotepath=remote_filepath, confirm=confirm)  # , preserve_mtime=True)

which produces the logs:

366a55245513_python-dissemination-api_sftp_1 | Accepted password for testuser from 172.18.0.3 port 40168 ssh2
web_1   | [2021-04-28 13:35:20,429] [dissapi.sftp] [DEBUG   ] /home/testuser/upload
web_1   | [2021-04-28 13:35:20,674] [dissapi.sftp] [DEBUG   ] SFTPing /tmp/test.txt to /home/testuser/upload/test.txt; remote server pwd is /
web_1   | [2021-04-28 13:35:20,677] ERROR in app: Exception on /sftp-upload [POST]
web_1   | Traceback (most recent call last):
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app
web_1   |     response = self.full_dispatch_request()
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request
web_1   |     rv = self.handle_user_exception(e)
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception
web_1   |     reraise(exc_type, exc_value, tb)
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
web_1   |     raise value
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request
web_1   |     rv = self.dispatch_request()
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request
web_1   |     return self.view_functions[rule.endpoint](**req.view_args)
web_1   |   File "dissapi/app.py", line 80, in sftp_upload
web_1   |     sftp_files(fpaths, body["destination_hostname"], body["username"], **kwargs)
web_1   |   File "./dissapi/sftp.py", line 37, in sftp_files
web_1   |     sftp.put(filename, remotepath=remote_filepath, confirm=confirm)  # , preserve_mtime=True)
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/pysftp/__init__.py", line 363, in put
web_1   |     sftpattrs = self._sftp.put(localpath, remotepath, callback=callback,
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/paramiko/sftp_client.py", line 759, in put
web_1   |     return self.putfo(fl, remotepath, file_size, callback, confirm)
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/paramiko/sftp_client.py", line 714, in putfo
web_1   |     with self.file(remotepath, "wb") as fr:
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/paramiko/sftp_client.py", line 372, in open
web_1   |     t, msg = self._request(CMD_OPEN, filename, imode, attrblock)
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/paramiko/sftp_client.py", line 813, in _request
web_1   |     return self._read_response(num)
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/paramiko/sftp_client.py", line 865, in _read_response
web_1   |     self._convert_status(msg)
web_1   |   File "/home/dissapi/.local/lib/python3.9/site-packages/paramiko/sftp_client.py", line 894, in _convert_status
web_1   |     raise IOError(errno.ENOENT, text)
web_1   | FileNotFoundError: [Errno 2] No such file
web_1   | [pid: 7|app: 0|req: 1/1] 172.18.0.1 () {36 vars in 493 bytes} [Wed Apr 28 13:35:20 2021] POST /sftp-upload => generated 290 bytes in 335 msecs (HTTP/1.1 500) 2 headers in 99 bytes (1 switches on core 0)

However, it's not true!! if I docker exec into the container:

de 366                                                 
root@myftpserver:/# cd /home/testuser/upload/
root@myftpserver:/home/testuser/upload# ls
root@myftpserver:/home/testuser/upload# pwd
/home/testuser/upload
root@myftpserver:/home/testuser/upload#

That directory definitely exists

I have also tried sftp.cd to change to /home/testuser/upload but same problem

@jruydemir
Copy link

FWIW I was able to get this to work just by making the /host/upload folder owned by the same uid as the docker user. In my case it was 1001.

chown 1001:1001 /host/upload

@nfleury
Copy link

nfleury commented Jun 22, 2022

For those still having issues:

1- Get UID of user with:

$ id -u

2- Use correct path for home dir when mounting volume + use previous UID:

For $USER:pass:$UID volume => /your/whatever/path:/home/$USER/upload

@hantsy
Copy link

hantsy commented Oct 11, 2022

FWIW I was able to get this to work just by making the /host/upload folder owned by the same uid as the docker user. In my case it was 1001.

chown 1001:1001 /host/upload

How to resovle this issue under Windows.

@themightyoarfish
Copy link

themightyoarfish commented Apr 3, 2023

@cthiebault Unfortunately this idea seems to result in

/entrypoint: /etc/sftp.d/init.sh: /bin/bash: bad interpreter: Permission denied

even though bash is available.


Update: You have to chmod +x the local init.sh file and mark it executable in the mount:

      - ./init.sh:/etc/sftp.d/init.sh:rox

@themightyoarfish
Copy link

themightyoarfish commented Apr 3, 2023

Can't get this to work. I have mounts like these in docker-compose.yml:

  sftp:
    image: atmoz/sftp
    volumes:
      - ${PWD}/test-files/files/file1:/home/${USERNAME}/files/file1
      - ${PWD}/test-files/files/file2:/home/${USERNAME}/files/file2
...
    command: |
      ${USERNAME}::${USERID}:${GROUPID}:files

I use the shell environment to set the user, id and group variables:

 USERNAME=rasmus USERID=$(id -u) GROUPID=$(id -g) docker compose up sftp --force-recreate

Which outputs

[+] Running 1/1
 ⠿ Container docker-compose-test-environment-sftp-1                                                                                                    R...                                                    0.1s
 ⠋ sftp The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested                                                         0.0s
Attaching to docker-compose-test-environment-sftp-1
docker-compose-test-environment-sftp-1  | [/usr/local/bin/create-sftp-user] Parsing user data: "rasmus::501:20:files,zips"
docker-compose-test-environment-sftp-1  | [/usr/local/bin/create-sftp-user] Directory already exists: /home/rasmus/files
docker-compose-test-environment-sftp-1  | [/usr/local/bin/create-sftp-user] Directory already exists: /home/rasmus/zips
docker-compose-test-environment-sftp-1  | [/entrypoint] Executing sshd
docker-compose-test-environment-sftp-1  | Server listening on 0.0.0.0 port 22.
docker-compose-test-environment-sftp-1  | Server listening on :: port 22.

So it seems to successfully substitute. But then inspecting ownership of the files/ directory shows surprising behaviour

$ docker exec -it docker-compose-test-environment-sftp-1 ls -la /home/rasmus/files
total 6612
drwxr-xr-x 3 root root    4096 Apr  3 12:51 .
drwxr-xr-x 6 root root    4096 Apr  3 12:51 ..
-rw-r--r-- 1 1001 1001   64721 Mar 31 11:11 file1
-rw-r--r-- 1 1001 1001   80364 Mar 31 11:11 file2

Why does a user named 1001 own these files now?

@themightyoarfish
Copy link

themightyoarfish commented Apr 3, 2023

Maybe an issue is that the /home/rasmus directory exists already due to the mounts, and thus https://github.com/atmoz/sftp/blob/master/files/create-sftp-user#L108 will not change the permissions.

It's also weird that a use string such as rasmus::501:20:files will lead to filess group to be users, not the group corresponding to 20 (which seems to be dialout).

@dMailonG
Copy link

dMailonG commented Oct 13, 2023

None of the above worked for me. Here's what I had to do:

services:
  sftp:
    image: atmoz/sftp
    volumes:
      - ./data:/home/user
    ports:
        - "2222:22"
    command: user:password:::folder

The gist of it is that data is empty, so folder is created inside it, with the appropriate permissions, when the service is started.
Here's how I was trying to do it:

services:
  sftp:
    image: atmoz/sftp
    volumes:
      - ./data/folder:/home/user/folder
    ports:
        - "2222:22"
    command: user:password:::folder

Ensuring the UID and GID matched did nothing for me in this case.

@mauleyzaola
Copy link

@dMailonG Your code is the only solution among all that works. Thanks!

@tebenkov2222
Copy link

tebenkov2222 commented Oct 30, 2023

None of the above worked for me. But solution for me is chmod -R 777 /shared/user/directory
Before that I created all the necessary directories by started container

/home folder was be auto created docker. if you change chmod application will crash
you need change chmod for only /home/user folders

and if users folders wasnt created after start docker, that you need create volumes to per users folder
PS: I know this bad idea but this the only solution that helped me
PS2: sorry for my bad English

@Stefen-Taime
Copy link

it work for me:

sftp:
image: atmoz/sftp
container_name: sftp
volumes:
- ./sftp/users.conf:/etc/sftp/users.conf:ro
- ./sftp/upload:/home/$USER/upload
networks:
- docsearch
ports:
- "2222:22"

file users.conf:
stefen:stefen123:1001:100

@heyvaldemar
Copy link

hey all,

Got it working! 🎉 Check out my repo and how-to guide here.

Hit me up if you're stuck or just wanna chat about it. Cheers!

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

Successfully merging a pull request may close this issue.