Vagrant is an open source tool to quickly setup machines that can be used for development and testing. They can be local virtual machines, Docker containers, AWS EC2 instances, and so on
In this page we discuss how to create a Vagrantfile, which you can use to create new boxes or machines. This content is specifically written to address the needs of MariaDB users.
A Vagrantfile is a Ruby file that instructs Vagrant to create, depending on how it is executed, new Vagrant machines or boxes. You can see a box as a compiled Vagrantfile. It describes a type of Vagrant machines. From a box, we can create new Vagrant machines. However, while a box is easy to distribute to a team or to a wider public, a Vagrantfile can also directly create one or more Vagrant machines, without generating any box.
Here is a simple Vagrantfile example:
Vagrant.configure("2") returns the Vagrant configuration object for the new box. In the block, we'll use the config alias to refer this object. We are going to use version 2 of Vagrant API.
vm.box is the base box that we are going to use. It is Ubuntu BionicBeaver (18.04 LTS), 64-bit version, provided by HashiCorp. The schema for box names is simple: the maintainer account in followed by the box name.
We use vm.provision to specify the name of the file that is going to be executed at the machine creation, to provision the machine. bootstrap.sh is the conventional name used in most cases.
To create new Vagrant machines from the Vagrantfile, move to the directory that contains the Vagrant project and run:
To compile the Vagrantfile into a box:
These operations can take time. To preventively check if the Vagrantfile contains syntax errors or certain types of bugs:
A provider allows Vagrant to create a Vagrant machine using a certain technology. Different providers may enable a virtual machine manager (, , ...), a container manager (), or remote cloud hosts (, ...).
Some providers are developed by third parties. supports search for boxes that support the most important third parties providers. To find out how to develop a new provider, see .
Provider options can be specified. Options affect the type of Vagrant machine that is created, like the number of virtual CPUs. Different providers support different options.
It is possible to specify multiple providers. In this case, Vagrant will try to use them in the order they appear in the Vagrantfile. It will try the first provider; if it is not available it will try the second; and so on.
Here is an example of providers usage:
In this example, we try to use VirtualBox to create a virtual machine. We specify that this machine must have 4G of RAM (1024M * 4). If VirtualBox is not available, Vagrant will try to use VMWare.
This mechanism is useful for at least a couple of reasons:
Different users may use different systems, and maybe they don't have the same virtualization technologies installed.
We can gradually move from one provider to another. For a period of time, some users will have the new virtualization technology installed, and they will use it; other users will only have the old technology installed, but they will still be able to create machines with Vagrant.
We can use different methods for provisioning. The simplest provisioner is shell, that allows one to run a Bash file to provision a machine. Other provisioners allow setting up the machines using automation software, including Ansible, Puppet, Chef and Salt.
To find out how to develop a new provisioner, see .
shell ProvisionerIn the example above, the provisioner runs boostrap.sh inside the Vagrant machine to provision it. A simple bootstrap.sh may look like the following:
To find out the steps to install MariaDB on your system of choice, see the section.
You may also want to restore a database backup in the new Vagrant machine. In this way, you can have the database needed by the application you are developing. To find out how to do it, see . The most flexible type of backup (meaning that it works between different MariaDB versions, and in some cases even between MariaDB and different DBMSs) is a .
On Linux machines, the shell provisioner uses the default shell. On Windows machines, it uses PowerShell.
If we use the shell provisioner, we need a way to upload files to the new machine when it is created. We could use the file provisioner, but it works by connecting the machine via ssh, and the default user doesn't have permissions for any directory except for the synced folders. We could change the target directory owner, or we could add the default user to a group with the necessary privileges, but these are not considered good practices.
Instead, we can just put the file we need to upload somewhere in the synced folder, and then copy it with a shell command:
Here is an example of how to provision a Vagrant machine or box by running Ansible:
With the , Ansible runs in the host system and applies a playbook in the guest system. In this example, it runs a playbook called vagrant.yml. The runs the playbook in the vagrant machine.
For more information, see in the Ansible documentation. For an introduction to Ansible for MariaDB users, see .
To provision a Vagrant machine or box by running Puppet:
In this example, Puppet Apply runs in the host system and no Puppet Server is needed. Puppet expects to find a manifests directory in the project directory. It expects it to contain default.pp, which will be used as an entry point. Note that puppet.manifests_path and puppet.manifest_file are set to their default values.
Puppet needs to be installed in the guest machine.
To use a Puppet server, the puppet_server provisioner can be used:
See the and the .
For an introduction to Puppet for MariaDB users, see .
To restore a backup into MariaDB, in most cases we need to be able to copy it from the host system to the box. We may also want to occasionally copy MariaDB logs from the box to the host system, to be able to investigate problems.
The project directory (the one that contains the Vagrantfile) by default is shared with the virtual machine and mapped to the /vagrant directory (the synced folder). It is a good practice to put there all files that should be shared with the box when it is started. Those files should normally be versioned.
The synced folder can be changed. In the above example, we could simply add one line:
The synced folder can also be disabled:
Note that multiple Vagrant machines may have synced folders that point to the same directory on the host system. This can be useful in some cases, if you prefer to test some functionalities quickly, rather that replicating production environment as faithfully as possible. For example, to test if you're able to take a backup from one machine and restore it to another, you can store the backup in a common directory.
It is often desirable for a machine to be able to communicate with "the outside". This can be done in several ways:
Private networks;
Public networks;
Exposing ports to the host.
Remember that Vagrant doesn't create machines itself; instead, it asks a provider to create and manage them. Some providers support all of these communication methods, while others may only support some of them, or even none at all. When you create a Vagrantfile that uses one of these networking features, it is implicit that this can only happen if the provider you are using supports them. Check your provider's documentation to find out which features it supports.
The default provider, VirtualBox, supports all of these communication methods, including multiple networks.
A private network is a networks that can only be accesses by machines that run on the same host. Usually this also means that the machines must run on the same provider (for example, they all must be VirtualBox virtual machines).
Some providers support multiple private networks. This means that every network has a different name and can be accessed by different machines.
The following line shows how to create or join a private network called "example", where this machine's IP is assigned by the provider via DHCP:
While this is very convenient to avoid IP conflicts, sometimes you prefer to assign some IP's manually, in this way:
As explained above, public networks are networks that can be accessed by machines that don't run on the same host with the same provider.
To let a machine join a public network:
To improve security, you may want to configure a gateway:
Vagrant allows us to map a TCP or UDP port in a guest system to a TCP or UDP port in the host system. For example, you can map a virtual machine port 3306 to the host port 12345. Then you can connect MariaDB in this way:
You are not required to map a port to a port with a different number. In the above example, if the port 3306 in your host is not in use, you are free to map the guest port 3306 to the host port 3306.
There are a couple of caveats:
You can't map a single host port to multiple guest ports. If you want to expose the port 3306 from multiple Vagrant machines, you'll have to map them to different host ports. When running many machines this can be hard to maintain.
Ports with numbers below 1024 are privileged ports. Mapping privileged ports requires root privileges.
To expose a port:
Suppose you run MariaDB and an application server in two separate Vagrant machines. It's usually best to let them communicate via a private network, because this greatly increases your security. The application server will still need to expose ports to the host, so the application can be tested with a web browser.
Suppose you have multiple environments of the same type, like the one described above. They run different applications that don't communicate with each other. In this case, if your provider supports this, you will run multiple private networks. You will need to expose the applications servers ports, mapping them to different host ports.
You may even want to implement different private networks to create an environment that reflects production complexity. Maybe in production you have of three MariaDB servers, and the application servers communicate with them via a proxy layer (ProxySQL, HAProxy, or ). So the applications can communicate with the proxies, but have no way to reach MariaDB directly. So there is a private network called "database" that can be accessed by the MariaDB servers and the proxy servers, and another private network called "application" that can be accessed by the proxy servers and the application servers. This requires that your provider supports multiple private networks.
Using public networks instead of private one will allow VMs that run on different hosts to be part of your topology. In general this is considered as an insecure practice, so you should probably ask yourself if you really need to do this.
The repository is an example of a Vagrantfile that creates a box containing MariaDB and some useful tools for developers.
Further information can be found in Vagrant documentation.
.
.
.
.
See also .
Content initially contributed by .
This page is licensed: CC BY-SA / Gnu FDL
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/bionic64"
config.vm.provider "virtualbox"
config.vm.provision :shell, path: "bootstrap.sh"
endVagrant is a tool to create and manage development machines (Vagrant boxes). They are usually virtual machines on the localhost system, but they could also be Docker containers or remote machines. Vagrant is open source software maintained by HashiCorp and released under the MIT license.
Vagrant benefits include simplicity, and a system to create test boxes that is mostly independent from the technology used.
For information about installing Vagrant, see in Vagrant documentation.
In this page we discuss basic Vagrant concepts.
Following are the core Vagrant concepts:
vagrant upvagrant packagevagrant validateVagrant.configure("2") do |config|
config.vm.box = "hashicorp/bionic64"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", 1024 * 4]
end
config.vm.provider "vmware_fusion"
end#!/bin/bash
apt-get update
apt-get install -ycp ./files/my.cnf /etc/mysql/conf.d/Vagrant.configure("2") do |config|
...
config.vm.provision "ansible" do |ansible|
ansible.playbook = "vagrant.yml"
end
endVagrant.configure("2") do |config|
...
config.vm.provision "puppet" do |puppet|
puppet.manifests_path = "manifests"
puppet.manifest_file = "default.pp"
end
endVagrant.configure("2") do |config|
...
config.vm.provision "puppet_server" do |puppet|
puppet.puppet_server = "puppet.example.com"
end
endconfig.vm.synced_folder "/host/path", "/guest/path"config.vm.synced_folder '.', '/vagrant', disabled: trueconfig.vm.network 'private_network', name: 'example', type: 'dhcp'config.vm.network 'private_network', name: 'example', ip: '111.222.111.222'# use provider DHCP:
config.vm.network "public_network", use_dhcp_assigned_default_route: true
# assign ip manually:
config.vm.network "public_network", ip: "111.222.111.222"config.vm.provision "shell", run: "always", inline: "route add default gw 111.222.111.222"mariadb -hlocalhost -P12345 -u<user> -p<password>config.vm.network 'forwarded_port', guest: 3306, host: 3306Vagrant Machine
The final environment created from a box. It can be a virtual machine, a container, or a remote cloud server.
Box
A reusable package used to create Vagrant machines. It can be a base OS image downloaded from Vagrant Cloud or a custom-built template.
Provider
The underlying virtualization technology that runs the machine (e.g., VirtualBox, VMware, Hyper-V, Docker).
Provisioner
A tool or script (e.g., Shell, Ansible, Puppet) that automatically installs and configures software on the machine after it is created.
The above concepts are probably easier to understand with an example.
We can use an Ubuntu box as a base to build a Vagrant machine with MariaDB. So we write a Vagrantfile for this purpose. In the Vagrantfile we specify VirtualBox as a provider. And we use the Ansible provisioner to install and configure MariaDB. Once we finish this Vagrantfile, we can run a Vagrant command to start a Vagrant machine, which is actually a VirtualBox VM running MariaDB on Ubuntu.
The following diagram should make the example clear:
A Vagrantfile is a file that describes how to create one or more Vagrant machines. Vagrantfiles use the Ruby language, as well as objects provided by Vagrant itself.
A Vagrantfile is often based on a box, which is usually an operating system in which we are going to install our software. For example, one can create a MariaDB Vagrantfile based on the ubuntu/trusty64 box. A Vagrantfile can describe a box with a single server, like MariaDB, but it can also contain a whole environment, like LAMP. For most practical use cases, having the whole environment in a single box is more convenient.
Boxes can be searched in Vagrant Cloud. Most of their Vagrantfiles are available on GitHub. Searches can be made, among other things, by keyword to find a specific technology, and by provider.
A provider adds support for creating a specific type of machines. Vagrant comes with several providers, for example:
VirtualBox allows one to create virtual machines with VirtualBox.
Microsoft-Hyper-V allows one to create virtual machines with Microsoft Hyper-V.
Docker allows one to create Docker containers. On non-Linux systems, Vagrant will create a VM to run Docker.
Alternative providers are maintained by third parties or sold by HashiCorp. They allow one to create different types of machines, for example using VMWare.
Some examples of useful providers, recognized by the community:
If you need to create machines with different technologies, or deploy them to unsupported cloud platforms, you can develop a custom provider in Ruby language. To find out how, see Plugin Development: Providers in Vagrant documentation. The Vagrant AWS Provider was initially written as an example provider.
A provisioner is a technology used to deploy software to the newly created machines.
The simplest provisioner is shell, which runs a shell file inside the Vagrant machine. powershell is also available.
Other providers use automation software to provision the machine. There are provisioners that allow one to use Ansible, Puppet, Chef or Salt. Where relevant, there are different provisioners allowing the use of these technologies in a distributed way (for example, using Puppet apply) or in a centralized way (for example, using a Puppet server).
It is interesting to note that there is both a Docker provider and a Docker provisioner. This means that a Vagrant machine can be a Docker container, thanks to the docker provisioner. Or it could be any virtualisation technology with Docker running in it, thanks to the docker provisioner. In this case, Docker pulls images and starts containers to run the software that should be running in the Vagrant machine.
If you need to use an unsupported provisioning method, you can develop a custom provisioner in Ruby language. See Plugin Development: Provisioners in Vagrant documentation.
It is possible to install a plugin with this command:
A Vagrantfile can require that a plugin is installed in this way:
A plugin can be a Vagrant plugin or a Ruby gem installable from rubygems.org. It is possible to install a plugin that only exists locally by specifying its path.
HashiCorp published an article that describes its plans for Vagrant 3.0.
Vagrant will switch to a client-server architecture. Most of the logic will be stored in the server, while the development machines will run a thin client that communicates with the server. It will be possible to store the configuration in a central database.
Another notable change is that Vagrant is switching from Ruby to Go. For some time, it will still be possible to use Vagrantfiles and plugins written in Ruby. However, in the future Vagrantfiles and plugins should be written in one of the languages that support gRPC (not necessarily Go). Vagrantfiles can also be written in HCL, HashiCorp Configuration Language.
This is a list of the most common Vagrant commands. For a complete list, see Command-Line Interface in Vagrant documentation.
To list the available machines:
To start a machine from a box:
To connect to a machine:
To see all machines status and their id:
To destroy a machine:
Here are some valuable websites and pages for Vagrant users.
Content initially contributed by Vettabase Ltd.
This page is licensed: CC BY-SA / Gnu FDL
Databases typically contain information to which access should be restricted. For this reason, it's worth discussing some security concerns that Vagrant users should be aware of.
By default, Vagrant machines are only accessible from the localhost. SSH access uses randomly generated key pairs, and therefore it is secure.
The password for root and vagrant is "vagrant" by default. Consider changing it.
By default, the project folder in the host system is shared with the machine, which sees it as /vagrant. This means that whoever has access to the project folder also has read and write access to the synced folder. If this is a problem, make sure to properly restrict the access to the synced folder.
If we need to exchange files between the host system and the Vagrant machine, it is not advisable to disable the synced folder. This is because the only alternative is to use the file provider, which works by copying files to the machine via ssh. The problem is that the default ssh user does not have permissions to write to any directory by default, and changing this would be less secure than using a synced folder.
When a machine is provisioned, it should read the needed files from the synced folder or copy them to other places. Files in the synced folder should not be accessed by the Vagrant machine during its normal activities. For example, it is fine to load a dump from the synced folder during provisioning; and it is fine to copy configuration files from the synced folder to directories in /etc during provisioning. But it is a bad practice to let MariaDB use table files located in the synced folder.
Note that security bugs are not reported as normal bugs. Information about security bugs are not public. See for details.
Content initially contributed by .
This page is licensed: CC BY-SA / Gnu FDL
vagrant plugin install <plugin_name>require 'plugin_name'vagrant box listcd /box/directory
vagrant upvagrant sshvagrant global-statusvagrant destroy <id>