304

I have a use case where I occasionally want to copy a single file from my host machine to the Vagrant guest.

I don't want to do so via traditional provisioners (Puppet / Chef) because this is often a one-off -- I just want something quick to add to my Vagrantfile.

I don't want to share an entire directory, possibly because I want to overwrite an existing file without nuking an entire directory on the guest.

It also seems a bit overkill to write a shell provisioning script, and deal with potential escaping, when all I want to do is copy a file.

So, what's the easiest way to copy a single file from host to guest?

LeeXGreen
  • 3,575
  • 2
  • 18
  • 14
  • note that the accepted answer is based on Vagrant 1.x--[using a file provisioner is the standard Vagrant 2 approach](http://stackoverflow.com/a/23302212/60724), although changing the mount point of `/vagrant` [as mentioned here](http://stackoverflow.com/a/22563024/60724) can also be a good option – STW Nov 07 '15 at 16:29
  • 11
    The answer from @jouell really merits more votes for the simple use case of a one-off copy of a single file: `vagrant upload /path/to/my/file`... – dat Jan 23 '19 at 18:20
  • 1
    `vagrant scp file.txt :~/.` – AlikElzin-kilaka Aug 28 '19 at 05:23
  • https://stackoverflow.com/a/53908426/547569 by https://stackoverflow.com/users/3462494/jouell should be the accepted answer. It is an inbuilt command to the Vagrant CLI to copy a file or directory to a host `vagrant upload SOURCE [DESTINATION] [NAME|ID]`. I missed that initially because it is buried too far down. – tmoschou Feb 11 '21 at 05:43

20 Answers20

301

Since you ask for the easiest way, I suggest using vagrant-scp. It adds a scp command to vagrant, so you can copy files to your VM like you would normally do with scp.

Install via:

vagrant plugin install vagrant-scp

Use it like so:

vagrant scp <some_local_file_or_dir> [vm_name]:<somewhere_on_the_vm>
sakovias
  • 1,356
  • 1
  • 17
  • 26
Luca Invernizzi
  • 6,489
  • 3
  • 28
  • 26
  • 1
    This didn't work for me. I installed the plugin, but kept getting an error that said "The plugin "vagrant-scp" could not be found. Please make sure that it is properly installed via `vagrant plugin`." – rockerston May 07 '15 at 15:55
  • 6
    Hi Rod, vagrant-scp works with Vagrant 1.7+. From the bug you opened, you are running 1.4.3. If you need this plugin, I'm afraid you'll have to upgrade (which is quick and painless). – Luca Invernizzi May 09 '15 at 02:37
  • Hi Abram, please have a look at the [readme](https://github.com/invernizzi/vagrant-scp), it'll show you how to upgrade your Vagrant version. – Luca Invernizzi Jun 29 '15 at 15:15
  • 2
    I tried this command to copy files but didn't work and giving error `vagrant scp /vagrant/www/koushik.php ubuntu/trusty64:/usr/share/nginx/html` I am trying to copy files into the nginx root directory. It says, `The machine with the name 'C' was not found configured for this Vagrant environment. `The directory and everything is fine. – Koushik Das Sep 23 '16 at 06:08
  • 3
    One thing to add: You have to use the ID of the machine that you can get with vagrant global-status in the first column. Nontheless, this is the best solution imho. – Horsty Mar 07 '17 at 13:08
  • This did not work for me as I have multiple VMS and for some reason there were issues even after specifying the VM name. What I wound up doing is hosting the file as a URL and downloading it. – invertedfjord Nov 08 '17 at 16:45
  • 1
    @KoushikDas Doesn't work out of the box on windows. You have to enable the Ubuntu subsystem on windows 10, and then instead of putting C:/.. for the path to the file, you put /mnt/c/... And works hooray! Also note the other comment, use vagrant global-status to get the id of the vagrant machine. – Andrew Dec 04 '18 at 15:17
  • I had a "Conflicting dependency" `fog-core` issue, solution: `wget -c https://releases.hashicorp.com/vagrant/2.0.3/vagrant_2.0.3_x86_64.deb` then `sudo dpkg -i vagrant_2.0.3_x86_64.deb`, I found the solution here: https://tutorials.technology/solved_errors/Vagrant-plugin-install--conflicting-dependencies-fog-core--~%3E-1_43_0--and-fog-core----1_45_0-.html – Waqleh Dec 24 '18 at 10:18
  • vagrant 2.2.6 works fine with this command it automatically adds localhost ip on port 2222 in the lists of known hosts: `$ vagrant scp mongod.config mongod-m103:~/ Warning: Permanently added '[127.0.0.1]:2222' (ECDSA) to the list of known hosts. mongod.config 100% 331 512.2KB/s 00:00 ` – briancollins081 Jan 08 '20 at 07:45
  • worked best for me. my use case was not to rebuild the VM, it was to get stuff in and out of it easily once it was running, so a file provisioner.... no. and `/vagrant/` wasn't mounted for whatever reason. this does the trick and is bi-directional: host 2 guest, guest to host, but is running from the host command line. nifty. – JL Peyret Mar 06 '20 at 01:03
168

There is actually a much simpler solution. See https://gist.github.com/colindean/5213685/#comment-882885:

"please note that unless you specifically want scp for some reason, the easiest way to transfer files from the host to the VM is to just put them in the same directory as the Vagrantfile - that directory is automatically mounted under /vagrant in the VM so you can copy or use them directly from the VM."

Eric P
  • 4,587
  • 6
  • 24
  • 19
138

Instead of using a shell provisioner to copy the file, you can also use a Vagrant file provisioner.

Provisioner name: "file"

The file provisioner allows you to upload a file from the host machine to the guest machine.

Vagrant.configure("2") do |config|
  # ... other configuration

  config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig"
end
Community
  • 1
  • 1
lynnaloo
  • 1,600
  • 1
  • 11
  • 5
  • 4
    This is definitely the best way to do this in Vagrant 2! However, Vagrant 2 was not available at the time I needed to do this... :) – LeeXGreen Jul 26 '14 at 15:35
  • 4
    This solution sounds nice, but i can't copy any file due to permission errors. – orbatschow Jul 10 '16 at 16:44
  • @orbatschow I had the same problem, but not if I copied it to `/tmp` – Ben Jun 18 '17 at 06:08
  • 7
    this is not what the OP asked. the question was how to _occasionally_ transfer files; having to run provisioning is overkill. – axd Jan 10 '18 at 13:25
111

Introducing a method that does not require installing any plugins and eliminates the need to provide the private key (which can easily be forgotten):

By default, the first Vagrant instance uses port 2222 for SSH and its IP address is 127.0.0.1. (Please adjust the port if you have created multiple virtual hosts.)

==> default: Forwarding ports...
default: 22 (guest) => 2222 (host) (adapter 1)

With this setup, you can use the following command to copy your local file to the Vagrant instance in any desired path, not just the /vagrant folder. The password is the same as the username, which is vagrant

scp -P 2222 your_file vagrant@127.0.0.1:.

You can also copy files back to your local host using the following command:

scp -P 2222 vagrant@127.0.0.1:/PATH/filename
BMW
  • 42,880
  • 12
  • 99
  • 116
  • 3
    I had to do this and disable strict key checking: `scp -P 2222 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no my-file.txt matt@127.0.0.1:/tmp` – Matt Feb 19 '15 at 19:03
  • I will recommend to add these ssh options into `~/.ssh/config` as default, which I did it in my environment: `StrictHostKeyChecking no` – BMW Feb 19 '15 at 22:40
  • 1
    +1 + If one has more than one virtual machines the value of the port should be taken from the UI of the Oracle VM VirtualBox Manager - select vm on the left , settings , network , port forwarding – Yordan Georgiev May 09 '15 at 06:59
  • 2
    This is better than the accepted answer. The /vagrant directory isn't always there. – jimm101 Dec 09 '15 at 22:56
  • Surprising how much harder it is to get `rsync` to work in this case compared to `scp`, given rsync's description as a "faster, flexible replacement for rcp." – Wildcard Apr 05 '17 at 06:29
  • using `-i .vagrant/machines/MY_VM/virtualbox/private_key` works for me – shcherbak Apr 09 '19 at 23:25
69
vagrant upload localfile

that will put localfile in the vagrant user's home dir

https://www.vagrantup.com/docs/cli/upload.html

jouell
  • 3,288
  • 1
  • 18
  • 15
64

Here is my approach to the problem:

Step 1 - Find the private key, ssh port and IP:

root@vivi:/opt/boxes/jessie# vagrant ssh-config
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /root/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

Step 2 - Transfer file using the port and private key as parameters for scp:

  scp -P 2222 -i /root/.vagrant.d/insecure_private_key \
  someFileName.txt vagrant@127.0.0.1:~

I hope it helps,

alfredocambera
  • 3,155
  • 34
  • 29
27

What I ended up doing was to keep the file within my vagrant directory (automatically mounted as /vagrant/) and copy it over with a shell provisioner:

command = "cp #{File.join('/vagrant/', path_within_repo)} #{remote_file}"
config.vm.provision :shell, :inline => command
LeeXGreen
  • 3,575
  • 2
  • 18
  • 14
  • 4
    I'd recommend using coreutils [`install`](http://www.gnu.org/software/coreutils/manual/html_node/install-invocation.html#install-invocation) e.g. `install -D -m644 -C ...` src dest. instead of cp, because you can do things like specify the permissions, ownership, automatically create leading directories, only do the copy if the file needs to be updated, etc... instead of cp, which is simple and fine if that's all you need to do. – xenoterracide Jun 12 '14 at 14:07
  • @LeeXGreen. I'm trying to to do the same thing you were trying to do but I don't quite get your answer. Did you type that line of code in the terminal? Where exactly did you place that? – Dan Rubio Jul 24 '14 at 18:49
  • The code snippet from my answer goes in your `Vagrantfile` alongside your other provisioners. You'll need to replace `path_within_repo` and `remote_file` with things that make sense, for your application, of course :) – LeeXGreen Jul 26 '14 at 15:33
  • Works but I get " default: stdin: is not a tty" error – radtek Jan 20 '15 at 02:42
21

If you are restrained from having the files in your directory, you can run this code in a script file from the Host machine.

#!/bin/sh
OPTIONS=`vagrant ssh-config | awk -v ORS=' ' '{print "-o " $1 "=" $2}'`

scp ${OPTIONS} /File/To/Copy vagrant@YourServer:/Where/To/Put/File

In this setup, you only need to change /File/To/Copy to the file or files you want to copy and then /Where/To/Put/File is the location on the VM you wish to have the files copied to.

If you create this file and call it copyToServer.sh you can then run the sh command to push those files.

sh ./copyToServer.sh

As a final note, you cannot run this code as a provisioner because that runs on the Guest server, while this code runs from the Host.

geedew
  • 1,368
  • 12
  • 16
  • 1
    This is probably the best solution outside of installing the vagrant-scp plugin. It uses the SSH configuration that Vagrant uses so it can handle the different network setups provided by different providers. – Sandy Chapman May 07 '15 at 12:53
  • 1
    Nice! I suggest you also note that people can simply take the output of `vagrant ssh-config` and paste it into their ~/.ssh/config file, to make this even easier in the future. I.e. combining this with chf's answer – nealmcb Jul 06 '15 at 04:38
  • 2
    I have found it necessary to skip the first line of the ssh-config output to avoid the error "Host directive not supported as a command-line option" -- caused by the header for the ssh-config section: "Host default". So, my script has `OPTIONS=\`vagrant ssh-config | tail -n +2 | awk -v ORS=' ' '{print "-o " $1 "=" $2}'\`` to omit using that first line of ssh-config output. – troyfolger Mar 03 '16 at 23:37
  • 2
    Alternatively, to remove the "Host directive not supported" error you can use `OPTIONS=\`vagrant ssh-config | grep -v '^Host ' | awk -v ORS=' ' 'NF{print "-o " $1 "=" $2}'\`` as documented here: https://gist.github.com/geedew/11289350 – user783836 Jun 21 '18 at 18:20
13

All the above answers might work. But Below is what worked for me. I had multiple vagrant host: host1, host2. I wanted to copy file from ~/Desktop/file.sh to host: host1 I did:

    $vagrant upload ~/Desktop/file.sh host1

This will copy ~/Desktop/file.sh under /home/xxxx where xxx is your vagrant user under host1

onlyme
  • 3,776
  • 2
  • 23
  • 17
12

Vagrant provides a way to execute a command over ssh instead of logging in, so for Linux host and guest you can use:

  • from host to guest:

cat ~/file_on_host.txt | vagrant ssh -c 'cat - > ~/file_on_guest.txt'

  • from guest to host:

vagrant ssh -c 'cat ~/file_on_guest.txt' > ~/file_on_host.txt

No need for plugins or guest reloads. Just make sure to provide vagrant box ID to 'vagrant ssh' if you are not in the same dir as the Vagrantfile. Tested on Vagrant v1.8.1.

user7962684
  • 121
  • 1
  • 3
9

You can add entry in ~/.ssh/config:

Host vagrant
    User vagrant
    HostName localhost
    Port 2222
    IdentityFile /home/user_name/.vagrant.d/insecure_private_key

and the simplescp file vagrant:/path/. You can find path to identity file using the vagrant ssh-config command.

chf
  • 107
  • 1
  • 3
  • 1
    Very helpful, and helps clarify what is going on. This lets you copy both directions, do recursive copies, etc. and leverages existing knowledge of scp / ssh nicely – nealmcb May 27 '15 at 22:43
  • 1
    I just re-read the answers above and discovered by playing wiht geedew's answer that `vagrant ssh-config` gives you an even more complete and convenient config snipped that you can put in your ~/.ssh/config. But thanks again! – nealmcb Jul 06 '15 at 04:37
8

Go to the directory where you have your Vagrantfile
Then, edit your Vagrantfile and add the following:

config.vm.synced_folder ".", "/vagrant", :mount_options => ['dmode=774','fmode=775']

"." means the directory you are currently in on your host machine
"/vagrant" refers to "/home/vagrant" on the guest machine(Vagrant machine).

Copy the files you need to send to guest machine to the folder where you have your Vagrantfile Then open Git Bash and cd to the directory where you have your Vagrantfile and type:

vagrant scp config.json XXXXXXX:/home/vagrant/

where XXXXXXX is your vm name. You can get your vm name by running

vagrant global-status
akshaynagpal
  • 2,965
  • 30
  • 32
8

if for some reasons you don't have permission to use

vagrant plugin install vagrant-scp

there is an alternative way :

First vagrant up yourVagrantProject, then write in the terminal :

vagrant ssh-config

you will have informations about "HostName" and "Port" of your virtual machine.

In some case, you could have some virtual machines in your project. So just find your master-machine (in general, this VM has the port 2222 ), and don't pay attention to others machines informations.

write the command to make the copy :

scp -P xxPortxx  /Users/where/is/your/file.txt  vagrant@xxHostNamexx:/home/vagrant

At this steep you will have to put a vagrant password : by default it's "vagrant"

after that if you look at files in your virtual machine:

vagrant ssh xxVirtualMachineNamexx
pwd
ls

you will have the "file.txt" in your virtual machine directory

slideWXY
  • 1,121
  • 8
  • 9
5

vagrant scp plugin works if you know your vagrant box name. check vagrant global-status which will provide your box name then you can run:

vagrant global-status
id       name    provider   state   directory
------------------------------------------------------------------------
13e680d  **default** virtualbox running /home/user

vagrant scp ~/foobar "name in my case default":/home/"user"/

ankidaemon
  • 1,363
  • 14
  • 20
Bálint Szigeti
  • 301
  • 3
  • 4
  • 1
    this worked for me. the edit is also helpful, i would also include the command to install the vagrant scp plugin. – WhyAyala Jan 13 '17 at 20:54
2

An alternative way to do this without installing anything (vagrant-scp etc.) Note that the name default needs to be used as is, since vagrant ssh-config emits that.

vg_scp() {
  tmpfile=$(mktemp /tmp/vagrant-ssh-config.XXXX)
  vagrant ssh-config > $tmpfile
  scp -F $tmpfile "$@"
  rm $tmpfile
}

# Copy from local to remote
vg_scp somefile default:/tmp

# Copy from remote to local
vg_scp default:/tmp/somefile ./

# Copy a directory from remote to local
vg_scp -r default:/tmp ./tmp

The function would not be necessary if scp -F =(vagrant ssh-config) ... would have worked across shells. But since this is not supported by Bash, we have to resort to this workaround.

Gurjeet Singh
  • 2,635
  • 2
  • 27
  • 22
2

If someone wants to transfer file from windows host to vagrant, then this solution worked for me.

1. Make sure to install **winscp** on your windows system
2. run **vagrant up** command
3. run **vagrant ssh-config** command and note down below details
4. Enter Hostname, Port, Username: vagrant, Password: vagrant in winscp and select **SCP**, file protocol 
5. In most cases, hostname: 127.0.0.1, port: 2222, username: vagrant, password: vagrant.

You should be able to see directories in your vagrant machine.

Lufy
  • 175
  • 1
  • 10
1

Try this.. vagrant ubuntu 14.04 This worked for me.

scp -r -P 2222 vagrant@localhost:/home .
Buddy
  • 10,874
  • 5
  • 41
  • 58
O.Caliari
  • 313
  • 2
  • 5
1

If you "cd .." enough times you will find the vagrant folder which contains all your host files and folder

jedidiah
  • 11
  • 2
0

The best ans for me is to write the file / directory(to be copied) to the vagrant file directory, now any file present there is available to vagrant in path /vagrant.

That's it, no need of scp or any other methods,

similarly you can copy any file from VM to host by pasting in /vagrant directory.

-3

Best way to copy file from local to vagrant, No need to write any code or any thing or any configuration changes. 1- First up the vagrant (vagrant up) 2- open cygwin 3- cygwin : go to your folder where is vagrantfile or from where you launch the vagrant 4- ssh vagrant 5- now it will work like a normal system.

D-2020365
  • 82
  • 1
  • 11
  • One problem I've discovered with this approach: if vagrant needs to configure your Guest Additions, the /vagrant directory may not actually be mounted when the file provisioner runs. – Torenware Networks Mar 15 '18 at 06:17