How can I upload more than one file with vagrant file provisioning?

10,994

Solution 1

You would need a separate config.vim.provision section for each file. You can add multiple of those sections to your Vagrantfile, like this:

config.vm.provision :file do |file|
  file.source = "/etc/file1.txt"
  file.destination = "/tmp/1.txt"
end

config.vm.provision :file do |file|
  file.source = "/etc/file2.txt"
  file.destination = "/tmp/2.txt"
end

Output:

[default] Running provisioner: file...
[default] Running provisioner: file...

You see it is executing both provisioning actions. You can verify the file presence inside the virtual machine:

vagrant ssh -- ls -al /tmp/{1,2}.txt
-rw-r--r-- 1 vagrant vagrant 4 Aug 27 08:22 /tmp/1.txt
-rw-rw-r-- 1 vagrant vagrant 4 Aug 27 08:22 /tmp/2.txt

Solution 2

Folder content uploads seem to work as well (I've only tried it with files, not nested folders):

config.vm.provision :file, source: '../folder', destination: "/tmp/folder"

Solution 3

In case anybody else just needs a quick and dirty hack to copy a directory structure from the host to the guest, this is how I finally did it:

require 'pathname' # at the beginning of the Vagrantfile

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  # more configuration here

  r = Pathname.new 'root'
  Dir.glob(File.join("root", File.join("**","*"))) do |f|
    if !File.directory?(f) then
      s = Pathname.new f
      t = s.relative_path_from r
      config.vm.provision "file" do |fp|
        fp.source = s.to_s
        fp.destination = "/tmp/root/" + t.to_s
      end
    end
  end

  # more configuration here

end

Thanks to @hek2mgl for getting me on the right track.

Solution 4

You can use file provisioner, as others had mentioned but it's still worth noting that it's possible to use a synced folder functionality with type set to rsync: http://docs.vagrantup.com/v2/synced-folders/rsync.html:

Vagrant can use rsync as a mechanism to sync a folder to the guest machine. This synced folder type is useful primarily in situations where other synced folder mechanisms are not available, such as when NFS or VirtualBox shared folders aren't available in the guest machine.

The rsync synced folder does a one-time one-way sync from the machine running to the machine being started by Vagrant.

On the first vagrant up syncing happens before provisioners are executed. Sample configuration in Vagrantfile would look like this:

config.vm.synced_folder "upload/", "/home/vagrant", type: "rsync"
Share:
10,994
Giacomo Tesio
Author by

Giacomo Tesio

I'm able to rapidly identify the independent variables that govern complex problems and to plan a strategy to avoid (or at least to solve) them through the use of the proper tools. Whenever the current technological offer does not match to my requirements, I can design and develop the missing tools or hack into existing ones. During the last 5 years, I've gained some experience with Domain Driven design and supporting architecture and I'm building Epic as a "DDD software factory" that aims to make DDD much more cheaper than it is now. I've also contributed to various opensource projects with patches and bugfixes.

Updated on June 05, 2022

Comments

  • Giacomo Tesio
    Giacomo Tesio almost 2 years

    In a Vagrant setup, I have to upload a couple of files from the host to the guest during the provisioning phase.

    In https://docs.vagrantup.com/v2/provisioning/file.html I can see how to upload a single file, from a source to a destination, but how can I upload multiple files or a folder structure?

    NOTE: I know I can do that using the shell provisioner, but in this particular case a set of file uploads would be more appropriate.

  • Giacomo Tesio
    Giacomo Tesio over 9 years
    Looks exactly what I was looking for... Any tip for entire folder structures?
  • hek2mgl
    hek2mgl over 9 years
    @GiacomoTesio When you want to make a whole folder accessible, use config.vm.synced_folder
  • Giacomo Tesio
    Giacomo Tesio over 9 years
    that's not what I need. For example I have a few files to be moved into /etc/apt/source.list.d/ from the host machine. I tried with tar in the shell provisioner (something like (cd root/ && tar cf - *) | (cd / && tar xf - --keep-old-files) ), but it doesn't works.
  • hek2mgl
    hek2mgl over 9 years
    Then you need to iterate over the folder with ruby and create the config.vm.provision entries dynamically.
  • zifot
    zifot over 8 years
    Yep, that seems to be working just fine. Also with nested folders.
  • Steve
    Steve over 8 years
    i had trouble with this. source:'../one/two', destination: '/destination' works as expected the first time, with all the files in /destination. Run vagrant provision again and you get all the files in /destination/two
  • Giacomo1968
    Giacomo1968 about 8 years
    -1: As presented this config is quite dangerous and destructive to basic Vagrant functionality. I am using Vagrant 1.8.1 on Mac OS X 10.10.5 (Yosemite). By setting the source to upload/ and the destination to /home/vagrant the Rsync process will overwrite /home/vagrant which means the Vagrant user’s .ssh directory will be wiped out so they can no longer login to this machine via SSH after this command is run. The destination should be /home/vagrant/upload/ so the config should be, config.vm.synced_folder "upload/", "/home/vagrant/upload/", type: "rsync".
  • Giacomo1968
    Giacomo1968 about 8 years
    While this is an older answer, the synced folder with Rsync option explained in this other answer conceptually works; just as the presented it’s dangerous. Setting a line like this in your Vagrantfile should work fine: config.vm.synced_folder "upload/", "/home/vagrant/upload/", type: "rsync".
  • Giacomo1968
    Giacomo1968 about 8 years
    While this appears to work, the problem is a nested folder issue. In this case /tmp/ gets flushed with each restart of the Vagrant box so you won’t see it. But if you used this command with the following destination that’s persistent between restarts: /home/vagrant/folder/. The first time the Vagrant box is started you get /home/vagrant/folder/. The next time the Vagrant box is started you would get /home/vagrant/folder/folder/. And the next after that? /home/vagrant/folder/folder/folder/. config.vm.synced_folder with type: "rsync" works better. Using Vagrant 1.8.1.