Category: DevOps

  • Xdebug 3 + Lando + PhpStorm Setup Guide

    Setting up Xdebug with Lando has gotten simpler over the years, but there are still a few gotchas — especially on Windows with WSL2. Here’s a quick, up-to-date setup guide for Xdebug 3 with Lando and PhpStorm.

    Enable Xdebug in Lando

    Lando has built-in Xdebug support. Add xdebug: true to your .lando.yml service config:

    name: my-project
    recipe: wordpress
    config:
      webroot: web
      xdebug: true
      conf:
        php: config/php.ini

    Configure Xdebug 3

    Create a custom config/php.ini with the Xdebug 3 directives. The old remote_enable and remote_host settings from Xdebug 2 no longer work.

    [xdebug]
    xdebug.mode = debug
    xdebug.start_with_request = yes
    xdebug.client_host = host.docker.internal
    xdebug.client_port = 9003
    xdebug.idekey = PHPSTORM
    xdebug.log = /tmp/xdebug.log

    Key changes from Xdebug 2 to 3:

    • xdebug.remote_enable = 1xdebug.mode = debug
    • xdebug.remote_hostxdebug.client_host
    • xdebug.remote_port = 9000xdebug.client_port = 9003 (default port changed)
    • xdebug.remote_autostart = 1xdebug.start_with_request = yes

    PhpStorm Setup

    1. Go to Settings → PHP → Debug and set the Xdebug port to 9003.
    2. Go to Settings → PHP → Servers, add a server matching your Lando URL, and configure the path mapping from your local project root to /app (Lando’s default mount point).
    3. Click Start Listening for PHP Debug Connections (the phone icon) in the toolbar.
    4. Run lando rebuild to apply the config, then load a page — PhpStorm should catch the breakpoint.

    WSL2 Note

    host.docker.internal resolves correctly on Docker Desktop for Windows and macOS. If you’re running Docker inside WSL2 natively (without Docker Desktop), you may need to use your WSL gateway IP instead — find it with ip route | grep default inside WSL.

    Troubleshooting

    If breakpoints aren’t hitting:

    • Check /tmp/xdebug.log inside the container (lando ssh to access it)
    • Make sure the port isn’t blocked by a firewall
    • Verify lando php -v shows Xdebug loaded
    • Try lando rebuildlando restart doesn’t always pick up php.ini changes
  • SSH & Linux Commands Cheatsheet

    A running list of SSH and Linux commands I use regularly when managing servers. Nothing fancy — just the ones I keep looking up.

    Navigation

    # Move into a directory
    cd /var/www/html/
    
    # Go up two levels
    cd ../..
    
    # Where am I?
    pwd
    
    # List files (all, long format, human-readable sizes)
    ls -alh

    Finding Things

    # Find a file by name
    find . -name "wp-config.php"
    
    # Find with wildcard
    find . -name "*.log"
    
    # Find directories only
    find . -name "uploads" -type d
    
    # Search inside files (recursive, case-insensitive, show filenames)
    grep -ril "search_string" /path/to/directory/

    grep flags: r recursive, i case-insensitive, l filenames only, c count matches.

    Find + Exec

    Run a command on every match from find:

    # Set directory permissions to 755
    find . -type d -exec chmod 755 {} \;
    
    # Set file permissions to 644
    find . -type f -exec chmod 644 {} \;
    
    # Move all .eml files to another folder
    find . -name "*.eml" -exec mv -uv {} /home/user/mail/cur \;
    
    # Delete all error_log files
    find . -name "error_log" -exec rm -v {} \;

    Files & Directories

    # Copy a file
    cp source.txt /path/to/destination/
    
    # Download a file from a URL
    wget https://example.com/file.zip
    
    # Delete a file
    rm -v file.txt
    
    # Delete a directory and everything in it
    rm -rvf directory_name/

    Archives

    # Create a tar.gz archive
    tar -czvf archive.tar.gz /path/to/folder/
    
    # Extract a tar.gz archive
    tar -xzvf archive.tar.gz

    Flags: c create, x extract, z gzip compression, v verbose, f filename follows.

    MySQL from the Command Line

    # Export a database
    mysqldump -u db_user -p db_name > backup.sql
    
    # Import a database
    mysql -u db_user -p db_name < backup.sql

    The -p flag prompts for the password — don't put it inline in the command.