Apache 2 and PHP (mod_php) on Linux

Apache 2 and PHP Installation

The following notes are how I got Apache 2 and PHP 4.x working together on Linux (initially RedHat 7.3 and now RedHat 9). These instructions also apply, mostly, for any UNIX-like system, especially other Linux distributions. If you have RedHat 9, you already have Apache 2 and PHP, so you don't need to do this unless you want the latest Apache 2 or PHP release or need to customize the Apache or PHP software. Don't forget to remove (or at least disable) the Apache rpm package if you install your own custom Apache.

Apache 2 Version Tip: Beginning with Apache 2.0.42 the API will be kept stable (yeah!). That means you will NOT have to recompile modules (and possibly upgrade/fix source) everytime you install a new Apache release. This assumes you stay in the same Apache release series. For example, upgrading from 2.0.43 to 2.0.45 should work. This will not apply to upgrading to the next series (e.g., "development" 2.1.x or "stable" 2.2.x).

I was only able to get PHP working with Apache 2 as a DSO (as opposed to compiled into Apache). I think DSO is the only way PHP is supported now on Apache 2.

I first used httpd-2.0.43 and php-4.3.0 with RedHat 7.3. I am now using httpd-2.0.49 and php-4.3.5 with RedHat 9. The older php-4.2.3 did not work with Apache 2.0.43. Also, since php 4.3.0 has a security problem, you should use php 4.3.1 or higher.

If you have problems with PHP and think it's a recent bug, you may want to consider using the latest snapshot at http://snaps.php.net/php4-latest.tar.gz
Beware that snapshots frequently have regression and are not for production use. Usually problems are because of mis-configuration, not bugs, so this will probably hurt more than help.

  1. Download/unpack Apache2 source from the Apache httpd server website, http://httpd.apache.org/

  2. In the Apache 2 source directory, type:
    ./configure --prefix=/usr/local/apache \
    	--enable-so	\
    	--enable-cgi	\
    	--enable-info	\
    	--enable-rewrite	\
    	--enable-speling	\
    	--enable-usertrack	\
    	--enable-deflate \
    	--enable-ssl	\
    	--enable-mime-magic
    
    You only need the enable-so line above. For information on other options, type ./configure --help and see "Compiling and Installing" in the Apache 2 Documentation, http://httpd.apache.org/

  3. Make Apache:
    make
    

  4. If make is successful, install Apache as root:
    make install
    

  5. Download/unpack PHP source from the PHP website, http://www.php.net/
    Pick one from the 4.3.x series (see note above).

  6. In the php source directory, type:
    ./configure \
    	--with-apxs2=/usr/local/apache/bin/apxs \
    	--with-mysql \
    	--prefix=/usr/local/apache/php \
    	--with-config-file-path=/usr/local/apache/php \
    	--enable-force-cgi-redirect \
    	--disable-cgi \
    	--with-zlib \
    	--with-gettext \
    	--with-gdbm
    
    You only need the with-apxs2, and prefix lines. with-mysql adds MySql, with-config-file moves the php.ini file location, disable-cgi disables the CGI version, which is not needed if you use Apache modules. It also enables and installs the command line interface (CLI) version. with-zlib allows use of gzip-type compression, with-gettext is for internationalization, and with-gdbm allows access to GDBM databases. For more information, type ./configure --help and see the "Installation" chapter in the PHP Manual, http://ww.php.net/docs.php

  7. Make PHP:
    make
    

  8. If make is successful, type this as root to install PHP:
    make install
    

    If you are not root (I do not perform makes while root, for security and safety reasons), become root and type the following:

    make install-su
    

  9. If file /usr/local/apache/modules/libphp4.so does not exist or is an older version, type this:
    cp -p .libs/libphp4.so /usr/local/apache/modules
    

  10. Install the php.ini file:
    cp -p php.ini-recommended /usr/local/apache/php/php.ini
    

  11. Verify that these directives are in /usr/local/apache/conf/httpd.conf (or add if missing):
    # Make sure there's only **1** line with this directive:
    LoadModule php4_module        modules/libphp4.so
    
    # Add index.php to your DirectoryIndex line:
    DirectoryIndex index.html index.php
    
    AddType application/x-httpd-php php
    
    # PHP Syntax Coloring (recommended):
    AddType application/x-httpd-php-source phps
    

    PHP Syntax coloring isn't required, but it's very nice for looking at your php source while debugging. Here's an example.

    Note: just for completeness I'll mention that you should be able to use SetOutputFilter / SetInputFilter instead of AddType, but you can't use both. However, SetOutputFilter / SetInputFilter no longer works for me. It used to work with an earlier PHP 4.x or Apache 2 version, but not with Apache 2.0.47/PHP 4.3.3. I understand this (PHP as an Apache 2 filter) is experimental, so I don't use it anymore.
    <Files *.php>
            SetOutputFilter PHP
            SetInputFilter  PHP
    </Files>
    

  12. Start httpd as root:
    /usr/local/apache/bin/apachectl start
    

  13. Perform these sanity checks to verify your install went OK:
    $ /usr/local/apache/bin/httpd -t
    Syntax OK
    
    $ /usr/local/apache/bin/httpd -v
    Server version: Apache/2.0.43
    Server built:   Oct 21 2002 16:20:01
    
    $ /usr/local/apache/bin/httpd -l
    Compiled in modules:
    . . .
      mod_so.c
    
    $ /usr/local/apache/bin/httpd -V
    Server version: Apache/2.0.43
    Server built:   Oct 21 2002 16:20:01
    Server's Module Magic Number: 20020903:0
    Architecture:   32-bit
    Server compiled with....
     -D APACHE_MPM_DIR="server/mpm/prefork"
     -D APR_HAS_SENDFILE
     -D APR_HAS_MMAP
     -D APR_HAVE_IPV6
     -D APR_USE_SYSVSEM_SERIALIZE
     -D APR_USE_PTHREAD_SERIALIZE
     -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
     -D APR_HAS_OTHER_CHILD
     -D AP_HAVE_RELIABLE_PIPED_LOGS
     -D HTTPD_ROOT="/usr/local/apache"
     -D SUEXEC_BIN="/usr/local/apache/bin/suexec"
     -D DEFAULT_PIDLOG="logs/httpd.pid"
     -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
     -D DEFAULT_LOCKFILE="logs/accept.lock"
     -D DEFAULT_ERRORLOG="logs/error_log"
     -D AP_TYPES_CONFIG_FILE="conf/mime.types"
     -D SERVER_CONFIG_FILE="conf/httpd.conf"
    
    $ /usr/local/apache/bin/httpd -S
    VirtualHost configuration:
    . . .
    
    $ ps -ef |grep httpd
    root     24069     1  0 09:17 ?        00:00:08 /usr/local/apache/bin/httpd -k s
    apache   29917 24069  0 15:30 ?        00:00:00 /usr/local/apache/bin/httpd -k s
    . . .
    
    

    Note: on BSD-based UNIX systems, you need to use "ps -aux" or "ps aux" instead of "ps -ef".

  14. Access your webserver with telnet. Type HEAD / HTTP/1.0 followwed by a blank line:
    $ telnet localhost 80
    Trying 127.0.0.1...
    Connected to localhost (127.0.0.1).
    Escape character is '^]'.
    HEAD / HTTP/1.0
    
    HTTP/1.1 200 OK
    Date: Thu, 02 Jan 2003 19:29:27 GMT
    Server: Apache/2.0.43 (Unix) mod_ssl/2.0.43 OpenSSL/0.9.6b PHP/4.3.0
    Accept-Ranges: bytes
    X-Powered-By: PHP/4.3.0
    Connection: close
    Content-Type: text/html; charset=ISO-8859-1
    Content-Language: en
    X-Pad: avoid browser bug
    
    Connection closed by foreign host.
    

  15. Access your webserver with your favorite browser. The following is a good test page to use for PHP. Only the line in bold is needed to display PHP configuration information. Name the file anything you want such as phpinfo.php and put it in your web server content directory:
    <html>
    <head>
    	<title>PHP Test</title>
    	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    </head>
    <body>
    	<h1>PHP Test</h1>
    	<p>
    	<b>An Example of PHP in Action</b><br />
    		<?php echo "The Current Date and Time is: <br>";
    			echo date("g:i A l, F j Y.");?>
    	</p>
    
    	<h2>PHP Information</h2>
    	<p>
    		<?php phpinfo(); ?>
    	</p>
    </body>
    </html>
    

Tips and Notes

• Disabling Existing Apache Software

If Apache is already installed with your Linux distribution you have to disable it before installing your own custom version. To do this, type the following under RedHat Linux:

/sbin/chkconfig --del httpd
/etc/init.d/httpd stop
You may also remove the httpd and php rpms, and dependent rpms, if you wish.

• Automatic Startup of Apache

To start Apache automatically, follow these steps:

PHP 4.3.5 PCRE Regression (March 2004)

If you use PHP 4.3.5 with PCRE (Perl Regular Expressions, the default), you get a core dump when you try and restart (SIGHUP) Apache (at least I and others do with 2.0.49). I have a report this is also true for PHP 5.0RC1. The cause is from adding a new version of PCRE, 4.5, to PHP 4.3.5. PHP 5.x may have a similar problem.

The symptom are these messages in error_log:

[Wed Mar 31 17:14:43 2004] [notice] SIGHUP received.  Attempting to restart
[Wed Mar 31 17:14:43 2004] [notice] seg fault or similar nasty error detected in the parent process
[Wed Mar 31 17:14:48 2004] [warn] pid file /var/run/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
Some workarounds are: For details, see PHP bug 27810: http://bugs.php.net/bug.php?id=27810 Sorry, I don't have the diffs for the fix. For me, this isn't much of the problem as I never automatically restart Apache (e.g., to rotate logs). I only restart manually when I add Apache configuration lines.

Redhat 9 (May 2003)
Apache 2 and PHP is built-in RedHat 9 (packages httpd, 2.0.40, and php, 4.2.2). Apache is mostly under /usr/lib/httpd and /usr/sbin/httpd. PHP is at /usr/lib/httpd/modules/libphp4.so For a complete file listing, type: rpm -ql httpd php

For RedHat 9, PHP 4.3.1 gives a compiler errors with RedHat 9 similar to:

my_malloc.c:24: undefined reference to `errno'

The problem is swith mysql and will have to wait for a fix from them. Until then, add this line to the beginning of file ./ext/mysql/libmysql/mysql.h:

#include <errno.h>

in your PHP source and remake (from scratch).

Redhat 8.0
Apache 2 and PHP is built-in RedHat 8.0 (packages httpd, 2.0.40, and php, 4.2.2). Apache is mostly under /usr/lib/httpd and /usr/sbin/httpd. PHP is at /usr/lib/httpd/modules/libphp4.so For a complete file listing, type: rpm -ql httpd php

• If you're compiling (unreleased) PHP 5 CVS, you need the newest libtool 1.4.3 (not in RedHat 8). See http://www.zend.com/lists/php-dev/200302/msg00476.html for RPMs.

ServerRoot Installation Directory

By default, Apache is installed in ServerRoot, as specified in httpd.conf or the httpd -d option:
ServerRoot "/usr/local/apache"
Some packagers and distributions move the location to /usr/local/httpd or /usr/local/apache2 so check that Apache is installed where you say it is, and check that you don't have 2 separate Apache installations by mistake.

MySQL
Use the --with-mysql configure option to build PHP with PHP's version of MySql. If you want the system's MySQL, or are also using MySql with another apache module (e.g., mod_perl), use this: with-mysql=/usr

Custom OpenSSL and SSL
When using "--enable-ssl" (i.e, build with OpenSSL), the configure script will try to guess the location of OpenSSL. If you're using your own custom SSL, you must specify the location. For example, "--with-ssl=/usr/local/ssl" (of course, you can use the SSL and PHP that comes with Redhat 8 or 9 and other distributions).

Please note that mod_ssl is only for Apache 1.x. Apache 2.x does not use mod_ssl--SSL is built into Apache 2.x.

Jason reports that with RedHat 9 on his system, the make failed at mod_ssl. It needed a missing krb5.h header file. The fix is to Add an environment variable, $CFLAGS, before making PHP. That is:
"-I/usr/kerberos/include/ -L/usr/kerberos/lib"

gdbm
If you get this error when using "--with-gdbm":
configure: error: DBA: Could not find necessary header file(s).
then you are probably missing the gdbm-devel rpm package.

Apache 1.x and Apache 2 Configuration Directives
The "AddModule," "AgentLog," "ReferrerLog," "RefererIgnore," "BindAddress," "ClearModuleList," "Port," "FancyIndexing," "ServerType," "AccessConfig," and "ResourceConfig" directives in Apache 1.x no longer exist in Apache 2. Also, "HAVE_*" httpd.conf definitions no longer exist. Most of these directives have been replaced by other directive(s).

Error after glibc library upgrade
Apache should still work after upgrading glibc with security and bug fixes for the same release. If you use another architecture (say from or to i386/i686), you need to recompile. One symptom is an error like this in your Apache error_log: [error] (38)Function not implemented:

make clean
Kåre Olaussen adds this note: If you're compiling php4 for both Apache 1.3 and Apache 2, use a separate php source directory for each version of Apache. "The module wouldn't load into Apache 2, because I had forgotten to run make clean in between." [Ed. note: I recommend untaring the source from scratch in another directory, that way you are sure no old state information is left behind from previous makes. Do this for any configuration or version changes.]

Enabling register_globals for Apache 2
From Duke: For those of you that are desperately trying to enable register_globals on a per-directory basis using Apache 2 with PHP 4 using .htaccess files, the syntax is different from Apache 1.x. In the directory you want to enable register_globals (or pretty much any other on/off setting), add an .htaccess file containing:
  php_value register_globals 1
Note that php_flag does not work with Apache 2. Neither does on / off -- you must use 0 (off) or 1 (on).

[Editor's note: To enable globally, add register_globals=off to your php.ini file.

To enable on a per-directory basis, you can add to a <Directory> stanza or create a .htaccess configuration file in the directory. To use .htaccess, you must first enable it by adding AllowOverride All (or some combination of AllowOverride options within the correct <Directory> stanza. Also newer PHP software, such as SquirrelMail, no longer require register_globals to be enabled. Keeping register_globals disalbed makes the system much more secure (as it's harder to set internal php variables through submitting html forms). ]

Multi-Processing Module (MPM): don't use multi-threading MPMs
MPMs is how Apache 2 handles multiple web server requests. That is, with multiple processes or multiple threads or some combination. For now, on Linux (and even UNIX) you should only use the (default) prefork module with PHP. This is specified at compile time. Other MPM modules (any involving threaes) break PHP. This is partly because PHP uses a great number of external libraries, and many or most of them are not thread-safe or thread-aware. In any case, Linux 2.4 doesn't handle threads efficiently yet--multiple processes are better (this changes with Linux 2.6, or RedHat 9 with 2.6 threads backported to Linux 2.4).

PATH_INFO
Dan Fitzpatrick notes that he uses PATH_INFO for many PHP scripts like /index.php/go/do/something, (where parameters are passed as "fake" subdirectories). He received a 404 Not Found errors with Apache 2 but not Apache 1.3.27. He had to add "AcceptPathInfo On" to file httpd.conf. For details, see http://httpd.apache.org/docs-2.0/mod/core.html#acceptpathinfo

Using <?   ?> style tags instead of <?php   ?> style tags
If you want to use the old-style (or MS ASP-like) tags, add this line to your php.ini file:
  short_open_tag = On

GD library now built-in PHP
PHP 4.3.0 has gd built-in, just pass --with-gd to configure.

--with-apache Use --with-apache=DIR, where DIR is the root source directory, if you don't have Apache source someone under /usr/local/apache. This tells PHP where to look for the Apache source.

References