Debug your PHP code on Remote Linux server using PHPStorm and xDebug with its port forwarding through SSH

Table of Content

One e-commerce site had a very strange issue, it stop working as expected after cache cleaning. This issue appeared only on production server and couldn’t be reproduced on local machine. So there wasn’t another solution how debug problem directly on the server.

It’s really important to closely check all configuration because one little mistake and you will spend hours or days to find out a problem. I spent 2 days, before I clarified that port on the server had been used by another process.

This tutorial will explain steps by steps how to debug PHP codes on remote Ubuntu 64-bit Server with PHP-FPM (FastCGI Process Manager), PHP 7.2 and Nginx.

Remote Server’s steps

Install xDebug

sudo apt install php-xdebug

Check port availability

xDebug will need a port (usually its port 9000). To make sure the port that we will use for xDebug is available, lets check which ports are in use:

lsof -i:9000

It will display something like this:

COMMAND     PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
php-fpm7. 15224 root   12u  IPv4 7878655      0t0  TCP localhost.localdomain:9000 (LISTEN)

Since port 9000 is already used (by PHP-FPM pool), we will use port 9005 for our xDebug.

Configure xDebug:

sudo vi /etc/php/7.2/mods-available/xdebug.ini

Add the following code into it:

; Enable xdebug extension module
zend_extension=xdebug.so
xdebug.idekey = PHPSTORM

xdebug.default_enable=1
xdebug.remote_autostart = 0
xdebug.remote_enable = 1
xdebug.remote_handler = dbgp
xdebug.remote_host = 127.0.0.1
xdebug.remote_log = /tmp/xdebug_remote.log
xdebug.remote_mode = req
xdebug.remote_port = 9005 # if you want to change the port you can change

Configure PHP_IDE_CONFIG through Nginx

Open configuration file of your site and add next line:

location / {
  ...
  include /etc/nginx/fastcgi_params;
  fastcgi_param SCRIPT_FILENAME $document_root/index.php;
  fastcgi_param SCRIPT_NAME /index.php;
  # this line is important if want to use custom configuration name instead of site domain
  fastcgi_param PHP_IDE_CONFIG "serverName=print-machine";
  ...
}

We will use this value serverName=print-machine when will configure PHPStorm.

NOTE: This step can be omitted, but in that case PHPStorm will automatically create configuration on first request, you’ll need just press "Apply" in popup window.

Restart the services:

sudo systemctl restart php-fpm
sudo systemctl restart nginx

Enable SSH Port Forwarding

Make sure that Allow TCP forwarding is enabled in your SSH server settings:

vi /etc/ssh/sshd_config

Look for:

AllowTcpForwarding yes

Restart the SSH service:

sudo systemctl restart sshd

Local Machine’s steps

Setup PHPStorm

Click "File" > "Settings…" > "Languages & Frameworks" > "PHP" > "Debug". Under "Xdebug" change the "Debug port" to your desired port. In out case we leave it default 9000.
file

Click Servers next to Debug and create new Server configuration.
Name and Host must be the same as we write in Nginx configuration PHP_IDE_CONFIG "serverName=print-machine". Don’t forget enable file mapping: left side – path to local project, right side – path to code on the server.
file

Create PHP Remote Debug

Click "Run" > "Edit configuration…", create new PHP Remote Debug. In Server select server which we created previously, IDE key (session id) should be PHPSTORM:
file

Port forwarding

We will use SSH tunnel port forwarding for connecting to xDebug from PHPStorm.

Execute the following command in terminal:

ssh -R 9005:localhost:9000 <remote_user>@<remote_server_ip>

Where:

  • -R 9005:127.0.0.1:9000 opens up port 9005 as we set the server’s xDebug’s xdebug.remote_port to 9005 earlier, then forwarded to localhost:9000 where PHPStorm is listening
  • <remote_user>@<remote_server_ip> are the username and hostname of the server

Nothing special you won’t see, it’ll open new session, connect to remote server and do port forwarding. Vualia!

Now, to test if the SSH tunnel port forwarding works, run the following command inside your SSH prompt on remove server:

lsof -i:9005

You should see something like this as response:

COMMAND   PID          USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
sshd    30935 print-machine    9u  IPv6 7824135      0t0  TCP ip6-localhost:9005 (LISTEN)
sshd    30935 print-machine   10u  IPv4 7824136      0t0  TCP localhost.localdomain:9005 (LISTEN)

Run Debug

  1. In your PhpStorm, click "Run" > "Break at first line in PHP scripts". This is optional, it is just to ensure that the PHPStorm will trigger when we started to debug our site. To start the PHPStorm listening to xDebug, click "Run" > "Start Listening for PHP Debug Connections".

  2. Open your favorite web browser and visit your site. This should pop a window at PHPStorm that there’s incoming connection from xDebug, just click the "Accept" button.

  3. Your PHPStorm will trigger to stop and highlight at the first line in your site’s PHP script.

Diving deeper

If still having problems you can use following tools in order to find the point where it fails:

tcpdump showing xDebug activity

You can use tcpdump command in order to verify if xDebug is even trying to connect to local machine — and if it does — which target it is trying to connect to.

sudo tcpdump -vv -nn -i any dst port 9000
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
23:50:31.531794 IP (tos 0x0, ttl 64, id 9877, offset 0, flags [DF], proto TCP (6), length 60)
    127.0.0.1.45240 > 127.0.0.1.9000: Flags [S], cksum 0xfe30 (incorrect -> 0x6efe), seq 3410588541, win 65495, options [mss 65495,sackOK,TS val 3683447502 ecr 0,nop,wscale 7], length 0

This log shows that xDebug on the remote server (127.0.0.1) connects to my host machine (127.0.0.1) on port 9000. This information is very helpful to get a starting point for further debugging.

With the nc command you can debug connectivity issues:

nc -w5 -z -v 127.0.0.1 9000
Connection to 127.0.0.1 9000 port [tcp/*] succeeded!

nc connecting from within the remote server to the host machine at port 9000
With this we have verified that there is no connectivity issue due to wrong configuration or network restrictions.

Useful links:

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *