最後更新: 2015-07-15


suEXEC is based on a setuid "wrapper" program that is called by the main Apache web server.

This wrapper is called when an HTTP request is made for a CGI or SSI program

that the administrator has designated to run as a userid other than that of the main server.

When such a request is made, Apache provides the suEXEC wrapper with the program's name and

the user and group IDs under which the program is to execute.


* suEXEC does not allow root to execute CGI/SSI programs.
* target userid/groupid  ABOVE the minimum ID number (AP_UID_MIN)
* target user/group the same as the program's user/group
* target program / directory NOT writable by anyone (所以 wrapper 既 permission 要係 755)
* Only one user (the Apache user) is allowed to execute this program. (AP_HTTPD_USER)
* safe hierarchical (AP_DOC_ROOT) (target CGI or SSI program's path 不可以有 a leading '/' or have a '..')



httpd -V | grep suexec

-D SUEXEC_BIN="/usr/sbin/suexec"    

The binary image suexec is installed in the directory defined by the --sbindir option.

(Default location is "/usr/local/apache2/bin/suexec")

在 httpd.conf 要有

LoadModule suexec_module modules/




suexec -V    # displays the compile options

 * For security reasons all configuration options are changeable only at compile time.

 -D AP_DOC_ROOT="/var/www"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_EXEC="/var/log/httpd/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

* suExec does not allow symlinks

不能用 FcgidWrapper /usr/bin/php-cgi .php          <-- 因為 CGI program 不在 AP_DOC_ROOT 內


Create a wrapper script for each web site in a subdirectory of /var/www;

the wrapper script will then call the PHP binary /usr/lib/cgi-bin/php

 * For security and efficiency reasons, all suEXEC requests must remain

within either a top-level document root for virtual host requests, or one top-level personal document root for userdir requests.




groupadd webuser1

useradd -s /bin/false -d /var/www/webuser1 -m -g web1 webuser1

mkdir -p /var/www/webuser1/web

# owner

chown webuser1:webuser1 /var/www/webuser1/web

# 放 CGI wrapper 的 Folder 都要有嚴格的 permission, 否則會有

[2014-07-23 14:59:40]: uid: (3334/???) gid: (3334/???) cmd: ???.sh
[2014-07-23 14:59:40]: target uid/gid (3334/3334) mismatch with directory (0/0) or program (3334/3334)

# 因為 .htaccess 要有 1

chmod 771 /var/www/webuser1/web

public_html 的 permission 要是 701


(13)Permission denied: /home/vhosts/???/public_html/.htaccess pcfg_openfile: 
unable to check htaccess file, ensure it is readable


Apache Configure



# Use FastCGI to process .fcg .fcgi & .fpl scripts
AddHandler fcgid-script fcg fcgi fpl

# Sane place to put sockets and shared memory file
FcgidIPCDir /run/mod_fcgid
FcgidProcessTableFile /run/mod_fcgid/fcgid_shm

# vhost example

<VirtualHost *>

    # suexe
    SuexecUserGroup user_account user_group

    # We run a single PHP FastCGI server
    # which will launch as many children
    # as necessary.

    <Directory ... >
      Options ... ExecCGI ...

    # fcgid
    FCGIWrapper /var/www/php-fcgi-scripts/suexec/webuser1/mywrapper .php
    AddHandler fcgid-script .php


# ispconfig example

<IfModule mod_fcgid.c>

  DocumentRoot    /var/www/ispconfig/
  SuexecUserGroup ispconfig ispconfig
  IPCCommTimeout  7200
  MaxRequestLen   15728640

  <Directory /var/www/ispconfig/>
    Options -Indexes +FollowSymLinks +MultiViews +ExecCGI
    AllowOverride AuthConfig Indexes Limit Options FileInfo
    <FilesMatch "\.php$">
        SetHandler fcgid-script
    FCGIWrapper /var/www/php-fcgi-scripts/ispconfig/.php-fcgi-starter .php
    Require all granted



export PHPRC
exec /usr/bin/php-cgi -d magic_quotes_gpc=off -d session.save_path=/usr/local/ispconfig/interface/temp




cd /var/www/php-fcgi-scripts/suexec

mkdir webuser1

chmod 755 webuser1

vi mywrapper

exec /usr/bin/php-cgi

chown user_account:user_group mywrapper

chmod 755 mywrapper


Configuring & Installing suEXEC


    enables the suEXEC feature

    # suexec binary will instead be installed with only the setuid/setgid "capability" bits
    # ( subset of full root priviliges )
    # Default: "setuid/setgid root" <-- full privileges of the root user

    The path to the suexec binary must be hard-coded in the server for security reasons.

    The username under which Apache normally runs. This is the only user allowed to execute this program.

    Define as the DocumentRoot set for Apache.

    Default: "/usr/local/bin:/usr/bin:/bin"

    processed by mod_userdir
    Define to be the subdirectory under users' home directories where suEXEC access should be allowed.
    All executables under this directory will be executable by suEXEC as the user so they should be "safe" programs.
    Default value is "public_html"

    Define a safe PATH environment to pass to CGI executables. Default value is "/usr/local/bin:/usr/bin:/bin".

    suEXEC wrapper will write log information to this file




    system("id -a");

# 沒有 suexec 時 uid=48(apache) "gid=48(apache) groups=48(apache)"


順利行到會見在 /var/log/httpd/suexec.log 內有

[2014-07-23 16:44:27]: uid: (3334/???) gid: (3334/???) cmd: wrapper

ps aux | grep 3334

3334     22663  0.0  0.2  58160 12228 ?        S    17:08   0:00 /usr/bin/php-cgi


Custom php.ini for Each Web Site


cp /etc/php5/cgi/php.ini /var/www/web1/

chown web1:web1 /var/www/web1/php.ini

vi /var/www/php-fcgi-scripts/web1/php-fcgi-starter

export PHP_INI_SCAN_DIR=/home/user/domain/conf
export PHPRC=/home/user/conf
exec /usr/lib/cgi-bin/php

reload php.ini:

killall php-cgi