Set php.ini directives for each site - php

I have multiple sites running on Apache2 and PHP on Ubuntu Server. I know PHP has a php.ini file that lets you set values for upload_max_filesize, max_file_uploads , upload_tmp_dir etc. But that applies one value to all sites.
How can set directives for each site? For Eg: I'd like to set upload_max_filesize to 50M for sitea.com and upload_max_filesize to 5M for siteb.com.
Similarly, I'd like to set unique a session.name for each sites. How can this be done? I read there's something called PHP_INI_USER, PHP_INI_PERDIR, PHP_INI_SYSTEM, PHP_INI_ALL, so how can I do this?

You can use .htaccess files per site (or even per-folder) to set PHP configuration values - at least for most settings: if you look in the configuration directives documentation, for every setting that is marked as either PHP_INI_PERDIR or PHP_INI_ALL you can set these in a .htaccess file using the php_value or php_flag commands as documented in PHP's "How to change configuration settings" document.
For example to set upload_max_filesize in a website, create a .htaccess file at the document root of that website and put in it the text:
php_value upload_max_filesize 24M
Unfortunately, max_file_uploads and upload_tmp_dir are settings marked as PHP_INI_SYSTEM and you cannot change them in a .htaccess file...

How can set directives for each site? For Eg: I'd like to set upload_max_filesize to 50M for sitea.com and upload_max_filesize to 5M for siteb.com.
The comment by Mike 'Pomax' Kamermans explicitly states how this should be done. However PHP manual documentation can be a little off-putting.
Also some clarifiers re the other answers here:
Using a PHP parser file (as described by Lajos Arpad) adds some security risks and a pile of coding, syntax and some processing overhead that really isn't needed.
.htaccess does work for setting custom ini directives for some PHP installations but if you're using "FastCGI" or "CGI" (and possibly suPHP) PHP installations then this will infact crash your website with a 500 error, so instead use a local .user.ini file as described here. How do I find out my SAPI?
ONLY if you are running PHP as an Apache module (eg mod_php), use .htaccess. How do I find out my SAPI?
PHP suPHP/FastCGI/CGI SAPI
So, how should your aspiration be completed?
1) Look up the Core PHP.ini details.
Read your PHP.ini file for your current version of PHP.
Around line 180 (for PHP 8.1) it should say something like this:
;==================;
; php.ini Options ;
;==================;
; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini"
user_ini.filename = ".account-php81.ini"
Make a note of this value and I would suggest customising this value (as shown in this example). This value is the file name of the file which will sit in each unique account on the server, holding the account specific "local" settings for the global PHP.ini file.
The file typically sits in the public_html folder so should begin with a . so as to set as hidden by default (see more about this later on). If the file doesn't exist an an account no core PHP settings are changed.
2) Remember/Set the Filename and Create the New Rules
So you now know/ have set the name for your custom PHP file; now generate the file in your account and you can then set the PHP.ini settings you want to customise for this account alone.
For example;
file: /home/sitea.com_account/public_html/.account-php81.ini
Would contain the following example information:
;
; Some optional comment text here for human consumption
;
session.cookie_secure=1
session.save_path=/home/sitea.com_account/sessions
session.name=session-sitea
error_log=/home/sitea.com_account/errors/PHP_errors.log
upload_max_filesize=50M
This information is parsed by PHP and overwrites any corresponding values in the core PHP.ini but only for this account.
3) Customise for Each Account as Needed
For example, for your siteb.com php user ini file it would look more like this:
file: /home/siteb.com_account/public_html/.account-php81.ini
Would contain the following example information:
;
; Some optional comment text here for human consumption
;
session.cookie_secure=1
session.save_path=/home/siteb.com_account/session_b
session.name=site-b-UniqueSession
error_log=/home/siteb.com_account/errors/PHP_errors.log
upload_max_filesize=5M
You can then check that these account settings are set correctly by exploring phpinfo() on each account and noting the local and core differences as displayed.
4) Test And Confirm
The core user.ini file in the /public_html/ path should be all you need for every child file/folder on that account to process (This can sometimes depend on your exact LAMP server setup and your PHP handler).
As I say, once you've set a test ini file you should run phpinfo() to check its values are implemented.
If you don't want to use phpinfo() then you can just as easily use [ini_get](https://www.php.net/manual/en/function.ini-get) to dump sensitive data out to the error log rather than to the browser.
<?php
error_log("ini data for this account: ".ini_get('upload_max_filesize'));
exit;
5) Security
The user.ini file is typically started with a . character to hide it in the directory, but that doesn't make it untouchable by browser agents, therefore it's best practise to add a few lines to your .htaccess to deny access to this file.
<Files .account-php81.ini>
Require all denied
</Files>
Some Final Thoughts:
Core PHP.ini values do change in new versions of PHP and so this is why it's best practise to have different local .ini files for different PHP versions (.account-php80.ini, .account-php81.ini, etc.). Note that each php.ini core will need to explicitly call their respective local user.ini file, as referenced in step 1 above.
The principles of the above are outlined in the PHP Manual and it must be noted:
If you are running PHP as Apache module, use .htaccess files for the same effect.

Your settings are in php.ini indeed. Yet, if you have multiple sites to set, then you can set values inside the .htaccess file in the root of the site folder.
However, you can create a json file somewhere on your server, let's assume it's at /path/settings.json of the format of:
{
sitename1: {
setting1: value1
setting2: value2
},
sitename2: {
setting1: value3
setting2: value4
}
}
Now, you can create a deploy.php file at all your sites that will run cat /path/settings.json via exec, like
if (exec('cat /path/settings/json', $output, $retval)) {
$currentSettings = json_decode($output, true)['mysitename'];
}
You will then have an array of key-value pairs that can be looped and the setting will be known, like:
$script = "";
foreach ($currentSettings as $key => $value) {
$script .= "ini_set('{$key}', '{$value}');\n";
}
and then save $script into a file, let's call it init.php for now. You require_once this file and then you can maintain a single json file and deploy it per site by running a single cli command. You can even create an sh file that runs all deployment commands so you will be able to deploy everything via a one-liner.

Related

Set php second configuration ( php.ini file )

I want to set my own (php2.ini) file, with just a few lines that must overwrite the first php.ini settings - only for those lines.
So I start looking on google and it seems like what I need is the parse_ini_file function.
Ok. Now, in index.php I have:
parse_ini_file("php2.ini");
phpinfo();
exit();
But those settings from php2.ini are not loaded...
Trying to see if the file php2.ini is read-it and it is, beacause if I set parse_ini_file("php2-not-exist.ini"), it tells me that the file cannot be found. So the file php2.ini is read, but the settings are not overwritten.
The php2.ini file has inside the next lines:
error_log = "errors.log"
display_errors = "0"
max_execution_time = "300"
upload_max_filesize = "60M"
post_max_size = "60M"
date.timezone = "Europe/Bucharest"
default_charset = "UTF-8"
mbstring.internal_encoding = "UTF-8"
mbstring.http_output = "UTF-8"
mbstring.encoding_translation = "On"
mbstring.func_overload = "6"
Trying to let this file with just one line like post_max_size = "60M", but still not overwriting the general php.ini settings.
What am I missing here?
I know that some settings can be setted only and only using the php.ini file configuration. So setting a second file with parse_ini_file witch is a function from php... something is not correct, because some servers doesn't allow you to edit the general php.ini file. So how can the php let you set a second php ini file if you don't have access to the general one ? I don't know if that has something to do with my problem. I'm just saying that maybe here is the problem.
Right now I'm using wamp with php 5.5.12. I just want when I upload my website up, to be all done. I know that some hosting servers lets you to have a second php.ini file that must be uploaded in public_html or whatever folder it is. This is why I want to set my php2.ini file. To have the website clean when I'll upload to hosting.
Thank you.
The php parse_ini_file() function reads an ini file into an associative array. It does not set them up as settings like the php.ini file.
There is not a convenience function to override the server settings like this. What you may want here are .user.ini (the leading dot is important) files:
Since PHP 5.3.0, PHP includes support for configuration INI files on a per-directory basis.
and:
In addition to the main php.ini file, PHP scans for INI files in each directory, starting with the directory of the requested PHP file, and working its way up to the current document root (as set in $_SERVER['DOCUMENT_ROOT']). In case the PHP file is outside the document root, only its directory is scanned.
For full documentation on that feature, take a look at http://php.net/manual/en/configuration.file.per-user.php.
Note that only a subset of settings can be changed here:
Only INI settings with the modes PHP_INI_PERDIR and PHP_INI_USER will be recognized in .user.ini-style INI files.

How to change php.ini on ibm bluemix

I want to use phpmyadmin by this git.
https://github.com/dmikusa-pivotal/cf-ex-phpmyadmin
but I have to change max_file_uploads in php.ini.
Any ideas how to solve this?
Sorry for my bad English.
PHP is quite flexible in how you configure it. There are several ways to change php.ini settings. Here's what I recommend for the PHP build pack.
The easiest way to change php.ini settings for a PHP application deployed to CF is to use PHP's per-directory settings.
To do this, you can just drop a file named .user.ini into the root of your PHP files. In the case of the PHPMyAdmin app you referenced, you'd put it in the htdocs directory, since this is where all the application files are installed. Set whatever options you need to adjust in that file.
Push your application to Cloud Foundry and it should pick up the new configuration options.
Side note, you can put the .user.ini file in other directories too, exactly where you put it depends on the scope of where you want the settings contained in that file to be applied. See the PHP docs for more details.
This option will work for any php.ini setting that's not marked as PHP_INI_SYSTEM.
If the setting you want to change is marked as PHP_INI_SYSTEM or if you want to change php.ini settings during staging (for example, to affect the options used by Composer) then you need to use this option.
First create the folder .bp-config/php/conf.d in the root of your project. Then add a file with the .ini extension into that directory, ex: my-settings.ini (side note, you can add multiple .ini files to this directory). Set whatever options you need to adjust in it.
Second set the environment variable PHP_INI_SCAN_DIR for for your application to .bp-config/php/conf.d. This will instruct PHP to look for additional INI configuration in the directory that we just created.
You can set the environment variable by running cf set-env app-name 'PHP_INI_SCAN_DIR' '.bp-config/php/conf.d' or by adding it to the env block of your manifest.yml file.
Push your application to Cloud Foundry and it should pick up the new configuration options.
The benefit of both of these approaches is that your .user.ini file only needs to set the options that you care about. The option that Alex mentioned in his answer will technically work, but if you do that you will override all of the default php.ini settings that are provided by the build pack.
There's two reasons I don't recommend overriding everything.
You now have the complete configuration file in your app and if we change anything in the build pack, your configuration will get out-of-sync and your app could fail to stage the next time you push it.
If you're not very careful you can break things. This is one of the most common things I see people doing with PHP apps that causes an application to fail, more specifically it causes the PHP extensions to not load which in turn causes the app fail.
Here is what you have to do:
1) First follow the instructions in the README to install PHPMyAdmin:
https://github.com/dmikusa-pivotal/cf-ex-phpmyadmin
2) In your application folder under .bp-config directory create a php sub-directory
3) Copy default php.ini to the php sub-directory. The default file is located here
4) Edit local php.ini and change max_file_uploads to 180
5) Push your application using cf command line
6) Check if max_file_uploads was properly updated:
# cf files <your app name> app/php/etc/php.ini | grep max_file_uploads
You can get more details here.

Overriding PHP.ini in a shared development environment

My development environment is shared with other developers of my startup and is setup on Rackspace. The php.ini file is located in /etc/ folder, and I believe this is a centralized location from where every other developer's dev environment setting is being configured from. I want to customize this php.ini file specifically for myself rather than having to do it in the /etc/ location.
Specifically I am setting up XDEBUG in my environment, some other developers don't want it, so I don't want to bug em :)
To do so, I scanned the Internet on how to override the php.ini file specifically for a directory, and found this page on stackoverflow
And following that, I simply copy pasted the php.ini file within my htdocs folder and then simply echoed out phpinfo() (I echoed this in one of my Controllers, (using Zend)). The index.php file is within the htdocs folder.
When I look # "Loaded Configuration File", it still reads
/etc/ instead of ../htdocs/
Anybody know what's up?
In general, it isn't possible to load php.ini on a per directory basis, but in some special cases (CGI/FastCGI), it is: see documentation for Per-user configuration
Since PHP 5.3.0, PHP includes support for .htaccess-style INI files on a per-directory basis. These files are processed only by the CGI/FastCGI SAPI. This functionality obsoletes the PECL htscanner extension. If you are using Apache, use .htaccess files for the same effect.
In addition to the main php.ini file, PHP scans for INI files in each directory, starting with the directory of the requested PHP file, and working its way up to the current document root (as set in $_SERVER['DOCUMENT_ROOT']). In case the PHP file is outside the document root, only its directory is scanned.
If you are hosting several independent sites on one server, you should consider FastCGI anyway, to keep them separated. With php5-fpm it's very easy to setup many pools of workers.
Note that only set a limited subset of the ini-options in the user-ini-file.
As you said you don't have control on the server, the possible work-arounds would be to:
Use ini_set() to override the changes inside your script. Not all of the configuration directives can be changed using ini_set() though.
Use an .htaccess file in your directory to override the configurations in php.ini file.
(certain parts adapted from #1438393)
Hope this helps!
I'm not sure you understood the post. The post means if you run the server and want a per domain php.ini you can run the module as a per domain so each user controls there domain php.ini however it looks like your server does not offer this so you will need to us htaccess file to overwrite the php.ini settings.
By over write this doesn't mean you can change the directory this means maybe add a module or add error reporting ect...
You can do it by using this post: How can I use xdebug to debug only one virtual host?

What order does PHP read configuration from?

PHP configuration can be made in a number of different places:
php.ini
httpd.conf
.htaccess
within a php script via ini_set()
any more?
Some configuration settings can only be set in certain places and there's certain Apache and PHP settings that would prevent you from doing any PHP config changes in .htaccess or with your PHP script. But assuming that a given PHP setting can be set in all of the above places, in what order is this configuration read? In other words what overrides what? (I'm assuming that ini_set() overrides any of the previous settings).
There's compile-time settings before php.ini. The rest of the stages aren't really "configuration". They're more of a way to override settings established in a previous stage. PHP will quite happily run without any other config directives in php.ini/http.conf/.htaccess. php.ini does list (almost?) all the configuration settings available, but that's just a courtesy so you don't have to dig around in the docs to find the one setting you do want to override.
You named them in the correct order.
I don't recommend setting configuration in any other place than a php.ini though.
There are also per-directory php.ini configurations and I don't know which comes first, .htaccess or the directory php.ini but I would guess the .htaccess first and php.ini after.
Apache loads PHP, so Apache's config is read first. .htaccess is also handled by the webserver, so I'm guessing that will be second. Thirdly PHP is loaded. It checks for PHP.ini's in several locations. Also see here. Finally the ini_set is checked runtime.
First, You can use a user.ini file.
I think PHP will read it from the bigger to the smaller, I mean from httpd.conf -> php.ini (and then user.ini if set) -> .htacess -> ini_set()

Can php.ini settings be overridden in by a website using PHP + IIS6?

We have PHP 5.2.6 deployed to c:\php and in that folder there is the php.ini file. On Windows, can a website override these settings similar to the way that apache has .htaccess? e.g.
DirectoryIndex index.php index.html
<IfModule mod_php5.c>
php_flag magic_quotes_gpc off
php_flag register_globals off
</IfModule>
<IfModule mod_php4.c>
php_flag magic_quotes_gpc off
php_flag register_globals off
</IfModule>
Update:
I was aware of ini_set() but wondered if there was a declarative way to do this in a configuration file in the website rather than in script.
I would recommend doing all you can to avoid changing register_globals to on as it's a major security hole.
But you can try using init_set() to change the settings within your PHP code, although some settings cannot be changed once PHP has started running. (These are somewhat server dependent I believe.)
You can override the directives in the php.ini file several ways, but not all directives can be changed by each method. See the php.ini directives page in the manual for a list of the directives and the methods that will work on each one.
The last column in the table lists the methods that will work on that particular method. In increasing level of access:
PHP_INI_USER - Can be set in user
scripts with ini_set() (or any higher method)
PHP_INI_PERDIR - Can be set using
the .htacess file with php_value
for string values or php_flag for
binary values (or any higher method)
PHP_INI_SYSTEM - Can
be set using php.ini or httpd.conf
only (both require access to the server's configuration files)
PHP_INI_ALL - Can be set using
any of the above methods
ini_set should do what you're after -
$option = 'magic_quotes_gpc';
echo "Value of $option => ", ini_get($option);
ini_set($option,0);
echo "New value of $option => ", ini_get($option);
A caveat here is that just because you can set the value at run-time doesn't mean it will work as expected, e.g. setting register_globals at runtime will be of little use as that setting has already done it's job by the time your script starts.
From http://us.php.net/configuration.changes:
Changing PHP configuration via the Windows registry
When running PHP on Windows, the configuration values can be modified on a per-directory basis using the Windows registry. The configuration values are stored in the registry key HKLM\SOFTWARE\PHP\Per Directory Values, in the sub-keys corresponding to the path names. For example, configuration values for the directory c:\inetpub\wwwroot would be stored in the key HKLM\SOFTWARE\PHP\Per Directory Values\c\inetpub\wwwroot. The settings for the directory would be active for any script running from this directory or any subdirectory of it. The values under the key should have the name of the PHP configuration directive and the string value. PHP constants in the values are not parsed. However, only configuration values changeable in PHP_INI_USER can be set this way, PHP_INI_PERDIR values can not.
...Haven't actually tried this yet, so your mileage may vary.
I just found a new way of doing this.
First of all, I used phpinfo() to find the PHP.ini being used by my Hosting provider.
Thereafter, I uploaded a file containing the following code to my Hosting space:
$fsrc = fopen($pathToIni,'r');
$fdest = fopen($myHostingDir,'w+');
$len = stream_copy_to_stream($fsrc,$fdest);
fclose($fsrc);
fclose($fdest);
echo $len;
This effectively copied the php.ini to my Hosting space. Thereafter, I downloaded that php.ini, changed the register_globals to off (for which I did all this), and uploaded it to the root of my Hosting space. Bingo, there you go.
I have relied on the fact that IIS uses the complete php.ini if available in a directory. You cannot override only specific settings like that using .htaccess on Apache.
For cgi environments, there is a module called htscanner. It basically fakes .htaccess behavior and allows per directory configurations. Unfortunately I have no experience with this on Windows, let alone with IIS6.

Categories