Vagrant and Ansible on Windows hosts

Vagrant runs nicely on Windows. Ansible does not. It can, at a pinch, with Cygwin etc – but that setup doesn’t work with the Vagrant Ansible provisioner.

There is a solution: use Vagrant’s shell provisioner to fire up Ansible on the guest, something like this. It adds a bit of overhead having to install another copy of Ansible on every guest, but this approach does work unchanged on both Linux and Windows hosts. We can still keep the config scripts centralized on the host, and access them via VirtualBox shared folders. Or can we?

TL;DR:

  • All the VirtualBox shared folders options have issues when the host is Windows and the guest is Linux.
  • The safest workaround is to copy your whole config scripts directory to a local directory on the guest, and run Ansible entirely on guest.

If you do keep your config scripts on the host, you’ll eventually run into the dreaded “atomic move” issue. That is, Unix file systems support an atomic move operation, and Windows file systems do not. See the archetypal gedit vs virtualbox pass-the-bug fest for a typical manifestation.

When using vboxfs synced folders, host file system semantics remain in place. That means even though you’re running Ansible on the Linux guest, your Windows host is still going to get you. You can provoke this just by using the Ansible template module, even when only the source file is on the host filesystem. To be defensive, you’d have to assume any command or program on the Linux side could have problems with vboxfs folders until proven otherwise. Oracle appears to be in no hurry to fix this or even admit that it needs fixing. Do you really want to spend your life tripping over all of the problem cases?

Ok, no problem, vagrant also supports rsync and smb for synced folders. Rsync would have to work, because the files end up on the guest where Windows can’t get at us anymore, and SMB must be easy because it’s Windows’ native protocol, right? Actually, not so simple.

Rsync requires an rsync.exe on the path of the host. You can get that by installing Cygwin. That might be acceptable for your own dev machine, but if you are using Vagrant to distribute demo environments, expecting all users to turn their machines into a bizarre Unix/Windows hybrid is probably not realistic. And there’s no installer-free Cygwin anymore (or any other Windows rsync port, for that matter), so the rsync route ends up being just too invasive.

SMB must just work out of the box, though, right? Unless you’re on Windows 8, wrong. Vagrant’s smb support needs Powershell 3.0. Powershell 3.0 needs .Net 4.0. On Windows 7 that’s two more installers, and even then it won’t work unless your version of Vagrant is very recent.

So what’s the solution? Obviously, get a Mac or a dedicated Linux dev box. But what about those of us working at home on a personal project, with only one machine that has to be a Windows machine because all our users run Windows and because dogfooding, and because running Windows as a guest isn’t great for anything graphics intensive? In that case – get *everything* over onto the guest as quickly and simply as possible, and then stay entirely on the guest. Vboxfs works fine for simple copying, or if your config is in a public repo maybe just pull it down straight onto the guest.

2 thoughts on “Vagrant and Ansible on Windows hosts

  1. Thanks for the post. It was helpful in getting me started with my setup. Unfortunately I’m on a windows host and creating VMs inside of another VM seemed silly. I was able to create a working version of the process: vagrant-bootstrap.
    Because of your comments I also made an option to share nothing between the host and VM so I hopefully never experience the problems you pointed out. Thanks!

  2. Paul, glad I could help. TBH, I didn’t think it was possible to create VMs within VMs, otherwise I would have just run Vagrant inside a Linux VM in the first place.

    If I understand it correctly, your “share nothing” approach is using github as the shared file system. That’s a nice twist – go the cloud!

    You’re correct that the file system problems arise from editing a file on the Windows side, due to Windows’ lack of an atomic move operation. The tricky part is that some operations that don’t look like a move actually boil down to an atomic move at some point. Obviously renaming a file is problematic, and unfortunately Ansible often works by creating temp file, then renaming/moving it when finished.

    However, just plain copying from Windows host to Linux guest works fine, so my equivalent of your bootstrap.sh has a line like this:

    cp -rf -v /vagrant/provisioning ~/provisioning

    which is functionally equivalent to your bootstrap.yml – it just serves to get the stuff onto the guest, and then everything runs locally after that.

Leave a Reply

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