Getting Homestead to play nice with Hyper-V
Tags: php, vagrant, hyperv, windows
Published: 2019-02-02 08:16:45

Homestead is a fantastic tool for local development. It's basically a preconfigured Ubuntu Vagrant box that already has everything you'd want for PHP development and more.
The most straightforward way to use it is to install Virtualbox. So if you don't need Hyper-V you can safely stop reading this post and be on your merry way.

However if you're like me, you may need it to run on Hyper-V instead of Virtualbox, because you can't have both running at the same time on Windows. So if you want to use Docker (which uses Hyper-V) or a Hyper-V machine for something else, it means you'll have to reboot your machine each time you want to use one or the other, which is really not practical.
The good news is that Homestead's support for Hyper-V has made a lot of progress in the past couple of years, but there are still a lot of gotchas that I'll try and go through here.

This was going to be a complete guide, but I figured that the [official docs](https://laravel.com/docs/5.7/homestead#configuring-homestead) should be enough to get you started, so I'll just cover the specific issues I encountered when running Homestead with hyper-V.


# Use everything as administrator
The first annoying thing is that for Homestead (and the underlying Vagrant) to be able to share your work folders with SMB, you need to use them as an administrator. Which in turn means that your IDE needs to be run as administrator to communicate with Homestead.

So you'll probably want to create shortcuts to start Powershell (or CMD) and your IDE as administrator and get into the habit of using those.


# Set up the network
The main issue with this setup is that Vagrant is not (yet ?) able to manage Hyper-V's virtual switches, so you'll have to create one yourself or you won't be able to access both the internet and your own host machine from homestead.
To do so, open hyper-V manager, select _Virtual Switch Manager_ in the _Actions_ pane, click on _New virtual Network Switch_, and click on the create button. Give it a useful name (like "External Switch"), make sure _External_ network is checked and the physical Ethernet controller that's connected to your network and the internet is selected, then click OK.
![](https://thepracticaldev.s3.amazonaws.com/i/jnt0k7gara8solwtge83.png)

The first time Homestead starts, it should ask you which network to use, and you'll tell it to use this External Switch.
![](https://thepracticaldev.s3.amazonaws.com/i/o9aa7p1nqico3sr4qoc5.png)


# Automatically manage the host file
Through the [vagrant-hostmanager](https://github.com/devopsgroup-io/vagrant-hostmanager) plugin, homestead is able to automatically update your _hosts_ file to make the domains you declare in Homestead.yaml accessible.
This is particularly useful with Hyper-V because the IP of your machine might change whenever you restart it, so without this plugin you'd need to go and edit your _hosts_ file manually each time. Assuming Vagrant is installed you can install the plugin by running `vagrant plugin install vagrant-hostmanager` from anywhere in the command line.

From now on, each time your homestead starts your _hosts_ file will be automagically updated so that all the domains declared in the Homestead.yaml file will point to your virtual machine. There are two things to keep in mind :
1. The plugin only triggers on `vagrant up`, not on `vagrant reload`, so when you restart your homestead machine you should always run `vagrant halt` then `vagrant up` to make sure your hosts are kept up to date
2. This only works because in this scenario we have to run vagrant as administrator so it has write access to the hosts file.


# Allow Homestead to access your work folders
Homestead uses SMB to share files between your machine and the virtual machine when using Hyper-V. By default, it will ask for your login and password each time it starts up, which quickly becomes annoying.
Fortunately, you can now specify credentials to use for SMB shares directly in the Homestead.yaml file, but I wouldn't recommend putting your own credentials in plain sight in a file on your computer. What I found to be an acceptable solution was to :
1. Create a new windows user names "vagrant" with the password "vagrant".
2. Share my code folder (and every folder declared in the Homestead.yaml file) with this user and give it read/write permissions
3. Use the "vagrant" user credentials for each folder in the Homestead.yaml file like so :
```yaml
folders:
    - map: ~/code
      to: /home/vagrant/code
      smb_username: vagrant
      smb_password: vagrant

```


# Get x-debug to work from the command-line
X-debug should work out of the box to debug web pages, but it won't work from the command line with the provided `xphp` command. The reason is that this command assumes that your host machine's IP from the VM is _192.168.10.1_, which is indeed the case with virtualbox, but not at all when running Hyper-v.
I found a solution to that, which is to modify the xphp alias so that it will find the last SSH connection to the VM, and use this IP as the remote_host for xdebug. It's probably not 100% reliable, but in most cases the IP should be your own since you'll be the only one to connect to the VM through ssh.
So what you'll need to do is edit the _aliases_ file at the root of the Homestead directory, and replace the xphp() function with this one :
```bash
function xphp() {
    (php -m | grep -q xdebug)
    if [[ $? -eq 0 ]]
    then
        XDEBUG_ENABLED=true
    else
        XDEBUG_ENABLED=false
    fi

    if ! $XDEBUG_ENABLED; then xon; fi

    #Find the IP of the latest ssh connection :
    HOST_IP=$(last --limit=1 | grep -oP '\d+(\.\d+){3}')

    php \
        -dxdebug.remote_host=${HOST_IP} \
        -dxdebug.remote_autostart=1 \
        "$@"

    if ! $XDEBUG_ENABLED; then xoff; fi
}
```





That's it for today, I hope this can be of help to someone !