Vagrant for DevOps: Vagrantfile

Vagrantfile is used to deploy the whole infrastructure from scratch on any machine running Vagrant.
Vagrantfile describes environment configuration – stuff like VMs, shares, networking, etc.
Vagrantfile should be stored in VCS, such as Git – we’ll be able to share environment configurations within the team and switch between different environment versions.

Vagrantfile should be stored in the project directory, but if it’s not found there, vagrant will search for it in all dirs from project to / :

Screen Shot 2016-05-25 at 17.02.05
And for security reasons you might want to store Vagrantfiles in a private dir, in this case use environment variable VAGRANT_CWD to specify a path.
If you have a few Vagrantfiles, vagrant will automatically merge them, but it’s not really common practice.

We can generate simple vagrant file with vagrant init command, but we’ll construct our own configuration which would be a bit more complex.
Vagrantfiles are ruby-based, so it’s really easy to have a deal with syntax.

You can use my simple comments in Vagrantfiles to understand basic things, but I recommend you to visit vagrant docks page for more details.

Here’s an example for a single Linux machine:

cpu = "1"
ram = "512"

Vagrant.configure("2") do |config|
    
    # Box to create VM from
    config.vm.box = "bento/ubuntu-16.04"

    # Box version to use (latest)
    config.vm.box_version = ">= 0"

    # Check box update during vagrant up
    config.vm.box_check_update = true

    # Check checksum after box download
    config.vm.box_download_checksum = true

    # Set checksum type
    config.vm.box_download_checksum_type = "sha1"

    # Check SSL certificate before box download
    config.vm.box_download_insecure = true

    # SSH for linux and winrm for Windows
    config.vm.communicator = "ssh"

    # SSH username 
    config.ssh.username = "vagrant"

    # Replace default insecure SSH key
    config.ssh.insert_key = false

    # Set VM network type
#    config.vm.network "private_network", type: "dhcp"
    
    # Set VM hostname
    config.vm.hostname = "svr1"

    # Set port forwarding 
#    config.vm.network "forwarded_port", guest: "80", host: "8080", host_ip: "127.0.0.1", protocol: "tcp", auto_correct: true
#    config.vm.network "forwarded_port", guest: "443", host: "8090", host_ip: "127.0.0.1", protocol: "tcp", auto_correct: true

    # Set VM CPU & RAM limits
    config.vm.provider "virtualbox" do |v|
        v.customize ["modifyvm", :id, "--cpuexecutioncap", "95"]
        v.memory = ram
        v.cpus = cpu
    end

    config.vm.provider "parallels" do |v|
        v.memory = ram
        v.cpus = cpu
    end

    config.vm.provider "vmware_fusion" do |v|
        v.memory = ram
        v.cpus = cpu
    end

    # Set shared folders: host > VM
    config.vm.synced_folder "~/", "/host"

    # Execute external script
    config.vm.provision "shell", path: "install-updates.sh"

    # Execute external script
    config.vm.provision "shell", path: "install-zsh.sh"

    # Execute external script
    config.vm.provision "shell", path: "install-gitversion.sh"

    # Copy file from host to VM  
#    config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig"

    # Seconds to wait during gracefull halt
    config.vm.graceful_halt_timeout = "120"

    # Message after vagrant up
    config.vm.post_up_message = "Thanks bento team for the source image!"

end

 

And single Windows machine:

Vagrant.configure("2") do |config|

    # Box to create VM from
    config.vm.box = "opentable/win-2012r2-standard-amd64-nocm"

    # Link by which box can be found, f.e. for URL check
    config.vm.box_url = "https://atlas.hashicorp.com/opentable/boxes/win-2012r2-standard-amd64-nocm"

    # Box version to use (latest)
    config.vm.box_version = ">= 0"

    # Check box update during vagrant up
    config.vm.box_check_update = true

    # Check checksum after box download
    config.vm.box_download_checksum = true

    # Set checksum type
    config.vm.box_download_checksum_type = "sha1"

    # Check SSL certificate before box download
    config.vm.box_download_insecure = false

    # Set VM guest OS type
    config.vm.guest = :windows
    
    # Communicator type to use with guest VM
    config.vm.communicator = "winrm"
    
    # Username to use WinRM
    config.winrm.username = "vagrant"
    
    # Password to use WinRM
    config.winrm.password = "vagrant"

    # Set VM network type
    config.vm.network "private_network", type: "dhcp"

    # Set VM hostname
    config.vm.hostname = "svr1"

    # Set port forwarding 
    config.vm.network "forwarded_port", guest: "3389", host: "3389", host_ip: "127.0.0.1", protocol: "tcp", auto_correct: true
    config.vm.network "forwarded_port", guest: "5985", host: "5985", host_ip: "127.0.0.1", protocol: "tcp", auto_correct: true
    config.vm.network "forwarded_port", guest: "80", host: "8080", host_ip: "127.0.0.1", protocol: "tcp", auto_correct: true
    config.vm.network "forwarded_port", guest: "443", host: "8090", host_ip: "127.0.0.1", protocol: "tcp", auto_correct: true

    # Set VM CPU & RAM limits
    config.vm.provider "virtualbox" do |v|
        v.customize ["modifyvm", :id, "--cpuexecutioncap", "75"]
        v.memory = "2048"
        v.cpus = "2"
    end

    # Execute external script
    config.vm.provision "shell", path: "script.ps1" 

    # Copy file from host to VM  
    config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig"

    # Seconds to wait during gracefull halt
    config.windows.halt_timeout = "120"

    # Message after vagrant up
    config.vm.post_up_message = "some instructions can be placed here"

end
new-item -type file -path "C:\" -name "testFile.txt"

 

A bit more complex example with two Linux VMs:

cpu = "1"
ram = "512"

Vagrant.configure("2") do |config|
    
    # Box to create VM from
    config.vm.box = "bento/centos-7.4"

    # Box version to use (latest)
    config.vm.box_version = ">= 0"

    # Check box update during vagrant up
    config.vm.box_check_update = true

    # Check checksum after box download
    config.vm.box_download_checksum = true

    # Set checksum type
    config.vm.box_download_checksum_type = "sha1"

    # Check SSL certificate before box download
    config.vm.box_download_insecure = true

    # SSH for linux and winrm for Windows
    config.vm.communicator = "ssh"

    # SSH username 
    config.ssh.username = "vagrant"

    # Replace default insecure SSH key
    config.ssh.insert_key = false

    # Setup first server
    config.vm.define "svr1" do |svr1|

        # Set VM hostname
        svr1.vm.hostname = "svr1"

        # Set port forwarding 
        svr1.vm.network "forwarded_port", guest: "80", host: "8080", host_ip: "127.0.0.1", protocol: "tcp", auto_correct: true

        # Set VM CPU & RAM limits
        config.vm.provider "virtualbox" do |v|
            v.customize ["modifyvm", :id, "--cpuexecutioncap", "95"]
            v.memory = ram
            v.cpus = cpu
        end

        config.vm.provider "parallels" do |v|
            v.memory = ram
            v.cpus = cpu
        end

        config.vm.provider "vmware_fusion" do |v|
            v.memory = ram
            v.cpus = cpu
        end

        # Set shared folders: host > VM
        svr1.vm.synced_folder "~/", "/host"

        # Execute external script
        svr1.vm.provision "shell", path: "install-zsh.sh"

        # Seconds to wait during gracefull halt
        svr1.vm.graceful_halt_timeout = "120"
    end

    # Setup first server
    config.vm.define "svr2" do |svr2|

        # Set VM hostname
        svr2.vm.hostname = "svr2"

        # Set port forwarding 
        svr2.vm.network "forwarded_port", guest: "80", host: "8090", host_ip: "127.0.0.1", protocol: "tcp", auto_correct: true

        # Set VM CPU & RAM limits
        config.vm.provider "virtualbox" do |v|
            v.customize ["modifyvm", :id, "--cpuexecutioncap", "95"]
            v.memory = ram
            v.cpus = cpu
        end

        config.vm.provider "parallels" do |v|
            v.memory = ram
            v.cpus = cpu
        end

        config.vm.provider "vmware_fusion" do |v|
            v.memory = ram
            v.cpus = cpu
        end

        # Set shared folders: host > VM
        svr2.vm.synced_folder "~/", "/host"

        # Execute external script
        svr2.vm.provision "shell", path: "install-zsh.sh"

        # Seconds to wait during gracefull halt
        svr2.vm.graceful_halt_timeout = "120"
    end

end

 

Vagrant for DevOps table of contents