HowToSetupFastCgiIndividualPermissions » History » Revision 12
« Previous |
Revision 12/39
(diff)
| Next »
Anonymous, 2006-09-24 19:19
Typo
= Setup FastCGI and PHP with individual user permissions =
''First of all: please notice that this how-to is only a suggestion on how to do this, so please don't blame anybody if you prefer to do things differently, or get mad customers, or whatever....''
''Note: This only works on *nix like operating systems. I don't know how to do this on Windows.''
IntroductionRunning a website hosting service for individual users/customers requires some extra brain-work when you set up your web-server.
Basically, you give every user an individual (ordinary) user account on your web-server. The user then uploads her PHP script files to her own virtual host document root.
What we want to do, is to execute all PHP script files with the exact same user permissions as the user that manages the virtual host in question. If this is accomplished, you can be sure that none of your users will be able to browse through other users' PHP scripts.
Consider the following PHP script executed on a web-server without individual user permissions on PHP-scripts (please do not attempt to do this, since you might end up with the police knocking on your door!):
{{{
#!php
$filename = "/path_to_other_users_vhost_root/index.php";
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
fclose($handle);
echo $contents;
?>
}}}
This will read (and show) the source code of PHP script of some other user. The source code might contain passwords that gives access to that user's MySQL databases, or other interesting stuff. You could even make a PHP script that writes PHP script files to other user's virtual host directories!
This is the setup we want to get rid of!
What about PHP's built-in safe_modeI will not say any bad things about PHP here, and you could probably just use PHP's built-in ''safe_mode'' features. (See the [http://www.php.net/manual/en/features.safe-mode.php safe_mode documentation at php.net] for a detailed description.)
However, if you rely on your operating system's build-in user permissions, you will be better off. (You can even combine the two, if you're completely paranoid.)
= Installation =
We assume that you already have Lighttpd installed, and installed PHP with FastCGI support. ([http://trac.lighttpd.net/trac/wiki/TutorialLighttpdAndPHP How to install PHP with FastCGI support])
You need to log in as ''root'' to do this.
1. Add users to the operating system(This is only needed if you haven't added users yet.)
You must add a user account to the operating system for each user that you want to give separate user permissions, in order to deny access to other users' source code.
Let's assume that we need to create three users (fred, george, and ron):
{{{#!ShellExample
- useradd fred
- useradd george
- useradd ron
}}}
You need to add one user group for each user added above. To keep things simple, we just name the user groups similar:
{{{#!ShellExample
- groupadd fred
- groupadd george
- groupadd ron
}}}
Now you need to add users to each of these user groups. For each user group, there must be two members: the corresponding user and the lighttpd daemon user.
You configure the user groups by editing /etc/group with your favourite text editor.
The file must look something like this (group numbers may vary):
{{{
..... [lots of stuff above]
fred:x:441:fred,lighttpd
george:x:442:george,lighttpd
ron:x:443:ron,lighttpd
}}}
Let's assume that you want to keep all files associated with the web-server's virtual hosts under the directory ''/var/www''. (Of course you can choose another location, just make sure that the users created above have read and execute rights to the directory. (I.e. ''chmod 755 /var/www && chown root:root /var/www'').
3.1 Create server root directoryNow, create two directories: One for some start-up scripts that only ''root'' have access to, and another for all your virtual hosts:
{{{#!ShellExample
- cd /var/www
- mkdir fastcgi
- mkdir vhosts
- chown lighttpd:lighttpd *
- chmod 755 *
- ls -l /var/www
drwxr-xr-x 2 lighttpd lighttpd 4096 Feb 15 12:17 fastcgi
drwxr-xr-x 9 lighttpd lighttpd 4096 Feb 15 11:21 vhosts
}}}
Now create a directory for each virtual host in the directory ''/var/www/vhosts'', and set up appropriate user rights to them:
{{{#!ShellExample
- cd /var/www/vhosts
- mkdir fred-weasley.com
- mkdir george-weasley.com
- mkdir ron-weasley.com
- chown fred:fred fred-weasley.com
- chown george:george george-weasley.com
- chown ron:ron ron-weasley.com
- chmod 750 *
- ls -l /var/www/vhosts
drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred-weasley.com
drwxr-x--- 6 george george 4096 Feb 15 11:02 george-weasley.com
drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron-weasley.com
}}}
Now we have created three directories where the three users cannot see each others' files; however, the ''lighttpd'' daemon user can see it all.
3.3 Create directory structure for each virtual hostNow, we want to create the directory struture needed for each virtual host:
{{{#!ShellExample
- cd /var/www/vhosts/fred-weasley.com
- mkdir html
- mkdir includes (optional)
- mkdir logs
- chown fred:fred *
- chown lighttpd:fred logs
- chmod 750 *
- ls -l /var/www/vhosts/fred-weasley.com
drwxr-x--- 14 fred fred 4096 Feb 17 11:55 html
drwxr-x--- 2 fred fred 4096 Feb 15 12:05 includes
drwxr-x--- 2 lighttpd fred 4096 Feb 15 11:11 logs
}}}
'''You need to repeat this for each virtual host, replacing the user name 'fred' with the appropriate user name.'''
3.4 Create a FastCGI directory for each userNow we have to do all the fun stuff!
Now, go to the ''/var/www/fastcgi'' directory where we want to create a directory for each user. (When we're finished, these directories will hold the sockets to the FastCGI server processes):
{{{#!ShellExample
- cd /var/www/fastcgi
- mkdir fred
- mkdir george
- mkdir ron
- chown fred:fred fred
- chown george:george george
- chown ron:ron ron
- chmod 750 *
- ls -l /var/www/fastcgi
drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred
drwxr-x--- 6 george george 4096 Feb 15 11:02 george
drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron
}}}
(Note that the lighttpd user can read all directories, while the three users can only access their own directory.)
4. Create a FastCGI start-up script for each userCreate a directory that will hold all your FastCGI start-up scripts:
{{{#!ShellExample
- cd /var/www/fastcgi
- mkdir startup
- chmod 750 startup
- ls -l /var/www/fastcgi
drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred
drwxr-x--- 6 george george 4096 Feb 15 11:02 george
drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron
drwxr-x--- 6 root root 4096 Feb 15 11:23 startup
}}}
Now, go to the ''/var/www/fastcgi/startup'' directory, create a start-up script for ''fred'' (let's call it ''fred-startup.sh'', using your favourite text editor:
{{{
#!sh
#!/bin/bash
- ABSOLUTE path to the spawn-fcgi binary
SPAWNFCGI="/usr/bin/spawn-fcgi"
- ABSOLUTE path to the PHP binary
FCGIPROGRAM="/usr/bin/php-cgi"
- bind to tcp-port on localhost
FCGISOCKET="/var/www/fastcgi/fred/fred.socket"
- number of PHP childs to spawn
PHP_FCGI_CHILDREN=5
- number of request server by a single php-process until is will be restarted
PHP_FCGI_MAX_REQUESTS=1000
- IP adresses where PHP should access server connections from
FCGI_WEB_SERVER_ADDRS="127.0.0.1"
- allowed environment variables sperated by spaces
ALLOWED_ENV="PATH USER"
- if this script is run as root switch to the following user
USERID=fred
GROUPID=fred
- no config below this line
if test x$PHP_FCGI_CHILDREN = x; then
PHP_FCGI_CHILDREN=5
fi
export PHP_FCGI_MAX_REQUESTS
export FCGI_WEB_SERVER_ADDRS
export PHPRC
ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS PHPRC"
- copy the allowed environment variables
E=
for i in $ALLOWED_ENV; do
E="$E $i=${!i}"
done
- clean environment and set up a new one
env - $E $SPAWNFCGI -s $FCGISOCKET -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN
chmod 770 $FCGISOCKET
}}}
Please be careful with the paths, USERID and GROUPID.
You need to repeat the process and create a startup-script for each user in the ''/var/www/fastcgi/startup'' directory. (Just copy the file and replace FCGISOCKET, USERID and GROUPID with the correct values).
Remember to set execute permissions on all your startup-scripts:
{{{#!ShellExample
- cd /var/www/fastcgi/startup
- chmod 750 *
}}}
If you're uncertain about the location of your php.ini, just run the following command:
{{{
#!ShellExample
$ php-cgi -i | grep php.ini
}}}
Please check, that you have the following line in your php.ini:
{{{
cgi.fix_pathinfo=1
}}}
Now, fire up all your FastCGI server processes:
{{{#!ShellExample
- /var/www/fastcgi/startup/fred-startup.sh
spawn-fcgi.c.170: child spawned successfully: PID: xxxxx - /var/www/fastcgi/startup/george-startup.sh
spawn-fcgi.c.170: child spawned successfully: PID: xxxxx - /var/www/fastcgi/startup/ron-startup.sh
spawn-fcgi.c.170: child spawned successfully: PID: xxxxx
}}}
If you get any error messages, please re-check your startup-scripts and the permissions to the ''/var/www/fastcgi'' directory, including all user sub-directories.
7. Configure virtual hosts in the lighttpd serverEdit ''/etc/lighttpd.conf'' in your favourite text-editor:
{{{
.....[lots of configuration stuff above].....
$HTTP["host"] =~ "(^|\.)fred-weasley.com$" {
server.document-root = "/var/www/vhosts/fred-weasley.com/html"
server.errorlog = "/var/www/vhosts/fred-weasley.com/logs/error_log"
accesslog.filename = "/var/www/vhosts/fred-weasley.com/logs/access_log"
fastcgi.server = ( ".php" =>
(
( "socket" => "/var/www/fastcgi/fred/fred.socket",
"check-local" => "disable",
"broken-scriptfilename" => "enable"
)
)
)
}
$HTTP["host"] =~ "(^|\.)george-weasley.com$" {
server.document-root = "/var/www/vhosts/george-weasley.com/html"
server.errorlog = "/var/www/vhosts/george-weasley.com/logs/error_log"
accesslog.filename = "/var/www/vhosts/george-weasley.com/logs/access_log"
fastcgi.server = ( ".php" =>
(
( "socket" => "/var/www/fastcgi/george/george.socket",
"check-local" => "disable",
"broken-scriptfilename" => "enable"
)
)
)
}
$HTTP["host"] =~ "(^|\.)ron-weasley.com$" {
server.document-root = "/var/www/vhosts/ron-weasley.com/html"
server.errorlog = "/var/www/vhosts/ron-weasley.com/logs/error_log"
accesslog.filename = "/var/www/vhosts/ron-weasley.com/logs/access_log"
fastcgi.server = ( ".php" =>
(
( "socket" => "/var/www/fastcgi/ron/ron.socket",
"check-local" => "disable",
"broken-scriptfilename" => "enable"
)
)
)
}
}}}
''Please note the paths to the FastCGI sockets for each virtual host.''
8. Restart the lighttpd daemon processSimply run this command:
{{{#!ShellExample
- /etc/init.d/lighttpd restart
}}}
If you get any errors, please re-check your ''/etc/lighttpd.conf'' configuration file.
9. Hello World!Now, log in as the user ''fred'' and create a PHP script file in his virtual host (e.g. ''/var/www/vhosts/fred-weasley.com/html/index.php''):
{{{
#!php
echo "<h1>Hello World!</h1>";
echo "<p>Current User ID is: ". posix_getuid();
echo "<p>Current Group ID is: ". posix_getgid();
?>
}}}
Also, make sure to set the file permissions:
{{{#!ShellExample
- chown fred:fred /var/www/vhosts/fred-weasley.com/html/index.php
- chmod 640 /var/www/vhosts/fred-weasley.com/html/index.php
- ls -l /var/www/vhosts/fred-weasley.com/html
rw-r---- 1 fred fred 116 Jul 25 2004 index.php
}}}
Now fire up your web-browser and check the output of your PHP script. (Here: http://www.fred-weasley.com/index.php)
If everything went well, you will see an output showing the User ID of the user ''fred'', and the Group ID of the user group ''fred''. (You can see these IDs in the files ''/etc/passwd'' and ''/etc/group'').
10. Automatically start the FastCGI startup scriptsOptionally, you may also create a crontab entry to automatically execute the FastCGI startup scripts when your server boots.
Use the following command to edit your crontab:
{{{- crontab -e
}}}
Now add the following line:
{{{
@reboot for i in /var/www/fastcgi/startup/*.sh; do $i; done
}}}
And finally type ":x" to save and exit.
This crontab entry will execute all .sh files found in the /var/www/fastcgi/startup directory after the server has booted.
Congratulations! You now have a working fast server configuration with individual (separate) user rights.
Updated by Anonymous about 18 years ago · 12 revisions