Running PHP under Apache on IBM i

This is IBM’s traditional path: the bundled IBM HTTP Server (Apache) handles the request, hands .php files off to a FastCGI process group running php-cgi, and returns the result. It’s well-trodden, configurable through a web interface, and what most existing IBM i shops are running today.

If you don’t already have a strong reason to choose NGINX, Apache is the lower-friction starting point.


1. Create the Apache instance

Open the IBM HTTP Admin interface in a browser:

http://YOUR-IBM-I-IP:2001/HTTPAdmin

The HTTP Admin interface only loads if the Admin Server is running on the partition. If the page won’t load, an admin needs to start it. See IBM’s Manage server documentation for the command.

Click Create HTTP Server in the top left, and walk through the wizard. Note the web-root paths it creates — typically /www/<server-name>/htdocs for the document root and /www/<server-name>/conf for the configuration. The rest of this chapter assumes the defaults; adjust accordingly if you customized them.


2. Configure Apache to run PHP

Use the Edit Configuration File option in the left panel of HTTP Admin and add the following near the top of the config:

# Load Apache's FastCGI support (originally created for Zend)
LoadModule zend_enabler_module /QSYS.LIB/QHTTPSVR.LIB/QZFAST.SRVPGM

# Tell Apache that any .php file should be handled by FastCGI
AddType    application/x-httpd-php .php
AddHandler fastcgi-script .php

# Allow URLs without /index.php
DirectoryIndex index.php index.html

Click OK at the bottom of the page to save.


3. Configure FastCGI

Apache now knows to route .php files to a FastCGI handler — but the handler itself isn’t configured yet. Without this step, your browser will simply download the PHP source instead of executing it.

Create a file named fastcgi.conf in /www/<server-name>/conf with the following contents:

Server type="application/x-httpd-php" \
       CommandLine="/QOpenSys/pkgs/bin/php-cgi" \
       StartProcesses="1" \
       SetEnv="PHP_FCGI_CHILDREN=10"

PHP_FCGI_CHILDREN=10 starts ten PHP worker processes. Each handles one request at a time, so this is effectively your concurrency cap. Increase it if you start seeing requests queue under load (more on tuning below).

Start the web server, either through the HTTP Admin UI or with:

STRTCPSVR SERVER(*HTTP) HTTPSVR(yourservername)

4. Test

Drop an index.php into your web root containing:

<?php phpinfo(); ?>

Visit the virtual host you set up. If you see the PHP info page, you’re running PHP via the RPMs on Apache. If you instead get a download prompt or a 404, double-check the LoadModule, AddType, and fastcgi.conf steps above — that combination is where almost every problem lives.


The defaults work, but a few additions materially improve performance and prevent a common encoding issue. Add these to your Apache config:

# gzip compression — keep these near the top with the other LoadModules
LoadModule deflate_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
AddOutputFilterByType DEFLATE \
    application/x-httpd-php \
    application/json \
    text/css \
    application/x-javascript \
    application/javascript \
    text/html

# Keep-alive and connection tuning
TimeOut          30000
KeepAliveTimeout 30
HotBackup        Off
ThreadsPerChild  40

# CCSID — fixes the "my output looks scrambled" problem most shops hit eventually
DefaultFsCCSID   37
CGIJobCCSID      37

The DefaultFsCCSID and CGIJobCCSID lines deserve a callout: when output looks like high-ASCII garbage, the cause is almost always a CCSID mismatch between the job running PHP and the data it’s reading. Setting both to 37 (the standard EBCDIC CCSID for U.S. English) resolves the most common version of this.

If your shop runs on a non-U.S. CCSID (e.g., 273, 285, 297, 1141), substitute that value instead of 37. The point is consistency between the filesystem CCSID, the job CCSID, and what your DB2 tables expect.


Tuning Apache and PHP for production

Getting PHP serving requests is one milestone. Sizing it correctly under load is another. Two articles are worth the read before you push to production:

The short version: start with PHP_FCGI_CHILDREN=10, watch your QHTTPSVR job memory and active request count under realistic load, and increase incrementally until p95 latency stops improving. Don’t blindly set this to 100; each child is a real PHP process with real memory cost.


Automating the Apache setup

Seiden Group publishes a tool, siteadd, that wraps the steps above into a single command:

Automatically configure IBM i Apache web server to run PHP with siteadd

If you’re standing up multiple instances or scripting environment setup, it’s worth using.


Where next