/WSL, nginx, PHP, Apache

Configure local website on WSL2 with PHP and nginx

I needed to make some changes to an old PHP (Wordpress) site and wanted to quickly run it locally. I don't actively use PHP anymore therefore I didn't want to install XAMPP or anything big like this. The obvious idea was to use WSL to run the site. First I tried with Apache, but for some reason, despite everything being set up correctly, the site was just not loading in the Windows browser. When I accessed it within WSL it returned the correct HTML. I spent a good part of the day trying to figure it out with no success. Then I thought, screw Apache, let me try nginx and surprise, surprise it all worked just fine without a single issue.
Below are all the steps I made to set up a simple dev site on WSL2 with PHP and nginx.

Configuration

  1. Install PHP with some common dependencies. I chose ones I needed for Wordpress. Feel free to remove or add modules as you see fit. Just make sure you install php7.4-fpm.

    sudo apt install php7.4 php7.4-cli php7.4-mysql php7.4-curl php7.4-mcrypt php7.4-json php7.4-mbstring php7.4-fpm
    
  2. Install nginx and run the service.

    sudo apt install nginx
    sudo service nginx start
    
  3. Check the path for PHP socket and make a note of it.

    sudo grep "listen =" /etc/php/7.4/fpm/pool.d/www.conf
    > listen = /run/php/php7.4-fpm.sock
    
  4. Make sure PHP is running.

    sudo service php7.4-fpm status
     * php-fpm7.4 is running
    
    # if it's "not running", start it with below command
    sudo service php7.4-fpm start
    
  5. Add nginx config for your local website by creating a config file. The example.local is just the domain I used, you can change it to whatever your domain will be. Just make sure that anywhere I used example.local you change it to your domain.

    sudo vim /etc/nginx/sites-available/example.local.conf
    

    Your config file should look similar to below.

    server {
        listen 80;
    
        access_log /var/log/nginx/example.local-access.log;
        error_log /var/log/nginx/example.local-error.log;
    
        root /mnt/c/Users/kosa/workspace/example-blog;
        index index.php index.html index.htm;
        server_name example.local www.example.local;
    
        location = /favicon.ico { access_log off; log_not_found off; }
        location = /robots.txt  { access_log off; log_not_found off; }
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    
        location ~ \.php$ {
            try_files      $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass   unix:/var/run/php/php7.4-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    
        location ~ /\.ht {
            deny all;
        }
    }
    

    Please note the root directive points to a path on a Windows drive. Essentially it's c:\Users\kosa\workspace\example-blog. Also "kosa" in there is just my username, you should change it to yours.
    Check the value of fastcgi_pass directive and make sure it is the same as the path you got in point 3 above.

  6. Symlink your newly created config file to enable your new site on nginx.

    sudo ln -s /etc/nginx/sites-available/example.local.conf /etc/nginx/sites-enabled/
    
    # test new nginx config
    sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
    # if all is good, restart nginx
    sudo service nginx restart
    
  7. Last step of the whole process is to add an entry to your Windows hosts file. We're talking about the Windows hosts file located in c:\Windows\System32\drivers\etc\. You don't need to touch the internal WSL hosts file in /etc/hosts.
    Add the below and we're done.

    127.0.0.1        example.local
    

Now, open your favourite browser on Windows and go to http://example.local/ You should see your website load up.

Troubleshooting

If for some reason the above process did not work for you, see if you get the correct response header from your site within WSL. While in WSL console, run:

curl -I http://example.local
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 01 Nov 2020 15:20:45 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Link: <http://example.local/wp-json/>; rel="https://api.w.org/"

# if you get "200 OK", then check the actual HTML returned by the server
curl http://example.local

You should see the full HTML code of your site. If you don't, then it means you made a mistake somewhere in the configuration or maybe simply nginx is not running. You can also use the Linux text based browser lynx, to see your website in text mode.

Another option is to fully restart WSL. Close your WSL console, open PowerShell and run below command:

wsl --shutdown

Then open WSL console again and make sure all services are running before testing in the browser.