Mr. DOS
Member
- Messages
- 230
- Reaction score
- 5
- Points
- 18
Preamble
There are literally hundreds of tutorials and howtos to be found on the web that purport to walk the budding sysadmin through configuring a web server in the best way possible. Many of these extol the benefits of running PHP through CGI under suEXEC or adding suPHP to the mix so PHP scripts run with the same permissions as the script owner. These lists of instructions wind on for pages and pages with little to no explanation as to what the procedure is doing to your precious server and are very often out-of-date or tailored for a different operating system than they claim. The purpose of this guide is to provide a concise, clear, and up-to-date tutorial on installing Apache 2.2 and FastCGI-based PHP 5 under suEXEC on a modern Debian installation. It assumes some pre-existing familiarity with *nix-based systems and Apache virtual hosts.
The Goals
Installing Everything
Assuming a Debian 5- or 6-based system with no existing webserver installed, we need to install Apache 2.2 in worker mode (apache2-mpm-worker). Additionally, we will need some form of FastCGI for Apache (libapache2-mod-fcgid), the suEXEC wrapper (apache2-suexec-custom), and PHP itself (php5-cgi).
suEXEC can be a bit fiddly in that the document root (the parent folder for all web content) is generally set at compile-time. This has led to numerous guides giving instructions for retrieving the Apache source and reconfiguring and recompiling the suEXEC module to set /home as the document root instead of /var/www. Fortunately for us, Debian provides a custom suEXEC package, apache2-suexec-custom, which has been modified to permit post-compilation reconfiguration by way of a simple configuration file.
Global Configuration
System
Site data will be stored in /home/user/public_html. However, this location doesn’t exist by default and it’s just one more step to forget when adding a new user. Every time a new user is created, the contents of /etc/skel/ are copied into his home directory. Therefore, if you create /etc/skel/public_html/ as root, a public_html directory will be placed into each new user’s home directory. You may also want to place a stub index.html file into /etc/skel/public_html/ to provide some placeholder content for new users.
Apache
Apache’s out-of-box configuration suitable for our needs as far as the scope of this tutorial is concerned, and therefore, will not be modified. You may wish to change things yourself at a later point, such as the DirectoryIndex directive. However, we do need to enable a few extra modules:
suEXEC
The default configuration file for apache2-suexec-custom is /etc/apache2/suexec/www-data. The first line of the file must be changed to reflect the non-default document root.
FastCGI
We will create a configuration file telling FastCGI how to run PHP in /etc/apache2/conf.d/. As any files in /etc/apache2/conf.d/ are automatically included by Apache, it can be named anything you like; this tutorial will use php5-fcgid.conf. Its contents should look something like this:
The first line simply tells Apache what MIME type to send for PHP files. Lines two and three establish that PHP files should be handled by an executable at /fcgi-bin/php5-fcgi, a location which is aliased in line four. Lines five through eight then configure everything in the aliased /fcgi-bin/ to be treated as a FastCGI script and to allow those scripts to execute.
You may have noticed that /fcgi-bin/ points to a location that probably doesn’t exist on your system – /home/www-data/. While this location will be overridden by individual virtual hosts, it should still be defined here as a fallback. You should also create the folder and chown it to www-data.
You may also have noticed that the handler inside /fcgi-bin/, php5-fcgi, doesn’t exist either. This file is simply a wrapper for the actual PHP 5 CGI binary (/usr/bin/php5-cgi), but because suEXEC requires all files run through it (including CGI binaries) to be inside its document root, we can’t point directly to the PHP binary. Create the file /home/www-data/php5-fcgi with these contents:
As you can see, it’s just a simple wrapper for the actual PHP binary. Set the executable bit on the file and chown it to www-data.
Site Configuration
Having finished the global configuration, you should now be able to start adding sites and configuring virtual hosts. As an example, we will set up the server to handle requests for example.com.
System
For consistency’s sake, you should determine a scheme for mapping system users to virtual hosts. For the rest of this tutorial, we will use the second-level domain of the virtual host’s fully-qualified domain name as the account username (e.g., example for example.com).
Add the system user example with home directory /home/example/.
Apache
We need to create a virtual host for this user. A basic template has been provided below; however, any configuration will do as long as it has the same Alias and SuexecUserGroup directives.
The Alias directive overrides the alias set in /etc/apache2/conf.d/php5-fcgid to tell FastCGI that the PHP binary is in /home/www-data/example/. We do this for the sake of suEXEC; not only does suEXEC require all files run through it to be inside its document root, but both the file and the parent folder must be owned by the same user as specified in the SuexecUserGroup directive. While neither this directory nor the PHP binary FastCGI expects to find within it currently exist, we’ll create those in the next step.
SuexecUserGroup simply tells suEXEC as what user and group it should execute things.
suEXEC
No site-specific configuration is necessary for suEXEC.
FastCGI
Now we will create the site-specific PHP wrapper. First, create a subfolder of /home/www-data/ for the site (in this case, /home/www-data/example/), then copy /home/www-data/php5-fcgi into it and chown the folder and the script to your new user.
Conclusion
At this point, it should be safe to enable the new site and restart Apache (or reload, if you restarted at any point after enabling the new modules). If you’d like to make sure PHP scripts now run as your new user, you can use this PHP script:
There are literally hundreds of tutorials and howtos to be found on the web that purport to walk the budding sysadmin through configuring a web server in the best way possible. Many of these extol the benefits of running PHP through CGI under suEXEC or adding suPHP to the mix so PHP scripts run with the same permissions as the script owner. These lists of instructions wind on for pages and pages with little to no explanation as to what the procedure is doing to your precious server and are very often out-of-date or tailored for a different operating system than they claim. The purpose of this guide is to provide a concise, clear, and up-to-date tutorial on installing Apache 2.2 and FastCGI-based PHP 5 under suEXEC on a modern Debian installation. It assumes some pre-existing familiarity with *nix-based systems and Apache virtual hosts.
The Goals
- Content stored in separate home directories and entirely owned by the user associated with the home directory
- Web-facing PHP scripts executed by the file owner, not www-data
- No part of the webserver configuration accessible or modifiable by the end-user
Installing Everything
Assuming a Debian 5- or 6-based system with no existing webserver installed, we need to install Apache 2.2 in worker mode (apache2-mpm-worker). Additionally, we will need some form of FastCGI for Apache (libapache2-mod-fcgid), the suEXEC wrapper (apache2-suexec-custom), and PHP itself (php5-cgi).
Code:
# apt-get install apache2-mpm-worker libapache2-mod-fcgid apache2-suexec-custom php5-cgi
Global Configuration
System
Site data will be stored in /home/user/public_html. However, this location doesn’t exist by default and it’s just one more step to forget when adding a new user. Every time a new user is created, the contents of /etc/skel/ are copied into his home directory. Therefore, if you create /etc/skel/public_html/ as root, a public_html directory will be placed into each new user’s home directory. You may also want to place a stub index.html file into /etc/skel/public_html/ to provide some placeholder content for new users.
Apache
Apache’s out-of-box configuration suitable for our needs as far as the scope of this tutorial is concerned, and therefore, will not be modified. You may wish to change things yourself at a later point, such as the DirectoryIndex directive. However, we do need to enable a few extra modules:
Code:
# a2enmod fcgid suexec actions
The default configuration file for apache2-suexec-custom is /etc/apache2/suexec/www-data. The first line of the file must be changed to reflect the non-default document root.
FastCGI
We will create a configuration file telling FastCGI how to run PHP in /etc/apache2/conf.d/. As any files in /etc/apache2/conf.d/ are automatically included by Apache, it can be named anything you like; this tutorial will use php5-fcgid.conf. Its contents should look something like this:
Code:
AddType application/x-httpd-php .php
AddHandler php-fcgi .php
Action php-fcgi /fcgi-bin/php5-fcgi
Alias /fcgi-bin/ /home/www-data/
<Location /fcgi-bin/>
SetHandler fcgid-script
Options +ExecCGI
</Location>
You may have noticed that /fcgi-bin/ points to a location that probably doesn’t exist on your system – /home/www-data/. While this location will be overridden by individual virtual hosts, it should still be defined here as a fallback. You should also create the folder and chown it to www-data.
You may also have noticed that the handler inside /fcgi-bin/, php5-fcgi, doesn’t exist either. This file is simply a wrapper for the actual PHP 5 CGI binary (/usr/bin/php5-cgi), but because suEXEC requires all files run through it (including CGI binaries) to be inside its document root, we can’t point directly to the PHP binary. Create the file /home/www-data/php5-fcgi with these contents:
Code:
#!/bin/sh
exec /usr/bin/php5-cgi
Site Configuration
Having finished the global configuration, you should now be able to start adding sites and configuring virtual hosts. As an example, we will set up the server to handle requests for example.com.
System
For consistency’s sake, you should determine a scheme for mapping system users to virtual hosts. For the rest of this tutorial, we will use the second-level domain of the virtual host’s fully-qualified domain name as the account username (e.g., example for example.com).
Add the system user example with home directory /home/example/.
Apache
We need to create a virtual host for this user. A basic template has been provided below; however, any configuration will do as long as it has the same Alias and SuexecUserGroup directives.
Code:
<VirtualHost *:80>
ServerAdmin [EMAIL="admin@example.com"]admin@example.com[/EMAIL]
ServerName example.com
ServerAlias [URL="http://www.example.com/"]www.example.com[/URL]
Alias /fcgi-bin/ /home/www-data/example/
SuexecUserGroup example example
DocumentRoot /home/example/public_html/
<Directory /home/example/public_html/>
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
allow from all
</Directory>
ErrorLog /var/log/apache2/error.log
LogLevel warn
CustomLog /var/log/apache2/access.log combined
</VirtualHost>
SuexecUserGroup simply tells suEXEC as what user and group it should execute things.
suEXEC
No site-specific configuration is necessary for suEXEC.
FastCGI
Now we will create the site-specific PHP wrapper. First, create a subfolder of /home/www-data/ for the site (in this case, /home/www-data/example/), then copy /home/www-data/php5-fcgi into it and chown the folder and the script to your new user.
Conclusion
At this point, it should be safe to enable the new site and restart Apache (or reload, if you restarted at any point after enabling the new modules). If you’d like to make sure PHP scripts now run as your new user, you can use this PHP script:
PHP:
<?php system('whoami'); ?>