This won’t be of interest to most of you, but I’m putting it here so that someone can maybe google for it on Bing, and find the answers that other websites, forums and StackOverflow answers don’t seem to have.
We assume you’re starting with a Windows machine that either has never had WSL installed, or else has had it thoroughly purged. This latter effect is hard to manage, but essential if you want to get this right.
Windows Terminal
First, if you’re still on Windows 10, install Windows Terminal. Life is too short to put up with inferior terminals.
Open Microsoft Store.
Search for Windows Terminal by Microsoft Corporation.
Install it.
Pin to Start and/or Taskbar.
Initially it will default to opening PowerShell. That’s fine; we’ll change that later.
Ubuntu in WSL
Now install the latest Ubuntu in WSL:
wsl --install -d Ubuntu
If you get a kernel error, try this:
wsl --update
Eventually it will want to restart, and then it will ask you for a user name and password. I suggest a password like “a”, since this is never going to be exposed to the internet so who needs security?
Windows Terminal will now contain an entry for Ubuntu. You can use that from now on.
PHP, Apache and MySQL
Now we build a development environment:
sudo apt update sudo apt install php8.3 apache2 mysql-server mysql-client sudo a2enmod rewrite sudo service apache2 start sudo apt install php8.3-curl php8.3-xml php8.3-yaml php8.3-mysql php8.3-imagick
You should be able to go to http://localhost and get the Apache2 Default Page.
Now let’s test PHP:
sudo su - rm /var/www/html/index.html echo '<?php phpinfo();' > /var/www/html/index.php
Look at http://localhost again and this time it will show the PHP info page.
Useful scripts
Add a couple of useful scripts:
/usr/local/bin/assertownership: (substitute xxxxx for your personal non-root sudo-enabled user)
Use this any time you’ve uploaded changes or used composer, because file permissions might get messed up. This changes everything to be owned by www-data, in the group that your login is part of, and readable and writeable appropriately.
#!/bin/bash
cd /var/www
sudo chown -R www-data:xxxxx * .[a-z]* 2>/dev/null
sudo chmod -R ug=rwX,o=rX * .[a-z]* 2>/dev/null
ls -alF
/usr/local/bin/kick:
This lets you restart Apache and MySQL any time you fiddle with the settings.
#!/bin/bash sudo echo Restarting Apache... sudo service apache2 restart echo Restarting MySQL... sudo service mysql restart echo Done.
Composer
Install Composer:
curl -sS https://getcomposer.org/installer -o composer-setup.php php composer-setup.php sudo mv composer.phar /usr/local/bin/composer
Pause…
At this point, you need to get a PHP project running. You probably want to install git or your version control system of choice, and maybe other packages apart from the php8.3-xxx modules I listed above. Eventually, when it’s all working (which is an exercise left for the reader) you will want to debug. And here I assume you’re using PHPStorm, because why wouldn’t you? Comments are welcome if you have similar tested, error-resistent instructions for other editors.
xdebug
Go to https://xdebug.org/wizard, paste in the contents of a phpinfo() page, and follow the instructions. This will create a hand-compiled version of xdebug that isn’t years old like the official Ubuntu package.
Open PowerShell, run ipconfig, and get the Ethernet adapter vEthernet (WSL) IPv4 address (in this example, 172.21.48.1).
Create /etc/php/8.3/mods-available/xdebug.ini with contents as follows:
zend_extension = xdebug xdebug.mode = debug,develop xdebug.discover_client_host = false xdebug.client_host = 172.21.48.1 xdebug.client_port = 9003 xdebug.start_with_request=trigger xdebug.idekey=PHPSTORM
Activate this with
sudo phpenmod xdebug
Set up configuration in PhpStorm. This assumes you have a project called example which lives in /var/www/example and can already be run successfully using http://example.localhost. See above about “exercise for the reader”!
Open a PHP project
Select “Edit Configurations” from the debug dropdown
Add > PHP Web Page
Server > …
Add > Name = Localhost > Host = example.localhost
Check “Use path mappings”
Against \\wsl$\Ubuntu\var\www\example put /var/www/example
OK, OK
That should work. If not, you have days of tedious debugging ahead of you as you try to figure it out. Good luck with that.