Skip to content

Instantly share code, notes, and snippets.

@sebastian-meyer
Last active October 25, 2024 23:24
Show Gist options
  • Save sebastian-meyer/be4662db945c1df3e95e020970cba606 to your computer and use it in GitHub Desktop.
Save sebastian-meyer/be4662db945c1df3e95e020970cba606 to your computer and use it in GitHub Desktop.
PHP Web Development on WSL2

PHP Web Development on WSL2

Introduction

The goal is to have an easy to use environment for developing, debugging and profiling web projects with PHP. We don't want to fiddle with configuration files each time we start a new project or try a different version of our project. Instead we want to symlink a new directory and fire up the browser to get going.

The following environment provides Debian GNU/Linux 12 (Bookworm) with PHP 8.2 (and Xdebug), Composer 2.5, Nginx 1.22.2, MariaDB 10.11, Memcached 1.6.18 and Redis 7.0.

Recommendation: Windows Terminal

Windows Terminal is not strictly necessary to run WSL, but it is highly recommended. Windows Terminal supports multiple command lines in tabs or window panes which makes switching between multiple Linux distributions or other command lines easy. Follow the instructions for Windows Terminal installation.

Accessing the Microsoft Store

When installing WSL or any Linux distribution the default command downloads all files from the Microsoft Store. If you can't access the Microsoft Store you can use the parameter --web-download with any wsl.exe --install and wsl.exe --update command or manually download and install the package from GitHub.

Setting up the environment

Installing Windows Subsystem for Linux (WSL)

Follow the instructions to Install WSL

  • Start a PowerShell as Administrator
  • Run WSL installation
    • wsl.exe --install --no-distribution

Alternatively on older versions of Windows:

Follow the Manual installation steps for older versions of WSL

  • Start a PowerShell as Administrator
  • Activate the WSL Feature
    • dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
  • Activate the VM Platform Feature
    • dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
  • Reboot
  • Download and install the Linux Kernel Update Package
  • Update WSL components to latest version
    • wsl.exe --update
  • Use WSL2 as default
    • wsl.exe --set-default-version 2

Installing Debian/GNU Linux

  • Download and install distribution image
    • wsl.exe --install -d Debian
  • Set username and password
  • Start shell with root privileges
    • sudo -s
  • Update packages
    • apt-get update && apt-get upgrade
  • Install useful packages
    • apt-get install aptitude curl git lsb-release mc nano unzip wget zip
  • Optional: Add DEB.SURY.ORG package archive for PHP 8.3+
    • curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg
    • sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ bookworm main" > /etc/apt/sources.list.d/php.list'
    • apt-get update
  • Install development packages
    • apt-get install composer mariadb-server memcached nginx php-apcu php-cli php-curl php-fpm php-gd php-mcrypt php-memcached php-mysql php-redis php-sqlite3 php-xdebug php-xml php-yaml php-zip redis-server
  • Secure MariaDB instance
    • service mariadb start
    • mysql_secure_installation
      • Set password for root
  • Allow PHP (and Composer) to write in web directories
    • chown -R www-data:www-data /var/www
  • Configure Xdebug extension for PHP
    • Create /etc/php/8.2/fpm/conf.d/99-xdebug.ini (see below)
      • If you are using a different version of PHP you have to adjust the path accordingly
  • Configure Nginx server
    • Stop service
      • service nginx stop
    • Create /etc/nginx/sites-available/dev-sites (see below)
    • Deactivate default site
      • rm /etc/nginx/sites-enabled/default
    • Activate development sites
      • ln -s /etc/nginx/sites-available/dev-sites /etc/nginx/sites-enabled/dev-sites
  • Start all services
    • Create /usr/local/bin/phpdev (see below)
    • phpdev start
  • Exit root shell
    • exit

Working with the environment

The Nginx configuration automatically serves sub-directories like /var/www/*.localhost/ as http://*.localhost while using /var/www/*.localhost/public/ as document root. Using domains other than localhost may require additional DNS configuration.

E. g. the file /var/www/example.localhost/public/index.php can be reached via http://example.localhost/index.php.

The files in WSL can be accessed in Visual Studio Code by using the Remote Development extension pack (or at least the WSL plugin). There is a nice tutorial on how to set up the IDE.

Alternatively, the WSL filesystem can be mounted as network storage in the file explorer with the address \\wsl$\Debian. Or you can symlink your Windows filesystem (automatically mounted as /mnt/c, /mnt/d, etc.) to /var/www/* and keep your files where they are. Be aware that cross-system filesystem performance is not the fastest with WSL2.

There are some helpful basic commands for WSL.

Restarting the environment

  • Start all services after reboot
    • sudo phpdev start
  • Restart all services during development
    • sudo phpdev restart
  • Stop all services
    • sudo phpdev stop
@sebastian-meyer
Copy link
Author

sebastian-meyer commented Nov 7, 2022

/etc/nginx/sites-available/dev-sites

server {
    listen 127.0.0.1:80 default_server;
    listen [::1]:80 default_server;
    server_name _;

    root /var/www/${host}/public;

    index index.php index.htm index.html;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string =404;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt { access_log off; log_not_found off; }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_buffering off;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock; # Adjust for your PHP version
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    }

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
}

@sebastian-meyer
Copy link
Author

sebastian-meyer commented Nov 7, 2022

/usr/local/bin/phpdev

#!/bin/bash

if [[ $1 == "start" ]]; then
    service mariadb start &>/dev/null
    service memcached start &>/dev/null
    service redis-server start &>/dev/null
    service php8.2-fpm start &>/dev/null # Adjust for your PHP version
    service nginx start &>/dev/null
    echo "PHP development environment is running."
elif [[ $1 == "stop" ]]; then
    service nginx stop &>/dev/null
    service php8.2-fpm stop &>/dev/null # Adjust for your PHP version
    service redis-server stop &>/dev/null
    service memcached stop &>/dev/null
    service mariadb stop &>/dev/null
    echo "PHP development environment stopped."
elif [[ $1 == "restart" ]]; then
    service mariadb restart &>/dev/null
    service memcached restart &>/dev/null
    service redis-server restart &>/dev/null
    service php8.2-fpm restart &>/dev/null # Adjust for your PHP version
    service nginx restart &>/dev/null
    echo "PHP development environment restarted."
fi

@sebastian-meyer
Copy link
Author

sebastian-meyer commented Jul 25, 2024

/etc/php/8.*/fpm/conf.d/99-xdebug.ini

[Xdebug]
xdebug.mode = develop,debug
xdebug.start_with_request = yes
xdebug.log_level = 0
xdebug.discover_client_host = 1
xdebug.client_port = 9003
xdebug.output_dir = ".vscode\xdebug"
xdebug.profiler_output_name = "cachegrind.out.vscode"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy