Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
This seems more like a question for your virtual server provider, or for the putty or winscp developers. – dobey Oct 29 '12 at 21:17
@dobey you obviusly wrong , it is about ubuntu privileges ! – Dimitris Sapikas Oct 30 '12 at 10:14
Why is this closed? This is a perfectly valid question about copying files with scp - every web developer is familiar with this situation – Sergey Oct 30 '12 at 22:02
Copying protected files between servers in one line? should help. – Gilles Oct 30 '12 at 23:04
up vote 48 down vote accepted

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.

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.

share|improve this answer
i didn't get the first solution , could you please be a litle more spesific ? – Dimitris Sapikas Oct 30 '12 at 9:42
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 Oct 30 '12 at 9:44
Re. the first solution. 1. scp -R mysite 2. ssh 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 – Sergey Oct 30 '12 at 21:58
hm.. it works fine ! thank you :) – Dimitris Sapikas Oct 31 '12 at 19:06

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

tar -c -C ./my/local/dir \
  | ssh "sudo tar -x --no-same-owner -C /var/www"
share|improve this answer
This is the best way to do it. – mttdbrd Mar 30 '15 at 20:31
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. – IBBoard Oct 26 '15 at 16:35

When you run sudo su, any files you create will be owned by root, but it is not possible by default to directly log in as root with ssh or scp. It is also not possible to use sudo with scp, so the files are not usable. Fix this by claiming ownership over your files:

Assuming your user name was dimitri, you could use this command.

sudo chown -R dimitri:dimitri /home/dimitri

From then on, as mentioned in other answers, the "Ubuntu" way is to use sudo, and not root logins. It is a useful paradigm, with great security advantages.

share|improve this answer
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 – Dimitris Sapikas Oct 30 '12 at 9:47
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. – Bailey S Oct 30 '12 at 17:48
hmm .... that seems working fine , thank you ! sorry i can't upvote (system does not allow me to do ...) – Dimitris Sapikas Oct 30 '12 at 19:05

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


  • 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/" \

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.

share|improve this answer
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 ... – Mike D Feb 16 at 19:30
@MikeD: how do the above changes look? – erik.weathers Feb 19 at 3:08
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 – Mike D Feb 19 at 20:40
ah, definitely a great point with all, I've updated all 3 cmds with that. And good catch with --module-name instead of --module. – erik.weathers Feb 19 at 21:01
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.) – mwfearnley Jun 10 at 15:37

You may use script I've written being inspired by this topic:

touch /tmp/justtest && scpassudo /tmp/justtest

but this requires some crazy stuff (which is btw. automatically done by script)

  1. server which file is being sent to will no longer ask for password while establishing ssh connection to source computer
  2. due to necessarility of lack of sudo prompt on the server, sudo will no longer ask for password on remote machine, for user

Here goes the script:

if [[ $# -ge 3 ]]; then interface=$3; fi
thisIP=$(ifconfig | grep $interface -b1 | tail -n1 | egrep -o '[0-9.]{4,}' -m1 | head -n 1)

if [[ $# -eq 0 ]]; then 
echo -e "Send file to remote server to locatoin where root permision is needed.\n\tusage: $0 local_filename [username@](ip|host):(remote_folder/|remote_filename) [optionalInterface=wlan0]"
echo -e "Example: \n\ttouch /tmp/justtest &&\n\t $0 /tmp/justtest "
exit 1


test -e $localFilePath 

usernameAndHost=$(echo $destString | cut -f1 -d':')

if [[ "$usernameAndHost" == *"@"* ]]; then
destUser=$(echo $usernameAndHost | cut -f1 -d'@')
destIP=$(echo $usernameAndHost | cut -f2 -d'@')

destFolderOnRemoteMachine=$(echo $destString | cut -f2 -d':')

set -e #stop script if there is even single error

echo 'First step: we need to be able to execute scp without any user interaction'
echo 'generating public key on machine, which will receive file'
ssh $destUser@$destIP 'test -e ~/.ssh/ -a -e ~/.ssh/id_rsa || ssh-keygen -t rsa'
echo 'Done'

echo 'Second step: download public key from remote machine to this machine so this machine allows remote machine (this one receiveing file) to login without asking for password'

key=$(ssh $destUser@$destIP 'cat ~/.ssh/')
if ! grep "$key" ~/.ssh/authorized_keys; then
echo $key >> ~/.ssh/authorized_keys
echo 'Added key to authorized hosts'
echo "Key already exists in authorized keys"

echo "We will want to execute sudo command remotely, which means turning off asking for password"
echo 'This can be done by this tutorial'
echo 'This you have to do manually: '
echo -e "execute in new terminal: \n\tssh $destUser:$destIP\nPress enter when ready"
echo 'run there sudo visudo'
echo 'change '
echo '    %sudo   ALL=(ALL:ALL) ALL'
echo 'to'
echo '    %sudo   ALL=(ALL:ALL) NOPASSWD: ALL'
echo "After this step you will be done."

listOfFiles=$(ssh $destUser@$destIP "sudo ls -a")

if [[ "$listOfFiles" != "" ]]; then 
echo "Sending by executing command, in fact, receiving, file on remote machine"
echo 'Note that this command (due to " instead of '', see man bash | less -p''quotes'') is filled with values from local machine'
echo -e "Executing \n\t""identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"" \non remote machine"
ssh $destUser@$destIP "identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"
ssh $destUser@$destIP "ls ${destFolderOnRemoteMachine%\\\\n}/$(basename $localFilePath)"
if [[ ! "$?" -eq 0 ]]; then echo "errror in validating"; else echo -e "SUCCESS! Successfully sent\n\t$localFilePath \nto \n\t$destString\nFind more at"; fi
echo "something went wrong with executing sudo on remote host, failure"

) | sudo tee /usr/bin/scpassudo && chmod +x /usr/bin/scpassudo
share|improve this answer
@Braiam yeah, sure, sorry for link, the script is pretty long and that was the reason :) – test30 Nov 22 '13 at 1:42

You can combine ssh, sudo and e.g tar to transfer files between servers without being able to log in as root and not having the permission to access the files with your user. This is slightly fiddly, so I've written a script to help this. You can find the script here:

or here:

#! /bin/bash
if test -z "$from" -o -z "$to" -o -z "$files"
    echo "Usage: $0    (file)*"
    echo "example: $0 server1 server2 /usr/bin/myapp"
    exit 1

read -s -p "Enter Password: " sudopassword
echo ""
(echo "$sudopassword";echo "$sudopassword"|ssh $from sudo -S tar c -P -C / $files 2>$temp1)|ssh $to sudo -S tar x -v -P -C / 2>$temp2
if [ $? -ne 0 -o $sourceres -ne 0 ]
    echo "Failure!" >&2
    echo "$from output:" >&2
    cat $temp1 >&2
    echo "" >&2
    echo "$to output:" >&2
    cat $temp2 >&2

rm $temp1 $temp2
exit $res
share|improve this answer
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. – Michael Lindman Jul 1 '15 at 15:25

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.