JetBrains’ IDEs such as PhpStorm have always been top notch tools for developers, offering a wealth of features.  Unfortunately this same wealth can also become an embarrassment of riches when trying to slog through all the settings and options to set up features.  Such is certainly the case for setting up Xdebug – there are so many factors to take into consideration that it can be positively nightmarish getting debugging to work.  Well, fear it no longer, for here is our super-complete guide to setting up your Apache server with Xdebug and configuring your local PhpStorm install for PHP debugging.

00 – Contents:

  1. Server Setup
  2. PhpStorm Setup
    1. Server <-> Local Filesystem Sync Configuration (Deployment) (Optional)
    2. Project Remote Server Configuration
  3. Local Browser Setup
  4. Testing & Troubleshooting
  5. Profiling (Optional)
  6. Tracing (Optional)

01 – Server Setup

For this post, the server environment was

Firstly, you need to ensure that Xdebug is installed.  You can install Xdebug manually, but the easiest was to do it is via the PECL package or apt-get from the Ubuntu repositories.  I chose PECL, as it is more likely to be the latest version.  If Xdebug is already installed, PECL will inform you and simply exit.

$ sudo pecl install xdebug

To check if Xdebug has been installed, check the output of phpinfo().  You can either whip up a quick PHP page and view the output in your browser, or if you have php5-client installed you can check the output via the -i flag piped through grep:

$ php -i | grep Xdebug
with Xdebug v2.2.1, Copyright (c) 2002-2012, by Derick Rethans

Next, we need to ensure that php.ini is properly configured (or /etc/php5/conf.d/xdebug.ini if you installed Xdebug via apt-get; note that installing via apt-get will add the zend_extension config value for you).  First, you’ll need to determine the exact location of your installation of

# sudo find / -name '' 2> /dev/null

If you want to generate PHP scripting profiles using Xdebug, you’ll also need to create an output directory that has write privileges for the Apache user (www-data).  In this example, the directory is being created right in the main web server directory.  In practice, this is not a good idea – choose somewhere more appropriate for your installation.

$ sudo mkdir /var/www/xdebug-profiles
$ sudo chown www-data:www-data /var/www/xdebug-profiles

Next, as root open /etc/apache2/php.ini in your favourite editor and add the following Xdebug configuration flags to the Dynamic Extensions section:


xdebug.remote_host=   ;insert your own workstation's IP here

;xdebug.remote_connect_back=1     ;uncomment if your workstation has a dynamic IP 
                                  ; or you need access from multiple workstations
xdebug.remote_port=9000           ;default value, change it if you need to

;add these four lines if you want to profile and have 
;  created the output directory for the apache user
xdebug.profiler_enable=0     ;to always profile, set to 1 & comment out xdebug.profiler_enable_trigger
xdebug.profiler_output_name=xdebug-profile.%R.%t    ;ensures unique filenames for output

;add these seven lines if you want to function trace and have 
;  created the output directory for the apache user
xdebug.auto_trace=0       ;to always profile, set to 1 & comment out xdebug.trace_enable_trigger
xdebug.collect_params=4   ;displays full parameter variable names and values
xdebug.collect_return=1   ;display function return values
xdebug.trace_format=2     ;HTML formatted; 0=human readable, 1=computer readable

Finally, make sure that you have the Xdebug remote port specified in php.ini (the default is port 9000) open in both your server firewall (if any)  and router firewall.  Depending on your router set up, you may need to explicitly forward the port to your server (ie, your server is not in your router’s DMZ).  Restart apache to load the new php.ini directives:

sudo apache2ctl restart

You can also ensure sure your Xdebug directives are being interpreted correctly by checking the output of phpinfo() and searching for the “xdebug” section:

If you want to use Xdebug PHP performance profiling with Webgrind with graphs, you’ll also need to install Python and Graphviz:

sudo apt-get install python graphviz

02 – PhpStorm Setup

While there is both a simple and detailed walk through on the JetBrains WebStorm & PhpStorm Blog, they are a couple of years old (for PhpStorm 2) and are missing a lot of troubleshooting details that will be included here.

For this stage, it’s assumed you already have a PHP project set up and have access to the remote files system.

Optional: Server <-> Local Filesystem Sync Configuration (Deployment)

Of course, you’ll need some way to synchronize local and server files.  In this example PhpStorm’s built-in FTP is used to sync the local files with the server’s.

To start, open the PhpStorm “Settings” by going to File->Settings (CTRL-ALT-S).   On the left hand navigation under the “Project Settings” heading, select “Deployment”.  Under the “Connection” Tab, make sure all the relevant fields are correctly filled out for your server & connection type.  Most of these fields will be the same, unless you’re using a mounted folder.

Name The name for the deployment profile.
Host The name or IP of your server.
Port The port to connect over.
Root path The absolute file system path to the directory for the remote connection to use as it’s root directory.
(eg) /var/www/
User name The name for the connection user account.
Password The password for the connection user account.
Web server root URL The URL path you would enter into a browser to visit the root for the project.

Click the “Test” button to make sure everything works.  You might also want to click on “Options” below “Deployment” in the left hand navigation pane and ensure that the “Upload changed files automatically to the default server” is at the value you want.  We’d recommend “On explicit save action” so that your files are synced whenever you save them in PhpStorm.

The next tab is “Mappings”, and it should be already populated with the correct values.  Double check to ensure that they are correct.  You can also use the “Excluded Paths” tab to define any folders that should not be synced with the server.

Local path Location of project files on local filesystem.
(eg) /home/developer/projects/myprojects/blog
Deployment path
The path on the server to the project files, relative to the “Root path” defined in the Connection tab.
(eg) If you defined your “Root path” as “/var/www” and the project files are in “/var/www/blog”, then the “Deployment path” would be “/blog”.
Web path on server
The URL path to the project, relative to “Web server root URL” path defined in the Connection tab.
(eg) If you defined your “Web server root URL” as “” and your project can be found at “”, then the “Web path on server” would be “/blog”.

To sync the local files with the server files, click “Tools->Deployment->Download from <server name>” from PhpStorm’s main menu.  After that, every time you save a file locally it will automatically be uploaded to the server as well.

You can also view the video tutorial “Working with remote project” on the JetBrains support website for more information.

Project Remote Server Configuration

Still in the Project settings, navigate to PHP->Servers.  Click the “+” button next to the search bar to add a new server.

A configuration panel will appear for you to enter your remote server’s details:

Name A custom name for the remote server.
Host The name or IP of your server.
Port The port to connect over. (default is http, ie. 80)
Debugger The debugger in use on the server. (ie, Xdebug)

You’ll also need to map the local files/directories to the remote server paths.  To map the server’s root directory to your project’s root directory, click on the project’s root directory in the filesystem tree under the column “File/Directory” to select it, and then click on or to the right of the square + pen in the right hand column “Absolute path on the server” to enter the corresponding root directory on the remote server.  If you are using PhpStorm’s built in FTP file syncing services, in the vast majority of cases this should match the syncing set up’s “Root Path” and “Deployment Path”.  For our example set up, the remote server path will be “/var/www/blog”.

If there are any other directories or files on the remote server that are being edited that are outside the root directory that has just been set, those will need to be mapped separately as well.  For instance, if the files in the remote directories “/var/www/blog” and “/home/webdev/includes” are in the same PhpStorm project, you will need to map the project’s local directory to the corresponding remote ones as well.

If you’ve set the Xdebug port to  a value other than the default (9000) in your server’s php.ini, you’ll need to navigate to PHP->Debug to change the port in PhpStorm as well.  The path mapping set will cascade to any subdirectories and files in the local project files, so in the example once “/var/www/blog” is set the local file “index.php” will be assumed to be mapped to “/var/www/blog/index.php”.  If there are any symlinked directories or files in the cascade, these will need to be manually mapped.

Finally, you’ll also need to be sure that your router and/or work station’s firewall is set up to allow connections over the Xdebug port (default is 9000).   If you have UPnP enabled on your router, you won’t have to worry about port forwarding the Xdebug port to your workstation.  If you’re working from outside the server’s LAN, such as from home, be aware some ISPs block non-standard ports for some account types (such as residential/consumer accounts).

03 – Local Browser Setup

The last step is setting up your local machine’s browser to trigger debugging, profiling, etc.  This is a simple matter of adding bookmarklets to turn on and off debugging, profiling, etc.  It’s also possible to manually set various cookie, GET or POST triggers, but the bookmarklets are by far the easiest method.

To start, visit JetBrain’s Zend Debugger & Xdebug bookmarklets generator for PhpStorm page.  Under the “Xdebug” section, the default IDE key (PHPSTORM) should already be set.  Click the “Generate” button to create the bookmarklets:

Right click on each of the generated links you want to use and select “Bookmark this link”.

The default bookmarklets generated are:

Start Debugger


Stop Debugger


Debug this Page


Start Profiler


Stop Profiler


Start Tracer


Stop Tracer


04 – Testing & Troubleshooting

To test your setup:

  1. Create a break point in the PHP page to test by left clicking the gutter next to the line number where you want to start debugging; a red dot should appear:

    If you try to left click or key CTRL+F8 on a blank line or comment nothing will happen, and the menu item “Run->Toggle Line Breakpoint” will be greyed out.  This does not mean debugging is not working.  PhpStorm does not allow for break points on non-code lines – you must set a breakpoint on a line with code.
  2. Turn on PhpStorm’s listener for debugging by either clicking Run->Start Listen PHP Debug Connections or by clicking the “Debug Listen” toggle button (the red phone icon will turn green and waves will come out of the ear piece):
  3. Navigate to the page you want to debug in the browser.
  4. Open your browser and click the “Start Debugging” bookmarklet.
  5. Refresh the page in the web browser to start debugging.

PhpStorm should now enter Debugging mode, showing the debug console and positioning the cursor at the first breakpoint in the file being debugged in the editor:

If PhpStorm doesn’t enter debugging mode, there are a few tests you can carry out to ensure that everything is connecting properly:

  • Check your local machine and server software firewalls (if any) as well as your local and server router firewalls to ensure that the debugging communications port (default is 9000) is not being blocked.
  • From your server, try to telnet to your local machine on port 9000.  If it can make a connection, PhpStorm is in debug mode and connected.
  • Enable Xdebug logging in your php.ini file by adding “xdebug.remote_log=”<some file path that your apache user has write permissions>”.  Then stop PhpStorm debug connection listening (either using the toggle button or the entry under the PhpStorm “Run” menu), stop your test page in your browser loading if it hasn’t already stopped, restart Apache (sudo service apache2 restart), start the debugging process again, and check for any helpful log entries.  A successful connection entry looks like this:
    Log opened at 2012-12-24 04:21:17
    I: Checking remote connect back address.
    I: Remote address found, connecting to
    I: Connected to client. 🙂
    -> <init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="
    debug" fileuri="file:///home/web/ti3/index.php" language="PHP" protocol_version=
    "1.0" appid="666" idekey="PHPSTORM"><engine version="2.2.1"><![CDATA[Xdebug]]></
    engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[http://xdebug.or
    g]]></url><copyright><![CDATA[Copyright (c) 2002-2012 by Derick Rethans]]></copy

That should have you up and running!  If you have any problems, there’s also always the JetBrains PhpStorm Support web page, the PhpStorm Online Manual (surprisingly good), and the JetBrains PhpStorm forums to search and ask for help.

05 – Profiling (Optional)

A handy tool for assessing bottlenecks, dependencies, etc.  in your code is profiling via Xdebug.  Profiling is enabled in php.ini on your server.  Probably the easiest way to view the resulting cachegrind files on your local machine is via Webgrind.  While this doesn’t give the same level of detail as something like KCachegrind, it is good enough for casual refactoring, optimization and debugging.

Change to your preferred directory for serving web files and git clone webgrind to your server (eg, “cd /var/www; sudo git clone”).   After it’s synced, edit config.php’s variables to reflect your local server’s environment:

$storageDir Directory for webgrind to store processed cachegrind files.  Creating a subdirectory of “/var/www/webgrind” for this would be the fastest and easiest course (ie, ‘/var/www/webgrind/profiles’).
$profileDir Directory specified in php.ini directive xdebug.profiler_output_dir that holds the Xdebug cachegrind profiling output.
$defaultTimezone Your local timezone.  (Optional)
$pythonExcecutable Python’s location on your server.  (Optional, used for displaying graphs)
Used to create profiling graphs via a Python script (installation on Ubuntu:  “sudo apt-get install python”).
You can determine python’s location using which (eg, “which python”).  On Ubuntu, the location is /usr/bin/python.
$dotExecutable Dot utility’s location on your server.  (Optional, used for displaying graphs)
Part of the graphviz utility (installation on Ubuntu: “sudo apt-get install graphviz”).
You can determine dot’s location using which (eg, “which dot”).  On Ubuntu, the location is /usr/bin/dot.

Make sure that the webgrind directories and files are accessible to your Apache user (eg, “sudo chown -R www-data:www-data /var/www/webgrind”), or webgrind will either error out when you try to visit it, or display blank pages when you update the view with profiling data.

To use Webgrind:

  1. Load the page you want to profile in your browser.
  2. Click the “Start profiler” bookmarklet.
  3. Reload the page.
  4. Visit the webgrind page in your local machine’s browser (eg, “”)
  5. Select the profile you’d like to see from the drop down selectbox, and click the “update” button.

06 – Tracing (Optional)

Function tracing is a handy Xdebug tool for recording all function calls in a PHP script in the order that they occur, with all parameters and return values available.  Tracing is enabled in php.ini on your server.  Probably the easiest way to view the resulting trace files on your local machine is via HTML output.

Make sure that the trace directories and files are accessible to your Apache user (eg, “sudo chown -R www-data:www-data /var/www/xdebug-profiles”), or Apache will either error out when you try to visit it, or won’t write any profiling data to the directory.

To view the profile results, you can add an .htaccess file with “Options +Indexes” to allow directory listing for the profiling directory, then visit “http://<domain>/xdebug-profiles” and click on the trace you’re interested in.

For nifty extra features in the directory listing, such as sortable column headers and the like, add “IndexOptions FancyIndexing” to .htaccess as well.

Finally, in order to get your browser to correctly interpret the .xt files as HTML and display them nicely, add “AddType text/html .xt” to .htaccess (or if you want to enable this MIME type mapping globally, you could put it in your http.conf).

(eg) .htaccess

Options +Indexes
IndexOptions FancyIndexing
AddType text/html .xt

Bear in mind this is enormously insecure, as it may display privileged information in the variable parameters.  You should at the very least password protect this directory.

Don’t forget that in order to use .htaccess files, you’ll need to set “AllowOverride AuthConfig” in your http.conf (on Ubuntu, the various site http.conf files are found in “/etc/apache2/sites-available”).

(eg) http.conf (with global mapping of Xdebug trace file extension xt to the HTML MIME type)

<IfModule mod_mime.c>
     AddType text/html .xt

<Directory /var/www/>
	DirectoryIndex index.php

	AllowOverride All
Related Posts
Installing Webalizer and Publishing Analytics to Your Website
For Linux users hosting their own websites using Apache, the log files provide a wealth of analytics information about bandwidth usage, visitor locales, referrers & keywords, etc.  However, they're not ...
I dislike Ubuntu's built in remote desktop service, and use x11vnc instead. Recently I was having a terrible time recently remotely accessing an Ubuntu+Gnome workstation: when I connect from a ...
Recently I needed to install Asterisk with FreePBX on an existing Ubuntu 10.04 LTS (Lucid Lynx) 64 bit server.  Since Asterisk is really targeted at CentOS this was a bit ...
vsftpd can cause trouble with  slow directory listings or timeouts, but with a little configuration magic you can get this working properly on a CentOS box. All commands will need to ...
While Ubuntu does many things well out of the box, being able to recognize Android devices connected by USB is not one of them.  Instead the devices have to be ...
Installing Webalizer and Publishing Analytics to Your Website
Getting Shift Key Working With x11vnc and VNC
Installing Asterisk 1.8 and FreePBX 2.9.0 on Ubuntu
Fix vsftpd Slow Directory Listings & Timeouts
Mounting your Android’s SD Card on Ubuntu