Scripting

How to Transfer Files Between a Host and a Vagrant VM

In this tutorial, we will look at two methods for exchanging files between a Vagrant-managed virtual machine and its host.

Working with Vagrant regularly involves exchanging files between your host machine and the managed virtual machines. Whether you need to deploy configuration scripts, sync source code, retrieve logs, etc., you should know that Vagrant includes built-in tools for this. The two main ones are: 

  • Using the vagrant-scp plugin for one-off command-line transfers.
  • Shared folders (synced_folders) for automatic and transparent synchronization.

Here, we will study both methods as well as the value of each one. The prerequisites for following this tutorial are the following:

  • Vagrant must be installed and working on your system;
  • A Vagrant virtual machine that has already been created and started.

Using vagrant-scp for One-Off Transfers

Installing the Plugin

The vagrant scp command is a simple command that copies files between your host machine and a Vagrant VM, without any prior configuration on the managed VMs. This command is available through a plugin. The vagrant-scp plugin is not included by default in Vagrant. To install it, we will run the following command to install it on the Vagrant host:

vagrant plugin install vagrant-scp

We can then verify that the plugin is installed correctly with:

$ vagrant plugin list

[...]
vagrant-scp (0.5.9, global)

As in my example, the vagrant-scp plugin should appear in the list.

Basic vagrant-scp Syntax

The command for transferring a file from the host to the Vagrant VM is as simple as using the classic scp command on Linux:

vagrant scp <source_file> <vm_name>:<destination_path>

Keep in mind that by default, when a VM is deployed, Vagrant generates a key pair that gives it SSH access to the system as the vagrant user. This key pair is used for file transfers through the scp plugin, as well as for command execution.

This means that by default, the vagrant scp command uses the privileges of the vagrant user, so you won't be able to place files just anywhere.

Here is an example with a file located in the current folder on the host:

$ vagrant scp ./mon_script.sh debian1:/home/vagrant/

Mon_script.sh 100%   13    52.4KB/s   00:00

This command copied the file mon_script.sh from my current directory to /home/vagrant/ in the debian1 VM. We can then confirm that the file is present inside the VM:

$ vagrant ssh debian1 -c "pwd;ls -l"

/home/vagrant
total 8
-rw-r--r-- 1 vagrant vagrant 445 Jun 30 20:02 index.html
-rw-r--r-- 1 vagrant vagrant  13 Jul  1 20:19 mon_script.sh

Of course, you can do the reverse and download a file from your VM to your host just as easily: 

vagrant scp <vm_name>:<source_file> <destination_path>

# Example
vagrant scp debian1:mon_script.sh ~/

# or
vagrant scp debian1:/home/vagrant/mon_script.sh ~/

Be careful: vagrant-scp does not natively handle directories. To work around this, we can compress the directory before transferring it, then use command execution to reverse the operation. Example with a scripts/ directory:

# From the host to the VM
$ tar -czf scripts.tar.gz scripts/ | vagrant scp scripts.tar.gz debian1:/home/vagrant/

scripts.tar.gz 100%  193   386.9KB/s   00:00    

$ vagrant ssh debian1 -c "tar zxvf scripts.tar.gz"
$ vagrant ssh debian1 -c "pwd;ls -l"

/home/vagrant
total 16
drwxr-xr-x 2 vagrant vagrant 4096 Jul  1 20:23 scripts
-rw-r--r-- 1 vagrant vagrant  193 Jul  1 20:25 scripts.tar.gz

Best Practices, Limits, and Common Errors

Here are some best practices to avoid errors and misunderstandings when using this command: 

  • Use absolute paths to avoid mistakes.
  • Check the VM name with vagrant status if you have multiple VMs.
  • Make sure the vagrant user inside the VM has write permissions on the destination path.

You should also understand the limits and specifics of the command, which can sometimes differ slightly from classic scp

  • vagrant-scp does not handle wildcards (*). To copy multiple files, use a bash loop or tar, as we saw above;
  • No progress bar is displayed during the transfer; output appears at the end of the transfer;
  • Files with spaces in their name must be enclosed in quotes to avoid breaking the command.

Here are some common errors you may encounter, along with likely solutions:

ProblemSolution
Command not found: vagrant-scpCheck that the plugin is installed on the host with vagrant plugin list.
machine with the name '[...]' was not found configuredUse vagrant status to list the available VMs.
Permission deniedCheck file or path permissions in the VM with ls -l.
No such file or directoryVerify that the source path exists (on the host or in the VM).
The provider for this Vagrant-managed machine is reporting that itis not yet ready for SSH.Make sure the VM is started with vagrant up.

Let's now move on to a second classic method for transferring files from the host to a VM managed by vagrant.

Using Shared Folders (synced_folders)

Shared folders make it possible to automatically synchronize a directory between your host machine and the VM. Any change made in one is reflected in the other; this is what is usually used with a "classic" virtual machine.

Configuration in the Vagrantfile

To enable a shared folder, we will modify our Vagrantfile before starting the VM and add the following line:

config.vm.synced_folder "<host_path>", "<vm_path>"

In my example, ./dossier_local is the relative or absolute path of the folder on my host and /dossier_vm is the path of that same folder (synchronized) in the VM. Full file example:

Vagrant.configure("2") do |config|
  config.vm.define "debian1" do |debian1|
    debian1.vm.box = "debian/bookworm64"
    debian1.vm.hostname = "debian1"
    debian1.vm.network "private_network", ip: "192.168.56.101"
    
    # Shared folder configuration
    debian1.vm.synced_folder "~/Documents/vagrant_share", "/mnt/vagrant_share"
    
    debian1.vm.provider "virtualbox" do |vb|
      vb.memory = "1024"
      vb.cpus = 1
    end
  end
end

Using Shared Folders

After modifying the Vagrantfile, start or reload the VM to apply the changes:

# Deploy the environment or start an existing one
vagrant up

# Reload a running environment to apply the change
vagrant reload

In all cases, you should see a line like this in the logs displayed in the terminal: 

==> debian1: Mounting shared folders...
    debian1: /home/mickael/Documents/vagrant_share => /mnt/vargant_share

These two folders are now synchronized; you can use them as a file exchange directory between the host and the virtual machine, or even between multiple virtual machines!

Transfert de fichier vie un répertoire partagé vagrant.
Transfert de fichier vie un répertoire partagé vagrant.

Keep in mind that by default, Vagrant already synchronizes the directory containing the Vagrantfile to /vagrant in the VM. If you do not need it, you can add this configuration to your Vagrantfile:

config.vm.synced_folder ".", "/vagrant", disabled: true

Vagrant supports several file synchronization mechanisms. The choice depends on your host OS and your performance needs. Advanced users may choose methods other than the default VirtualBox Shared Folders, such as NFS, Rsync or SMB.

Which Method Should You Choose?

We have just looked at two different methods for exchanging files between a Vagrant-managed VM and its host. Here is a brief summary of both methods, along with their advantages and limitations: 

Criteriavagrant-scpShared folders (synced_folders)
Transfer typeOne-off (manual)Continuous (automatic)
Ease of useSimple for individual filesIdeal for frequently used folders and files
PerformanceFast for small filesCan be slow for large folders or many files (especially with VirtualBox)
SynchronizationOne-way (depending on the command)Bidirectional (depending on the configuration)
ConfigurationNone required (plugin to install)Requires a change to the Vagrantfile
Use caseOccasional transfersDevelopment, testing, configurations

In short, you can use vagrant-scp if you need to transfer one or a few files occasionally, or if you prefer a simple and direct command-line solution, or if you do not want to modify your Vagrantfile.

On the other hand, you can use shared folders if you work with frequently changed files (for example, source code or logs) and want automatic synchronization without manual intervention between the host and the VM, or even between multiple VMs.

Conclusion

The two methods presented in this tutorial provide complementary solutions for transferring files between your host machine and a Vagrant VM.

  • vagrant-scp for simple, one-off transfers through the command line.
  • Shared folders for automatic and transparent synchronization, especially in a development or testing context.

Depending on your needs, you can choose one method or the other, or even combine them to take advantage of their respective strengths.

author avatar
Mickaël Dorigny Co-founder
Co-founder of IT-Connect. Auditor/Pentester at Orange Cyberdéfense.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.