How do I copy files that need root access with scp?

423,168

Solution 1

You're right, there is no sudo when working with scp. A workaround is to use scp to upload files to a directory where your user has permissions to create files, then log in via ssh and use sudo to move/copy files to their final destination.

scp -r folder/ [email protected]:/some/folder/you/dont/need/sudo
ssh [email protected]
 $ sudo mv /some/folder /some/folder/requiring/perms 
# YOU MAY NEED TO CHANGE THE OWNER like:
# sudo chown -R user:user folder

Another solution would be to change permissions/ownership of the directories you uploading the files to, so your non-privileged user is able to write to those directories.

Generally, working in the root account should be an exception, not a rule - the way you phrasing your question makes me think maybe you're abusing it a bit, which in turn leads to problems with permissions - under normal circumstances you don't need super-admin privileges to access your own files.

Technically, you can configure Ubuntu to allow remote login directly as root, but this feature is disabled for a reason, so I would strongly advice you against doing that.

Solution 2

Quick way

From server to local machine:

ssh user@server "sudo cat /etc/dir/file" > /home/user/file

From local machine to server:

cat /home/user/file | ssh user@server "sudo tee -a /etc/dir/file"

Solution 3

Another method is to copy using tar + ssh instead of scp:

tar -c -C ./my/local/dir \
  | ssh [email protected] "sudo tar -x --no-same-owner -C /var/www"

Solution 4

You can also use ansible to accomplish this.

Copy to remote host using ansible's copy module:

ansible -i HOST, -b -m copy -a "src=SRC_FILEPATH dest=DEST_FILEPATH" all

Fetch from remote host using ansible's fetch module:

ansible -i HOST, -b -m fetch -a "src=SRC_FILEPATH dest=DEST_FILEPATH flat=yes" all

NOTE:

  • The comma in the -i HOST, syntax is not a typo. It is the way to use ansible without needing an inventory file.
  • -b causes the actions on the server to be done as root. -b expands to --become, and the default --become-user is root, with the default --become-method being sudo.
  • flat=yes copies just the file, doesn't copy whole remote path leading to the file
  • Using wildcards in the file paths isn't supported by these ansible modules.
  • Copying a directory is supported by the copy module, but not by the fetch module.

Specific Invocation for this Question

Here's an example that is specific and fully specified, assuming the directory on your local host containing the files to be distributed is sourcedir, and that the remote target's hostname is hostname:

cd sourcedir && \
ansible \
   --inventory-file hostname, \ 
   --become \
   --become-method sudo \
   --become-user root \
   --module-name copy \
   --args "src=. dest=/var/www/" \
   all

With the concise invocation being:

cd sourcedir && \
ansible -i hostname, -b -m copy -a "src=. dest=/var/www/" all

P.S., I realize that saying "just install this fabulous tool" is kind of a tone-deaf answer. But I've found ansible to be super useful for administering remote servers, so installing it will surely bring you other benefits beyond deploying files.

Solution 5

May be the best way is to use rsync (Cygwin/cwRsync in Windows) over SSH?

For example, to upload files with owner www-data:

rsync -a --rsync-path="sudo -u www-data rsync" path_to_local_data/ [email protected]:/var/www

In your case, if you need root privileges, command will be like this:

rsync -a --rsync-path="sudo rsync" path_to_local_data/ [email protected]:/var/www

See: scp to remote server with sudo.

Share:
423,168

Related videos on Youtube

Dimitris Sapikas
Author by

Dimitris Sapikas

I am student at TEI of Piraeus, IEEE SB of TEI Piraeus Chair and Firefox TEI of Piraeus Club Lead

Updated on September 18, 2022

Comments

  • Dimitris Sapikas
    Dimitris Sapikas over 1 year

    I have an Ubuntu server to which I am connecting using SSH.

    I need to upload files from my machine into /var/www/ on the server, the files in /var/www/ are owned by root.

    Using PuTTY, after I log in, I have to type sudo su and my password first in order to be able to modify files in /var/www/.

    But when I am copying files using WinSCP , I can't create create/modify files in /var/www/, because the user I'm connecting with does not have permissions on files in /var/www/ and I can't say sudo su as I do in case of an ssh session.

    Do you know how i could deal with this ?

    If I was working on my local machine, I would call gksudo nautilus but in this case I only have terminal access to the machine.

    • dobey
      dobey over 11 years
      This seems more like a question for your virtual server provider, or for the putty or winscp developers.
    • Dimitris Sapikas
      Dimitris Sapikas over 11 years
      @dobey you obviusly wrong , it is about ubuntu privileges !
    • Sergey
      Sergey over 11 years
      Why is this closed? This is a perfectly valid question about copying files with scp - every web developer is familiar with this situation
    • h3.
      h3. over 11 years
    • JanezKranjski
      JanezKranjski about 6 years
      I have a similar problem. I create a file (HTML in this case) on Windows computer and try to copy it with WinSCP to /var/www/html/website folder. And it says that there is a permission problem. Because I can copy to my /home folder I copied the file in two steps, but it isn't very convenient :-) I tried with adding my user to www-data group, but it didn't help. Any idea why adding to user to www-data still don't allow user to copy a file to folder which is owned by www-data group?
  • Dimitris Sapikas
    Dimitris Sapikas over 11 years
    i didn't get the first solution , could you please be a litle more spesific ?
  • Dimitris Sapikas
    Dimitris Sapikas over 11 years
    Whe i say my own files i mean /var/www , i am using my vps as web server .... on my own folder i have full access
  • Dimitris Sapikas
    Dimitris Sapikas over 11 years
    i am using this solution any way , but what if i could get full access to my own file system , i don't want to type sudo chow ... for every single directory :S
  • trognanders
    trognanders over 11 years
    Changing ownership of all system files to the user for passing convenience is highly discouraged. It allows any userspace bug you might encounter to severely compromise the security of your system. It is much better to change the ownership of the files that you need to change or update by SCP, but to leave everything else owned by root (like it is supposed to be). That said, the -R in chown tells it to change the ownership of that directory, and all children files and directories recursively... so you can do anything you like.
  • Dimitris Sapikas
    Dimitris Sapikas over 11 years
    hmm .... that seems working fine , thank you ! sorry i can't upvote (system does not allow me to do ...)
  • Sergey
    Sergey over 11 years
    Re. the first solution. 1. scp -R mysite [email protected]:/home/dimitris/ 2. ssh [email protected] 3. sudo mv ~/mysite /var/www - it's a 2-step process, first you scp the files to your home dir, then you log in via ssh and copy/move the files to where they should be
  • test30
    test30 over 10 years
    @Braiam yeah, sure, sorry for link, the script is pretty long and that was the reason :)
  • mttdbrd
    mttdbrd about 9 years
    This is the best way to do it.
  • Michael Lindman
    Michael Lindman almost 9 years
    Welcome to Ask Ubuntu. Could you please include the script in your answer? I know it is unlikely but if the github repo was ever removed or the url changed then the answer would be void. It is better to include the script directly and leave the github repo as a source.
  • typeduke
    typeduke over 8 years
    I can't get this method to work successfully. As written I get sudo: sorry, you must have a tty to run sudo. If I add "-t" to allocate a TTY then I get Pseudo-terminal will not be allocated because stdin is not a terminal.. I can't see this working without passwordless sudo.
  • Mike D
    Mike D over 8 years
    I like the this answer but I recommend you direct it at the asked question versus more generalized commentary before upvote. something like ansible -i "hostname," all -u user --become -m copy -a ...
  • erik.weathers
    erik.weathers about 8 years
    @MikeD: how do the above changes look?
  • Mike D
    Mike D about 8 years
    better but it's fails, --module-name is the correct switch name. and since hostname is the only host in your inventory, you can just say all
  • erik.weathers
    erik.weathers about 8 years
    ah, definitely a great point with all, I've updated all 3 cmds with that. And good catch with --module-name instead of --module.
  • user3757405
    user3757405 almost 8 years
    Would something like -i 'host,' be valid syntax? I think it's easy to lose punctuation like that when reading a command. (For the reader I mean, if not the shell.)
  • erik.weathers
    erik.weathers almost 8 years
    hi @mwfearnley: I'm not sure I follow the question. The syntax is valid, in that it is the only way supported by ansible to directly specify the hostnames without using an inventory file. I agree that it's not obvious nor intuitive, but "it is what it is". ¯\_(ツ)_/¯
  • user3757405
    user3757405 almost 8 years
    I'm just wondering if the host, could be validly wrapped in quotes, just to show someone reading a script that: a) yes, there's supposed to be a comma there; and: b) don't worry, the extra punctuation won't, and can't, get misinterpreted by the shell.
  • erik.weathers
    erik.weathers almost 8 years
    @mwfearnley: sure, the shell will treat -i 'host,' and same as -i host, or -i "host,". In general I prefer to keep these invocations as short as possible to keep them from being daunting, but you should feel free to make it as verbose and explicit as you think is needed for clarity.
  • typeduke
    typeduke over 7 years
    @AlexanderBird While that works in many cases, I'm not sure it works here because we're trying to pipe a tarball over the SSH connection. See serverfault.com/questions/14389/…
  • markgo2k
    markgo2k about 6 years
    This answer is underrated. It's simple, clean, reads or writes a root file with a single atomic operation, and requires nothing that's not already guaranteed to be there if you're using scp. Main drawback is that it does not copy permissions. If you want that, the tar solution is better. This is a powerful technique, particularly if combined with xargs/bash magic to traverse paths..
  • forumulator
    forumulator almost 6 years
    This is what finally worked for me. You don't have permissions to a remote file that you want to copy to local, do a sudo tar, archive it, change permissions using chmod and chown, and then copy it to local. Especially if it's a directory.
  • jonatan
    jonatan over 5 years
    Way to go thinking outside the box! Great use of Ansible
  • przemo_li
    przemo_li over 5 years
    tar: Cowardly refusing to create an empty archive I think I'm selecting folders incorrectly is 'dir' the folder to be compressed? Is '/var/www/dir' the folder that will be created by uncompressing?
  • Korayem
    Korayem over 5 years
    I think the question was about uploading a file from local to remote and not vice versa
  • jaygooby
    jaygooby over 5 years
    If you're already in the directory you want to tar up, use tar -c * | ssh [email protected] "sudo tar -x --no-same-owner -C /var/www"
  • Ed Neville
    Ed Neville about 5 years
    Building on the above, what I tend to do is: tar -cf - * | ssh [email protected] sudo /bin/bash -c '( cd /var/www && tar -xf - --no-same-owner )', this is typically because /bin/bash is listed in sudoers but tar might not be at $CORP, or sometimes it is su - that is listed. It can get uglier :)
  • Jeremy
    Jeremy about 5 years
    Beautifully done. This is exactly what I was looking for both up and down. Thank you
  • Andrew Watson
    Andrew Watson almost 5 years
    Deserves to be the top answer, for sure.
  • lucidbrot
    lucidbrot almost 5 years
    Can this be done for a directory instead of a file as well?
  • conny
    conny over 4 years
    ...but you will need to pass -t to ssh, unless {a number of prerequisite assumptions}. Otherwise it will error with sudo: no tty present and no askpass program specified. And tee -a? The question is about copying, not about appending and at the same time echoing back to stdout.
  • Daniel Harding
    Daniel Harding about 4 years
    If using bash, you can use read -s passwd instead of using stty -echo and stty echo.
  • WinEunuuchs2Unix
    WinEunuuchs2Unix almost 4 years
    It's ludicrous you can't setup a root account to use scp for root owned files. sudo simply does not work. Who owns my computer me or Canonical? It's just as bad as Android and Google from that respect. IMHO. I just want to copy files from /usr/local/bin from one machine I OWN to another machine I OWN.
  • Sergey
    Sergey almost 4 years
    @WinEunuuchs2Unix: indeed you can to set up your machines so you can SSH in as root, all it takes is a small change in a config. Once you do that you can scp files as root as much as you want.
  • rh16
    rh16 almost 4 years
    I will add that another way around sudo: no tty present and no askpass program specified is to specify "sudo -S cat /etc/dir/file" rather than just "sudo cat /etc/dir/file"
  • Elliptical view
    Elliptical view almost 4 years
    "there is no sudo when working with scp", this is actually not completely true. You can use sudo scp.. to gain access to local root files. You can therefore ssh into the source machine, use and use sudo scp from there to get root files to or from a remote machine.
  • Sergey
    Sergey almost 4 years
    @Ellipticalview:That's a clever idea but it won't work in many scenarios (the source files are on a local machine behind NAT, no SSH server on the source machine, the files on the source machine are owned by root too :) )
  • Mohamed
    Mohamed over 3 years
    If you got something like "msg": "Missing sudo password" you can specify sudo user by appending --extra-vars "ansible_become_pass=yourPasswor" after -b
  • erik.weathers
    erik.weathers over 3 years
    @Mohamed : interesting workaround. My instinctual reaction is that you should be careful specifying your password in clear text like this. i.e., Ensure it's not getting written to your shell history & that you are not running on a shared server, since the parameter would be visible in the process table. Also make sure ansible isn't logging / storing this anywhere locally or on the remote server.
  • bitinerant
    bitinerant over 3 years
    The sudo -S cat ... trick is great, but be aware, it WILL DISPLAY YOUR PASSWORD on the screen.
  • Ernesto Allely
    Ernesto Allely over 3 years
    Another thing to have in mind is if the server has a display banner will be added to the file, as well as the message Connection to xxx.xxx.xxx.xxx closed. In order to avoid that happening you need to add -o LogLevel=QUIET to the ssh command. The command would be then ssh -o LogLevel=QUIET -t user@server "sudo cat /etc/dir/file" > /home/user/file.
  • Md. Minhazul Haque
    Md. Minhazul Haque about 3 years
    This should be the best answer. I just added -K which asks for sudo password.
  • FedericoCapaldo
    FedericoCapaldo over 2 years
    any way to do this for entire folders?
  • German Garcia
    German Garcia over 2 years
    how to do this for an entire directory: ssh user@server "tar -cf - dir" | tar -x
  • MewX
    MewX over 2 years
    Thanks! This is the best way for copying big protected files!