Custom PHP.ini for ISPC3 with Suphp and FastCGI

Discussion in 'Tips/Tricks/Mods' started by ethanlifka, Mar 7, 2010.

  1. ethanlifka

    ethanlifka New Member

    This code creates custom php.ini files automatically when creating a new site using SuPHP or SuExec.

    Using ISPConfig 3.0.1.6, CentOS 5.4 Perfect Server Setup.

    Use at your own Risk

    Test on a Test Server before Production.
    I have not done any long term testing.

    Warning: any Problems may break you ISPC Configuration.

    Step #1

    Create a Custom php.ini master file.
    Code:
    # vi /usr/local/ispconfig/server/conf/php.ini.master
    
    Here's mine:
    Code:
    [PHP]
    engine = On
    zend.ze1_compatibility_mode = Off
    short_open_tag = On
    asp_tags = Off
    precision    =  14
    y2k_compliance = On
    output_buffering = 4096
    ;output_handler =
    zlib.output_compression = Off
    ;zlib.output_handler =
    implicit_flush = Off
    unserialize_callback_func=
    serialize_precision = 100
    allow_call_time_pass_reference = Off
    safe_mode = Off
    safe_mode_gid = Off
    safe_mode_include_dir =
    safe_mode_exec_dir =
    safe_mode_allowed_env_vars = PHP_
    safe_mode_protected_env_vars = LD_LIBRARY_PATH
    ;open_basedir =
    disable_functions = apache_note, apache_setenv, closelog, debugger_off, debugger_on, define_syslog_variables, escapeshellarg, escapeshellcmd, exec, ini_restore, openlog, passthru, pclose, pcntl_exec, popen, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, shell_exec, syslog, system, url_exec, get_defined_constants
    disable_classes =
    ;highlight.string  = #DD0000
    ;highlight.comment = #FF9900
    ;highlight.keyword = #007700
    ;highlight.bg      = #FFFFFF
    ;highlight.default = #0000BB
    ;highlight.html    = #000000
    ; ignore_user_abort = On
    ; realpath_cache_size=16k
    ; realpath_cache_ttl=120
    expose_php = On
    max_execution_time = 30
    max_input_time = 60
    memory_limit = 32M
    error_reporting = E_ALL & ~E_NOTICE
    display_errors = Off
    display_startup_errors = Off
    log_errors = On
    log_errors_max_len = 1024
    ignore_repeated_errors = Off
    ignore_repeated_source = Off
    report_memleaks = On
    track_errors = Off
    ;html_errors = Off
    ;docref_root = "/phpmanual/"
    ;docref_ext = .html
    ;error_prepend_string = "<font color=ff0000>"
    ;error_append_string = "</font>"
    ;error_log = filename
    ;error_log = syslog
    ;arg_separator.output = "&amp;"
    ;arg_separator.input = ";&"
    variables_order = "EGPCS"
    register_globals = Off
    register_long_arrays = Off
    register_argc_argv = Off
    auto_globals_jit = On
    post_max_size = 8M
    magic_quotes_gpc = Off
    magic_quotes_runtime = Off
    magic_quotes_sybase = Off
    auto_prepend_file =
    auto_append_file =
    default_mimetype = "text/html"
    ;default_charset = "iso-8859-1"
    ;always_populate_raw_post_data = On
    ;include_path = ".:/php/includes"
    doc_root =
    user_dir =
    extension_dir = "/usr/lib/php/modules"
    enable_dl = Off
    ; cgi.force_redirect = 1
    ; cgi.nph = 1
    ; cgi.redirect_status_env = ;
    ; fastcgi.impersonate = 1;
    ; fastcgi.log = 0
    ;cgi.rfc2616_headers = 0
    file_uploads = On
    upload_tmp_dir = "<tmpl_var name='document_root'>/tmp"
    upload_max_filesize = 10M
    allow_url_fopen = On
    ;from="john@doe.com"
    default_socket_timeout = 60
    [Date]
    ;date.timezone =
    [Syslog]
    define_syslog_variables  = Off
    [mail function]
    SMTP = localhost
    smtp_port = 25
    ;sendmail_from = me@example.com
    sendmail_path = /usr/sbin/sendmail -t -i
    ;mail.force_extra_parameters =
    [SQL]
    sql.safe_mode = Off
    [ODBC]
    ;odbc.default_db    =  Not yet implemented
    ;odbc.default_user  =  Not yet implemented
    ;odbc.default_pw    =  Not yet implemented
    odbc.allow_persistent = On
    odbc.check_persistent = On
    odbc.max_persistent = -1
    odbc.max_links = -1
    odbc.defaultlrl = 4096
    odbc.defaultbinmode = 1
    [MySQL]
    mysql.allow_persistent = On
    mysql.max_persistent = -1
    mysql.max_links = -1
    mysql.default_port =
    mysql.default_socket =
    mysql.default_host =
    mysql.default_user =
    mysql.default_password =
    mysql.connect_timeout = 60
    mysql.trace_mode = Off
    [MySQLi]
    mysqli.max_links = -1
    mysqli.default_port = 3306
    mysqli.default_socket =
    mysqli.default_host =
    mysqli.default_user =
    mysqli.default_pw =
    mysqli.reconnect = Off
    [mSQL]
    msql.allow_persistent = On
    msql.max_persistent = -1
    msql.max_links = -1
    [PostgresSQL]
    pgsql.allow_persistent = On
    pgsql.auto_reset_persistent = Off
    pgsql.max_persistent = -1
    pgsql.max_links = -1
    pgsql.ignore_notice = 0
    pgsql.log_notice = 0
    [Sybase]
    sybase.allow_persistent = On
    sybase.max_persistent = -1
    sybase.max_links = -1
    ;sybase.interface_file = "/usr/sybase/interfaces"
    sybase.min_error_severity = 10
    sybase.min_message_severity = 10
    sybase.compatability_mode = Off
    [Sybase-CT]
    sybct.allow_persistent = On
    sybct.max_persistent = -1
    sybct.max_links = -1
    sybct.min_server_severity = 10
    sybct.min_client_severity = 10
    [bcmath]
    bcmath.scale = 0
    [browscap]
    ;browscap = extra/browscap.ini
    [Informix]
    ifx.default_host =
    ifx.default_user =
    ifx.default_password =
    ifx.allow_persistent = On
    ifx.max_persistent = -1
    ifx.max_links = -1
    ifx.textasvarchar = 0
    ifx.byteasvarchar = 0
    ifx.charasvarchar = 0
    ifx.blobinfile = 0
    ifx.nullformat = 0
    [Session]
    session.save_handler = files
    ;session.save_path = "/var/lib/php/session"
    session.save_path = "<tmpl_var name='document_root'>/tmp"
    session.use_cookies = 1
    ;session.name = PHPSESSID
    session.name = sessxid
    session.auto_start = 0
    session.cookie_lifetime = 0
    session.cookie_path = /
    session.cookie_domain =
    session.serialize_handler = php
    session.gc_probability = 1
    session.gc_divisor     = 1000
    session.gc_maxlifetime = 1440
    session.bug_compat_42 = 0
    session.bug_compat_warn = 1
    session.referer_check =
    session.entropy_length = 0
    session.entropy_file =
    ;session.entropy_length = 16
    ;session.entropy_file = /dev/urandom
    session.cache_limiter = nocache
    session.cache_expire = 180
    session.use_trans_sid = 0
    session.hash_function = 0
    session.hash_bits_per_character = 5
    url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
    [MSSQL]
    mssql.allow_persistent = On
    mssql.max_persistent = -1
    mssql.max_links = -1
    mssql.min_error_severity = 10
    mssql.min_message_severity = 10
    mssql.compatability_mode = Off
    ;mssql.connect_timeout = 5
    ;mssql.timeout = 60
    ;mssql.textlimit = 4096
    ;mssql.textsize = 4096
    ;mssql.batchsize = 0
    ;mssql.datetimeconvert = On
    mssql.secure_connection = Off
    ;mssql.max_procs = -1
    ;mssql.charset = "ISO-8859-1"
    [Assertion]
    ;assert.active = On
    ;assert.warning = On
    ;assert.bail = Off
    ;assert.callback = 0
    ;assert.quiet_eval = 0
    [Verisign Payflow Pro]
    pfpro.defaulthost = "test-payflow.verisign.com"
    pfpro.defaultport = 443
    pfpro.defaulttimeout = 30
    ;pfpro.proxyaddress =
    ;pfpro.proxyport =
    ;pfpro.proxylogon =
    ;pfpro.proxypassword =
    [COM]
    ;com.typelib_file =
    ;com.allow_dcom = true
    ;com.autoregister_typelib = true
    ;com.autoregister_casesensitive = false
    ;com.autoregister_verbose = true
    [mbstring]
    ;mbstring.language = Japanese
    ;mbstring.internal_encoding = EUC-JP
    ;mbstring.http_input = auto
    ;mbstring.http_output = SJIS
    ;mbstring.encoding_translation = Off
    ;mbstring.detect_order = auto
    ;mbstring.substitute_character = none;
    ;mbstring.func_overload = 0
    ;mbstring.strict_encoding = Off
    [FrontBase]
    ;fbsql.allow_persistent = On
    ;fbsql.autocommit = On
    ;fbsql.default_database =
    ;fbsql.default_database_password =
    ;fbsql.default_host =
    ;fbsql.default_password =
    ;fbsql.default_user = "_SYSTEM"
    ;fbsql.generate_warnings = Off
    ;fbsql.max_connections = 128
    ;fbsql.max_links = 128
    ;fbsql.max_persistent = -1
    ;fbsql.max_results = 128
    ;fbsql.batchSize = 1000
    [gd]
    ;gd.jpeg_ignore_warning = 0
    [exif]
    ;exif.encode_unicode = ISO-8859-15
    ;exif.decode_unicode_motorola = UCS-2BE
    ;exif.decode_unicode_intel    = UCS-2LE
    ;exif.encode_jis =
    ;exif.decode_jis_motorola = JIS
    ;exif.decode_jis_intel    = JIS
    [Tidy]
    ;tidy.default_config = /usr/local/lib/php/default.tcfg
    tidy.clean_output = Off
    [soap]
    soap.wsdl_cache_enabled=1
    soap.wsdl_cache_dir="/tmp"
    soap.wsdl_cache_ttl=86400
    ; Local Variables:
    ; tab-width: 4
    ; End:
    cgi.fix_pathinfo = 1
    
    Warning: do not use the default from your /etc/php.ini

    There are some "<?" tags that will brake the file
    that's why mine is minified. Also for file size.

    Notice: "<tmpl_var name='document_root'>/tmp"
    for upload_tmp_dir and session.save_path

    also use your own disable_functions

    step #2

    Edit vhost.conf.master

    Code:
    # vi /usr/local/ispconfig/server/conf/vhost.conf.master
    
    Add "suPHP_ConfigPath <tmpl_var name='suphp_custom_path'>"

    Code:
    # suphp enabled
        <Directory {tmpl_var name='web_document_root'}>
            suPHP_Engine on
            suPHP_ConfigPath <tmpl_var name='suphp_custom_path'>
            # suPHP_UserGroup <tmpl_var name='system_user'> <tmpl_var name='system_group'>
            AddHandler x-httpd-suphp .php .php3 .php4 .php5
            suPHP_AddHandler x-httpd-suphp
        </Directory>
    
    Also to the SSL Section

    Code:
    <tmpl_if name='php' op='==' value='suphp'>
        suPHP_Engine on
        suPHP_ConfigPath <tmpl_var name='suphp_custom_path'>
        # suPHP_UserGroup <tmpl_var name='system_user'> <tmpl_var name='system_group'>
        AddHandler x-httpd-suphp .php .php3 .php4 .php5
        suPHP_AddHandler x-httpd-suphp
    </tmpl_if>
    
    Step #3

    Edit "apache2_plugin.inc.php"

    Code:
    # vi /usr/local/ispconfig/server/plugins-enabled/apache2_plugin.inc.php
    
    find the IF statement "if ($data["new"]["php"] == "fast-cgi")"

    around line 700.

    replace Entire IF Statement with:
    Code:
    if ($data["new"]["php"] == "fast-cgi")
    		{
    			$fastcgi_config = $app->getconf->get_server_config($conf["server_id"], 'fastcgi');
    			
    			$fastcgi_starter_path = str_replace("[system_user]",$data["new"]["system_user"],$fastcgi_config["fastcgi_starter_path"]);
    			$fastcgi_starter_path = str_replace("[client_id]",$client_id,$fastcgi_starter_path);
    			
    			if (!is_dir($fastcgi_starter_path))
    			{
    				exec("mkdir -p ".escapeshellcmd($fastcgi_starter_path));
    				//exec("chown ".$data["new"]["system_user"].":".$data["new"]["system_group"]." ".escapeshellcmd($fastcgi_starter_path));
    				
    				
    				$app->log("Creating fastcgi starter script directory: $fastcgi_starter_path",LOGLEVEL_DEBUG);
    			}
    			
    			exec("chown -R ".$data["new"]["system_user"].":".$data["new"]["system_group"]." ".escapeshellcmd($fastcgi_starter_path));
    			
    			if(!file_exists($fastcgi_starter_path."php.ini")){
    				// Custom php.ini
    				$phpini_tpl = new tpl();
    				$phpini_tpl->newTemplate("php.ini.master");
    				$phpini_tpl->setVar('document_root',$data["new"]["document_root"]);
    				$phpini_script = escapeshellcmd($fastcgi_starter_path."php.ini");
    				file_put_contents($phpini_script,$phpini_tpl->grab());
    				unset($phpini_tpl);
    				$app->log("Creating Custom php.ini file: $phpini_script",LOGLEVEL_DEBUG);
    				exec("chown ".$data["new"]["system_user"].":".$data["new"]["system_group"]." $phpini_script");
    			}
    			
    			// FastCGI Wrapper
    			$fcgi_tpl = new tpl();
    			$fcgi_tpl->newTemplate("php-fcgi-starter.master");
    			
    			
    				
    			if(file_exists($fastcgi_starter_path."php.ini")){
    				$fcgi_tpl->setVar('php_ini_path',str_replace("[system_user]",$data["new"]["system_user"],$fastcgi_config["fastcgi_phpini_path"]));
    				$fcgi_tpl->setVar('php_fcgi_bin',str_replace("[system_user]",$data["new"]["system_user"],$fastcgi_config["fastcgi_bin"])); // add " -c /var/www/php-fcgi-scripts/[system_user]/php.ini"
    			}else{
    				$fcgi_tpl->setVar('php_ini_path',"/etc/");
    				$fcgi_tpl->setVar('php_fcgi_bin',"/usr/bin/php-cgi");
    			}
    
    			$fcgi_tpl->setVar('document_root',$data["new"]["document_root"]);
    			$fcgi_tpl->setVar('php_fcgi_children',$fastcgi_config["fastcgi_children"]);
    			$fcgi_tpl->setVar('php_fcgi_max_requests',$fastcgi_config["fastcgi_max_requests"]);
    			$fcgi_tpl->setVar('security_level',$web_config["security_level"]);
    				
    			$fcgi_starter_script = escapeshellcmd($fastcgi_starter_path.$fastcgi_config["fastcgi_starter_script"]);
    			file_put_contents($fcgi_starter_script,$fcgi_tpl->grab());
    			unset($fcgi_tpl);
    			
    			$app->log("Creating fastcgi starter script: $fcgi_starter_script",LOGLEVEL_DEBUG);
    			
    			
    			exec("chmod 755 $fcgi_starter_script");
    			exec("chown ".$data["new"]["system_user"].":".$data["new"]["system_group"]." $fcgi_starter_script");
    
    			$tpl->setVar('fastcgi_alias',$fastcgi_config["fastcgi_alias"]);
    			$tpl->setVar('fastcgi_starter_path',$fastcgi_starter_path);
    			$tpl->setVar('fastcgi_starter_script',$fastcgi_config["fastcgi_starter_script"]);
    			
    		}
    		
    		 /**
    		 * suphp Config
    		 */
    
    		
    		if ($data["new"]["php"] == "suphp")
    		{
    			if (!is_dir("/var/www/php-suphp-scripts/"))
    			{
    				exec("mkdir -p ".escapeshellcmd("/var/www/php-suphp-scripts/"));
    				$app->log("Creating suphp custom script directory: /var/www/php-suphp-scripts/",LOGLEVEL_DEBUG);
    			}
    			
    			$suphp_custom_path = "/var/www/php-suphp-scripts/".$data["new"]["system_user"]."/";
    			
    			if (!is_dir($suphp_custom_path))
    			{
    				exec("mkdir -p ".escapeshellcmd($suphp_custom_path));
    				$app->log("Creating suphp custom script directory: $suphp_custom_path",LOGLEVEL_DEBUG);
    			}
    			
    			exec("chown -R ".$data["new"]["system_user"].":".$data["new"]["system_group"]." ".escapeshellcmd($suphp_custom_path));
    			
    			if(!file_exists($suphp_custom_path."php.ini")){
    				// Custom php.ini
    				$phpini_tpl = new tpl();
    				$phpini_tpl->newTemplate("php.ini.master");
    				$phpini_tpl->setVar('document_root',$data["new"]["document_root"]);
    				$phpini_script = escapeshellcmd($suphp_custom_path."php.ini");
    				file_put_contents($phpini_script,$phpini_tpl->grab());
    				unset($phpini_tpl);
    				$app->log("Creating Custom php.ini file: $phpini_script",LOGLEVEL_DEBUG);
    				exec("chown ".$data["new"]["system_user"].":".$data["new"]["system_group"]." $phpini_script");
    			}
    
    			if(file_exists($suphp_custom_path."php.ini")){
    				$tpl->setVar('suphp_custom_path',substr($suphp_custom_path,0,-1));
    			}else{
    				$tpl->setVar('suphp_custom_path',"/etc");
    			}
    			
    		}
    
    This will also add a new IF statement for suphp


    Last Step #4

    In your ISPC3 Admin go to:
    System -> Server Config
    Select the server to edit.
    then select "FastCGI"

    Edit these Fields:

    FastCGI starter path:
    /var/www/php-fcgi-scripts/[system_user]/

    FastCGI php.ini Path:
    /var/www/php-fcgi-scripts/[system_user]/

    FastCGI Bin:
    /usr/bin/php-cgi -c /var/www/php-fcgi-scripts/[system_user]/php.ini

    Save

    That should do it.

    Now Create or Edit a Site
    It might take a minute or to for the configuration to take effect.
    try logging out and back in.

    Now test you new site with phpinfo().
    see if you have disabled functions

    Let me know how it works.
     
    Last edited: Mar 7, 2010

Share This Page