Back to Part 1

Ubuntu 24.04 PHP Development: MySQL, Virtual Hosts & Xdebug

Part 2: Professional development tools setup (December 2025)

Complete your PHP development environment with MySQL/MariaDB, wildcard virtual hosts, Xdebug debugging, APCu caching, and YAML support.

📋 Prerequisites

Before starting this guide, you must have completed Part 1 where you installed:

  • Apache 2.4 with PHP-FPM support
  • Multiple PHP versions (7.0 - 8.4)
  • The sphp version switcher script
  • Working ~/Sites directory

If you haven't done Part 1 yet, go back and complete it first!

What You'll Have After This Guide

  • MariaDB (MySQL drop-in replacement) with phpMyAdmin or Adminer
  • Easy *.test domains (myproject.test, blog.test) with simple addhost script
  • Xdebug for all PHP versions with easy on/off toggle
  • APCu cache for 5X faster YAML processing
  • Native YAML support for modern PHP frameworks

1 MySQL/MariaDB Installation

MariaDB is a drop-in replacement for MySQL that's faster, more open, and easier to manage. It's what most modern servers use today.

sudo apt install -y mariadb-server mariadb-client
sudo systemctl enable mariadb
sudo systemctl start mariadb

Secure Your Installation

Run the security script to set a root password and remove test databases:

sudo mysql_secure_installation

Answer the prompts like this:

  • Switch to unix_socket authentication? → No
  • Change the root password? → Yes (set a strong password)
  • Remove anonymous users? → Yes
  • Disallow root login remotely? → Yes
  • Remove test database? → Yes
  • Reload privilege tables? → Yes

Test the Connection

sudo mysql -u root -p

Enter your password. If you see MariaDB [(none)]> you're in! Type exit to leave.

Create a Development User (Recommended)

Instead of using root for everything, create a dedicated development user:

sudo mysql -u root -p

Then run these SQL commands:

CREATE USER 'devuser'@'localhost' IDENTIFIED BY 'YourSecurePassword123!';
GRANT ALL PRIVILEGES ON *.* TO 'devuser'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

What this does:

  • CREATE USER – Creates a new MySQL user (like creating a new system user)
  • GRANT ALL PRIVILEGES – Gives the user full access to all databases
  • FLUSH PRIVILEGES – Reloads the permission tables (makes changes take effect)

2 Database Management: phpMyAdmin or Adminer

Choose one of these tools to manage your databases visually:

Option A: Adminer (Recommended - Lightweight)

Adminer is a single PHP file that's faster and simpler than phpMyAdmin:

sudo mkdir -p ~/Sites/adminer
cd ~/Sites/adminer
sudo wget -O index.php https://github.com/vrana/adminer/releases/download/v4.8.1/adminer-4.8.1.php
chmod 644 index.php

Access at: http://localhost/adminer

Option B: phpMyAdmin (Full-Featured)

If you need more features, install phpMyAdmin:

sudo apt install -y phpmyadmin php-mbstring php-zip php-gd php-json php-curl

# Create symbolic link to ~/Sites
sudo ln -s /usr/share/phpmyadmin ~/Sites/phpmyadmin

During installation:

  • Web server: Select apache2 (use spacebar to select)
  • Configure database: Yes
  • Password: Set a password for the phpMyAdmin application

Access at: http://localhost/phpmyadmin

Login with user devuser or root and your password.

3 Apache Virtual Hosts Configuration

Virtual hosts let you use custom domain names like myproject.test instead of localhost/myproject.

Two Approaches:

  • Individual VHost Files (Recommended) - One file per project, more flexible and professional
  • Wildcard VHost - Single file for all projects, simpler but less configurable

✅ Option A: Individual Virtual Host Files (Recommended)

Create a separate virtual host file for each project. This gives you full control over each project's configuration.

Step 1: Keep localhost working

First, ensure localhost still works for your ~/Sites directory:

sudo nano /etc/apache2/sites-available/000-default.conf

Update DocumentRoot to point to your Sites directory:

DocumentRoot /home/YOUR_USERNAME/Sites

<Directory /home/YOUR_USERNAME/Sites>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

Step 2: Create a VHost file for each project

For each project, create a new virtual host file. Here's an example for "myproject":

sudo nano /etc/apache2/sites-available/myproject.test.conf

Paste this configuration:

<VirtualHost *:80>
    ServerName myproject.test
    ServerAlias www.myproject.test
    DocumentRoot /home/YOUR_USERNAME/Sites/myproject

    <Directory /home/YOUR_USERNAME/Sites/myproject>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/myproject-error.log
    CustomLog ${APACHE_LOG_DIR}/myproject-access.log combined
</VirtualHost>

Remember: Replace YOUR_USERNAME with your actual Ubuntu username!

Step 3: Enable the virtual host

sudo a2ensite myproject.test.conf
sudo systemctl reload apache2

Step 4: Add the domain to hosts

sudo addhost myproject

Quick Script to Create New VHosts

Create a helper script to make this easier:

sudo nano /usr/local/bin/vhost

Paste this script:

#!/usr/bin/env bash
# vhost - Create Apache virtual hosts quickly
# Auto-detects Laravel/Symfony projects and sets correct DocumentRoot
# Usage: sudo vhost myproject [docroot]
#   sudo vhost myproject           - Auto-detect (public/ for Laravel/Symfony)
#   sudo vhost myproject public    - Force public/ subdirectory
#   sudo vhost myproject web       - Use web/ subdirectory
#   sudo vhost myproject .         - Use project root

if [ -z "$1" ]; then
    echo "Usage: sudo vhost projectname [docroot]"
    echo ""
    echo "Examples:"
    echo "  sudo vhost myproject         # Auto-detect Laravel/Symfony"
    echo "  sudo vhost myproject public  # Force public/ directory"
    echo "  sudo vhost myproject .       # Use project root"
    exit 1
fi

PROJECT="$1"
DOMAIN="${PROJECT}.test"
USERNAME=$(logname)
VHOST_FILE="/etc/apache2/sites-available/${DOMAIN}.conf"
PROJECT_DIR="/home/${USERNAME}/Sites/${PROJECT}"
DOCROOT_SUBDIR="${2:-auto}"

# Create project directory if it doesn't exist
if [ ! -d "$PROJECT_DIR" ]; then
    mkdir -p "$PROJECT_DIR"
    chown ${USERNAME}:${USERNAME} "$PROJECT_DIR"
    echo "✓ Created directory: $PROJECT_DIR"
fi

# Auto-detect DocumentRoot
if [ "$DOCROOT_SUBDIR" == "auto" ]; then
    # Check if it's a Laravel/Symfony project
    if [ -f "$PROJECT_DIR/artisan" ] || [ -f "$PROJECT_DIR/composer.json" ]; then
        if [ -d "$PROJECT_DIR/public" ]; then
            DOCROOT_SUBDIR="public"
            echo "â„šī¸  Detected Laravel/Symfony project - using public/ directory"
        fi
    elif [ -d "$PROJECT_DIR/web" ]; then
        DOCROOT_SUBDIR="web"
        echo "â„šī¸  Detected web/ directory"
    else
        DOCROOT_SUBDIR="."
    fi
fi

# Set DocumentRoot
if [ "$DOCROOT_SUBDIR" == "." ]; then
    DOCUMENT_ROOT="$PROJECT_DIR"
else
    DOCUMENT_ROOT="${PROJECT_DIR}/${DOCROOT_SUBDIR}"
    # Create subdirectory if it doesn't exist
    if [ ! -d "$DOCUMENT_ROOT" ]; then
        mkdir -p "$DOCUMENT_ROOT"
        chown ${USERNAME}:${USERNAME} "$DOCUMENT_ROOT"
        echo "✓ Created DocumentRoot: $DOCUMENT_ROOT"
    fi
fi

# Create virtual host file
cat > "$VHOST_FILE" <
    ServerName ${DOMAIN}
    ServerAlias www.${DOMAIN}
    DocumentRoot ${DOCUMENT_ROOT}

    
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    

    # Additional security for Laravel/Symfony
    
        Options FollowSymLinks
        AllowOverride None
        Require all denied
    

    
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    

    ErrorLog \${APACHE_LOG_DIR}/${PROJECT}-error.log
    CustomLog \${APACHE_LOG_DIR}/${PROJECT}-access.log combined

EOF

echo "✓ Created virtual host: $VHOST_FILE"
echo "  DocumentRoot: $DOCUMENT_ROOT"

# Enable site
a2ensite "${DOMAIN}.conf" > /dev/null 2>&1
echo "✓ Enabled virtual host: ${DOMAIN}"

# Add to hosts file using addhost
if command -v addhost > /dev/null; then
    addhost "$PROJECT"
else
    echo "127.0.0.1 ${DOMAIN}" >> /etc/hosts
    echo "✓ Added ${DOMAIN} to /etc/hosts"
fi

# Reload Apache
systemctl reload apache2
echo "✓ Apache reloaded"
echo ""
echo "🎉 All done! Visit http://${DOMAIN}"

Make it executable:

sudo chmod +x /usr/local/bin/vhost

Usage Examples:

# Auto-detect Laravel/Symfony projects
sudo vhost mylaravel    # Automatically uses public/ if Laravel detected

# Create a simple PHP project
sudo vhost myproject    # Uses project root

# Force specific document root
sudo vhost myapp public # Always use public/ directory
sudo vhost legacyapp .  # Use project root directory

# Real-world Laravel example
cd ~/Sites
composer create-project laravel/laravel myblog
sudo vhost myblog       # Auto-detects and uses myblog/public/

đŸŽ¯ Smart Detection:

  • Automatically detects Laravel/Symfony by looking for artisan or composer.json
  • If public/ directory exists → uses it as DocumentRoot
  • Adds security rules to prevent access to parent directories
  • Works with existing projects or creates new ones

Pros:

  • Full control over each project's configuration
  • Can set different PHP versions per project
  • Separate error logs for each project
  • Can add custom settings per project
  • More professional and maintainable

Cons:

  • Need to create a file for each project
  • Slightly more initial setup (but vhost script makes it easy!)

Option B: Wildcard Virtual Host (Simple)

One configuration file that automatically handles all *.test domains. Simpler but less flexible.

Enable Required Modules

sudo a2enmod vhost_alias
sudo systemctl restart apache2

Create Virtual Host Configuration

Create a new configuration file:

sudo nano /etc/apache2/sites-available/dev-vhosts.conf

Paste this configuration:

# Default localhost - keeps working as-is
<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /home/YOUR_USERNAME/Sites

    <Directory /home/YOUR_USERNAME/Sites>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/localhost-error.log
    CustomLog ${APACHE_LOG_DIR}/localhost-access.log combined
</VirtualHost>

# Wildcard *.test domains
<VirtualHost *:80>
    ServerAlias *.test
    VirtualDocumentRoot /home/YOUR_USERNAME/Sites/%1

    <Directory /home/YOUR_USERNAME/Sites>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/vhosts-error.log
    CustomLog ${APACHE_LOG_DIR}/vhosts-access.log combined
</VirtualHost>

Remember: Replace YOUR_USERNAME with your actual Ubuntu username!

Enable the Configuration

sudo a2ensite dev-vhosts.conf
sudo systemctl reload apache2

How it works:

  • ServerAlias *.test – Matches any domain ending in .test
  • VirtualDocumentRoot – Maps myproject.test → ~/Sites/myproject
  • %1 – Captures the first part of the domain name

Pros:

  • One-time setup - no need to create individual files
  • Automatically works for any new project

Cons:

  • All projects share the same configuration
  • Can't customize settings per project
  • All projects share one error log

4 DNS Resolution for *.test Domains

You need a way to resolve *.test domains to localhost. Choose one of these methods:

Why .test? We use .test instead of .dev because Chrome now forces all .dev domains to use HTTPS.

✅ Option A: addhost Script (Recommended - Simpler)

If you have trouble with dnsmasq or prefer a simpler solution, use this script to manage /etc/hosts entries:

Create the Script

sudo nano /usr/local/bin/addhost

Paste this script:

#!/usr/bin/env bash
# addhost - Manage .test domains in /etc/hosts

if [ "$1" == "list" ]; then
    echo "Current .test domains:"
    grep "\.test" /etc/hosts | grep -v "^#"
    exit 0
fi

if [ -z "$1" ]; then
    echo "Usage:"
    echo "  sudo addhost myproject        # Adds myproject.test"
    echo "  sudo addhost list             # List all .test domains"
    echo "  sudo addhost remove myproject # Remove myproject.test"
    exit 1
fi

if [ "$1" == "remove" ]; then
    DOMAIN="${2}.test"
    sudo sed -i "/$DOMAIN/d" /etc/hosts
    echo "✓ Removed $DOMAIN"
    exit 0
fi

DOMAIN="${1}.test"

# Check if already exists
if grep -q "127.0.0.1.*$DOMAIN" /etc/hosts; then
    echo "âš ī¸  $DOMAIN already exists"
    exit 0
fi

# Add to hosts
echo "127.0.0.1 $DOMAIN" | sudo tee -a /etc/hosts > /dev/null
echo "✓ Added $DOMAIN → http://$DOMAIN"

Make it executable:

sudo chmod +x /usr/local/bin/addhost

Usage Examples

sudo addhost myproject        # Creates myproject.test
sudo addhost blog             # Creates blog.test
sudo addhost list             # Shows all .test domains
sudo addhost remove myproject # Removes myproject.test

Pros:

  • Simple and straightforward
  • No service configuration needed
  • Works on all Linux distributions
  • Easy to add/remove domains

Cons:

  • Need to manually add each domain
  • No true wildcard support

Option B: Dnsmasq (Advanced - True Wildcards)

Dnsmasq automatically resolves ALL *.test domains without manual entries. Use this if you want true wildcard support.

Note: Dnsmasq can conflict with other DNS services. If you experience issues, use Option A instead.

Install Dnsmasq

sudo apt install -y dnsmasq

Configure *.test Resolution

echo 'address=/.test/127.0.0.1' | sudo tee -a /etc/dnsmasq.conf

Configure NetworkManager

sudo nano /etc/NetworkManager/NetworkManager.conf

Add this line under the [main] section:

[main]
plugins=ifupdown,keyfile
dns=dnsmasq

Restart Services

sudo systemctl restart dnsmasq
sudo systemctl restart NetworkManager

Test It

ping -c 3 anything.test

If you see 64 bytes from 127.0.0.1 — success! 🎉

Pros:

  • True wildcard support - ALL *.test domains work automatically
  • No need to manually add each domain

Cons:

  • Can conflict with other DNS services
  • More complex to configure
  • May cause issues with NetworkManager on some systems

5 Xdebug Installation for All PHP Versions

Xdebug is essential for debugging PHP. It lets you set breakpoints, inspect variables, and step through code.

Version Compatibility:

  • PHP 7.0-7.1: Xdebug 2.x (legacy)
  • PHP 7.2-8.4: Xdebug 3.x (modern)

Install Xdebug for All Versions

# Install Xdebug for all PHP versions
sudo apt install -y php7.0-xdebug php7.1-xdebug php7.2-xdebug php7.3-xdebug php7.4-xdebug
sudo apt install -y php8.0-xdebug php8.1-xdebug php8.2-xdebug php8.3-xdebug php8.4-xdebug

What this does:

  • Installs the Xdebug extension for each PHP version
  • Ubuntu's package manager handles version compatibility automatically
  • Extensions are disabled by default — you'll enable them per-version next

6 Xdebug Configuration (Modern & Legacy)

For PHP 8.0+ (Xdebug 3.x - Modern Syntax)

Create configuration for modern PHP versions:

for v in 8.0 8.1 8.2 8.3 8.4; do
    sudo tee /etc/php/${v}/mods-available/xdebug.ini > /dev/null <<EOF
zend_extension=xdebug.so
xdebug.mode=debug
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
xdebug.start_with_request=trigger
xdebug.log=/tmp/xdebug.log
EOF
done

For PHP 7.2-7.4 (Xdebug 3.x - Modern Syntax)

for v in 7.2 7.3 7.4; do
    sudo tee /etc/php/${v}/mods-available/xdebug.ini > /dev/null <<EOF
zend_extension=xdebug.so
xdebug.mode=debug
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
xdebug.start_with_request=trigger
xdebug.log=/tmp/xdebug.log
EOF
done

For PHP 7.0-7.1 (Xdebug 2.x - Legacy Syntax)

for v in 7.0 7.1; do
    sudo tee /etc/php/${v}/mods-available/xdebug.ini > /dev/null <<EOF
zend_extension=xdebug.so
xdebug.remote_enable=1
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
xdebug.remote_handler=dbgp
EOF
done

Key Configuration Differences:

  • Xdebug 3.x (PHP 7.2+): Uses xdebug.mode=debug and port 9003
  • Xdebug 2.x (PHP 7.0-7.1): Uses xdebug.remote_enable=1 and port 9000
  • start_with_request=trigger: Xdebug only activates when you trigger it (better performance)

What this does:

  • for v in ... – Loop through each PHP version
  • tee ... > /dev/null – Write config file silently
  • <<EOF...EOF – Multi-line text block (heredoc)

7 Xdebug Switcher Script (Easy On/Off)

Xdebug slows down PHP. Use this script to enable it only when debugging:

sudo nano /usr/local/bin/xdebug

Paste this script:

#!/usr/bin/env bash
# xdebug — Ubuntu Xdebug on/off switcher
# Usage: xdebug on   xdebug off   xdebug (check status)

PHP_VERSION=$(php -v | head -n 1 | cut -d ' ' -f 2 | cut -d '.' -f 1,2)

if [ "$1" == "on" ]; then
    sudo phpenmod xdebug
    echo "✓ Xdebug ENABLED for PHP ${PHP_VERSION}"
elif [ "$1" == "off" ]; then
    sudo phpdismod xdebug
    echo "✓ Xdebug DISABLED for PHP ${PHP_VERSION}"
else
    # Check current status
    if php -m | grep -q xdebug; then
        echo "Xdebug is currently: ON (PHP ${PHP_VERSION})"
    else
        echo "Xdebug is currently: OFF (PHP ${PHP_VERSION})"
    fi
    echo ""
    echo "Usage: xdebug [on|off]"
fi

sudo systemctl restart apache2
echo "Apache restarted."

Make it executable:

sudo chmod +x /usr/local/bin/xdebug

Usage Examples

xdebug          # Check if Xdebug is on or off
xdebug on       # Enable Xdebug for current PHP version
xdebug off      # Disable Xdebug (faster performance)

💡 Pro Tip:

Always run xdebug off when not debugging. Xdebug can slow PHP down by 2-3x!

What this does:

  • phpenmod – Enables a PHP module (creates symlink)
  • phpdismod – Disables a PHP module (removes symlink)
  • php -m | grep – Checks if xdebug is in the loaded modules list

8 CLI Xdebug Setup (for Command Line Debugging)

Sometimes you need to debug CLI scripts (Composer, Artisan, etc.). Create a helper script:

mkdir -p ~/bin
nano ~/bin/xdebug-cli.sh

Paste this content:

#!/usr/bin/env bash
# xdebug-cli.sh — Enable Xdebug for CLI commands
# Usage: source ~/bin/xdebug-cli.sh

export XDEBUG_MODE=debug
export PHP_IDE_CONFIG="serverName=localhost"
export XDEBUG_SESSION=PHPSTORM
export XDEBUG_CONFIG="client_host=127.0.0.1 client_port=9003"

echo "✓ Xdebug CLI environment activated"
echo "Run your PHP command now (e.g., php artisan, composer, etc.)"

Make it executable:

chmod +x ~/bin/xdebug-cli.sh

Usage Example

# Activate Xdebug for CLI
source ~/bin/xdebug-cli.sh

# Now debug any PHP command
php artisan migrate
composer install
php my-script.php

What this does:

  • export – Sets environment variables for the current terminal session
  • source – Runs the script in the current shell (so exports persist)
  • XDEBUG_MODE=debug – Tells Xdebug to activate debugging mode

9 APCu Cache Installation (3X Performance Boost)

APCu is an in-memory cache that dramatically speeds up PHP applications (especially frameworks like Laravel, Symfony).

Install APCu for All Versions

sudo apt install -y php7.0-apcu php7.1-apcu php7.2-apcu php7.3-apcu php7.4-apcu
sudo apt install -y php8.0-apcu php8.1-apcu php8.2-apcu php8.3-apcu php8.4-apcu

Configure APCu (Optional but Recommended)

Create optimized configuration for better performance:

for v in 7.0 7.1 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4; do
    sudo tee /etc/php/${v}/mods-available/apcu.ini > /dev/null <<EOF
extension=apcu.so
apc.enabled=1
apc.shm_size=64M
apc.ttl=7200
apc.enable_cli=1
EOF
done

Restart Services

sudo systemctl restart php*-fpm
sudo systemctl restart apache2

Verify Installation

php -m | grep apcu

Should output: apcu

Configuration Explained:

  • apc.shm_size=64M – Cache size (64MB is good for development)
  • apc.ttl=7200 – Cache lifetime (2 hours = 7200 seconds)
  • apc.enable_cli=1 – Enable APCu for CLI scripts

What this does:

  • APCu stores data in shared memory (RAM) for ultra-fast access
  • Frameworks like Laravel use it for config/route caching
  • Can result in 2-3X performance improvement

10 YAML Extension (5X Faster YAML Processing)

The native YAML extension uses the C library for 5X faster YAML parsing than PHP libraries.

Install libyaml First

sudo apt install -y libyaml-dev

Install PHP Development Tools

sudo apt install -y php-pear php8.3-dev

Install YAML via PECL

sudo pecl install yaml

When prompted for libyaml installation prefix:

Just press Enter to accept the default [autodetect]

Create Configuration File

for v in 8.0 8.1 8.2 8.3 8.4; do
    echo "extension=yaml.so" | sudo tee /etc/php/${v}/mods-available/yaml.ini
    sudo phpenmod yaml
done

Restart Services

sudo systemctl restart php*-fpm
sudo systemctl restart apache2

Verify Installation

php -m | grep yaml

Should output: yaml

For PHP 7.x versions:

Install php7.x-dev first, then follow the same PECL install process. For PHP 7.0-7.1, you may need to install an older YAML version:

sudo pecl install yaml-2.0.4

What this does:

  • PECL – PHP Extension Community Library (package manager for PHP extensions)
  • libyaml – C library that does the heavy lifting
  • Results in 5X faster YAML parsing compared to PHP libraries

11 Final Testing - Put It All Together

Let's test everything we just set up!

Test 1: Virtual Hosts

mkdir -p ~/Sites/testproject
echo "<?php phpinfo(); ?>" > ~/Sites/testproject/index.php
sudo addhost testproject  # Add testproject.test to hosts (if using addhost script)

Visit: http://testproject.test — should show PHP info!

Test 2: PHP Version Switching

sudo sphp 8.3   # Check version at http://testproject.test
sudo sphp 7.4   # Refresh - version changes!
sudo sphp 8.2   # Works instantly

Test 3: Xdebug Toggle

xdebug          # Check status
xdebug on       # Enable debugging
xdebug off      # Disable for performance

Test 4: Database Connection

sudo mysql -u root -p
# Or visit http://localhost/adminer or http://localhost/phpmyadmin

Test 5: Extensions

php -m | grep -E 'apcu|yaml|xdebug|opcache'

Should list all installed extensions.

Test 6: Real-World Laravel Project

cd ~/Sites
composer create-project laravel/laravel mylaravel
cd mylaravel
cp .env.example .env
php artisan key:generate

# Create virtual host (auto-detects Laravel and uses public/)
sudo vhost mylaravel

Visit: http://mylaravel.test (no /public needed!)

✨ Notice the difference:

  • Old way: http://mylaravel.test/public (ugly!)
  • New way with vhost script: http://mylaravel.test (clean!)
  • The script automatically detected Laravel and configured the DocumentRoot correctly

🎉 Congratulations!

You now have a complete, professional PHP development environment:

  • ✅ MySQL/MariaDB with phpMyAdmin or Adminer
  • ✅ Easy *.test domains (addhost script or dnsmasq)
  • ✅ Apache virtual hosts with automatic routing
  • ✅ Xdebug with easy toggle
  • ✅ APCu cache for performance
  • ✅ Native YAML support
  • ✅ Multiple PHP versions with instant switching

Start building amazing PHP projects! 🚀

Quick Reference Commands

sudo sphp 8.3 Switch to PHP 8.3
sudo vhost myproject Create full vhost setup for myproject.test
sudo addhost myproject Just add myproject.test to hosts
xdebug on Enable Xdebug
xdebug off Disable Xdebug
sudo systemctl restart apache2 Restart Apache
sudo mysql -u root -p Access MySQL
php -m List loaded PHP modules

🔧 Common Issues & Solutions

Virtual host not working?

Check: ping myproject.test — should respond with 127.0.0.1

If using addhost: sudo addhost myproject

If using dnsmasq: sudo systemctl restart dnsmasq NetworkManager

Xdebug not working?

Check: php -m | grep xdebug — should show xdebug

If not: xdebug on && sudo systemctl restart apache2

Can't connect to MySQL?

Check: sudo systemctl status mariadb — should be active

If not: sudo systemctl start mariadb

🚀 Next Steps

  • 1. Check out Part 3 for SSL/HTTPS setup (coming soon)
  • 2. Install Composer globally: curl -sS https://getcomposer.org/installer | php && sudo mv composer.phar /usr/local/bin/composer
  • 3. Install Node.js: curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install -y nodejs
  • 4. Set up your IDE (VS Code, PHPStorm) with Xdebug configuration