PHP development on Win10 through WSL2, Laravel Valet and Tighten Takeout
Tags: development, wsl2, php, devops
Published: 2020-11-27 09:04:23

I've been doing PHP development professionally for pretty much the last 10 years. I've also been a Windows user pretty much forever. Put together that has not been the greatest experience as when it comes to running a local webserver the experience has always not been excellent. Nuances like Windows line endings always cause issues. I've tried switching over to Linux but the GUI has always felt like it has lacked. I've never been a fan of macOS but the tools they have like Laravel Valet have made me jealous a fair few times. Thankfully Win10 has WSL2 nowadays which is a game-changer.

This guide explains steps how to set up a PHP environment for local development using Laravel Valet Linux and Tighten Takeout tools on Docker.

## WSL2
First of all you will need to set up WSL (Windows Subsystem for Linux) on your machine if you haven't done this already. The official guide for doing this can be found [here](https://docs.microsoft.com/en-us/windows/wsl/install-win10)

Whilst the linux distro used is purely personal preference I've used Ubuntu as it is very widely used and always has good documentation / search results for any issues on web.

Whilst most of the environment will be set up on WSL with Laravel Valet, it does not automatically set up database engine to allow users selecting their own preference. For this reason we will be using [Tighten Takout](https://github.com/tighten/takeout) to set up any necessary engines like database / cache / search etc.

## Docker
First of all if you don't have docker installed - it is a [simple install process](https://www.docker.com/get-started) to get started. After you set up docker you want to check and ensure docker uses WSL containers - guide to verify and adjust can be found [here](https://docs.docker.com/docker-for-windows/wsl/)

## Setting up environment
Now that we have pre-requisites installed we can set up the environment. 

#### Update package lists
```
sudo apt-get update
```

#### Install php, its modules and unzip on system
```
sudo apt install unzip php php-cli php-fpm php-json php-intl php-common php-mysql php-zip php-gd php-mbstring php-curl php-xml php-pear php-bcmath -yqq
```
If you need any other module you can install it via `sudo apt install php-module` command. If you require a specific php version or php module version you can use `php7.4 php7.4-zip` format.

#### Install composer
```
curl -sS https://getcomposer.org/installer | php \
            && sudo mv composer.phar /usr/local/bin/ \
            && sudo ln -s /usr/local/bin/composer.phar /usr/local/bin/composer
```

#### Prepare for Laravel Valet
We have few additional dependencies to install:
```
sudo apt-get install network-manager libnss3-tools jq xsel
```
Also edit `/etc/wsl.conf` to add following lines. This is nescessary as WSL normally does recreate `/etc/resolv.conf` file when you start it. Adding this line in wsl config will prevent it from re-writing file *as long as the file is not a symlink*
```
[network]
generateResolvConf=false
```

#### Install Laravel Valet Linux & Tighten Takeout
```
composer global require cpriego/valet-linux tightenco/takeout
```
We also want to make sure we can use commands like `valet` or `takeout` without specifying path so we want to make sure that the path to these binaries is registered as part of the system PATH variable. This can be added by updating the `~/.bashrc` file by adding the path to global composer bin path.
```
export PATH=~/.config/composer/vendor/bin:$PATH
```
Once file has been updated you can reload the bash shell for the new path to be loaded by running `source ~/.bashrc`

Now we can install Valet.
```
valet install
```
This will set up Laravel Valet on device. Valet does change the `/etc/resolv.conf` file to a symlink which is going to be reset after WSL gets rebooted even with our wsl.conf file edit if we leave it as a symlink. Due to this it is recommended to copy the valet resolv config over.
```
sudo unlink /etc/resolv.conf
sudo cp /opt/valet-linux/valet-dns /etc/resolv.conf
```
An issue I've also noticed is that valet linux does not include default DNS config which can cause issues with accessing anything on web from the wsl (including composer installs, pinging and other actions). Due to this it is recommended to add `/opt/valet-linux/dns-servers` file and have following in it
```
nameserver 1.1.1.1
```
`1.1.1.1` is Cloudflare DNS, if you don't want to use it you can use `8.8.8.8` for Google DNS or any other alternative.

## Starting Services

#### valet
Now everything should be set up and you should be able to get things started with `valet start` command. In personal experience I've noticed that php-fpm on ubuntu tends not to start with valet linux and I'm yet to figure out why, but this can be bypassed by running `sudo service php7.4-fpm start` (or your php version) after starting valet.

Valet also requires you to park a directory to identify where to look for sites. Run `valet park` in directory where you are locating your projects.

#### Takeout
Running `takout enable` should bring up a menu allowing to enable specific service - mysql, postgres, redis, elasticsearch etc. Enabling these will set up a docker container that will be used to manage the service. Services already set up can be seen running `takeout list` and started/stopped running `takeout start CONTAINER_ID` and `takeout stop CONTAINER_ID`

__NB__ Services are available on 127.0.0.1 not localhost so make sure you update your environment variables to reflect this.

## Additionals

#### Node.js
Node.js won't be installed by default, you can run install for this. I've also included npm, however yarn is also a popular package manager that can be used as an alternative to npm.
```
sudo apt install nodejs npm
```
I would recommend installing [NVM (node version manager)](https://github.com/nvm-sh/nvm#install--update-script) as it allows easily switching between node versions which might come in handy if you need to support some legacy projects. It also could make it easier to upgrade when new version is released

#### Request routing / DNS
The last thing to  get sites working is the requirement to add dns entries for your local pc to route the site to 127.0.0.1. This normally is done in `C:/Windows/System32/drivers/etc/hosts` file where you specify the domain name and its IP address
```
127.0.0.1 mysite.test
```

This is a relatively large set-back when you compare it to the ease of valet on linux/macos where wildcard DNS routing is possible as it requires managing each site individually.
There is however a potential workaround if you are using Chrome as your development web brower. As per [IETF specification](https://tools.ietf.org/html/rfc2606) `*.localhost` TLD is outlined to be a loopback domain and it should route back to 127.0.0.1. This is however for web browser companies to implement and there are mixed results. From my own testing I've found out that Chrome does support this functionality whilst other browsers (Firefox / Edge) do not do  this. So if you primarily work on this browser you can switch valet domain to localhost and it will remove necessity to manually add dns entries.
```
valet domain localhost
```