I decided to change from Apache2 to Lighttpd after finally upgrading my old Lenny installations to Debian Squeeze. At the same time I finally got the time to write configuration scripts for virtual hosts.
My installation is based on Lighttpd running
PHP5 FastCGI with individual user permissions and due to security and management reasons. This is not to be considered as a tutorial, but as it is based on official help files it can be used to help you write your own scripts. I'm trying to adhere to standards so it could also be used as is.
If you need help installing the needed packages,
this tutorial might help.
So, my goal is to create a script which can be used to create the needed directories and config files to be used with Lighttpd. Everything I need to do when I want to add another virtualhost can be done with this script. Using scripts like this can turn day-to-day maintenance your Linux installations from constant pain to - uh - at least tolerable.
The only thing to remember when using this script is that you have to be in /var/www/vhosts -directory (or similar, please check the script)! You can't give it an absolute path as a parameter.
After installing the needed packages, be sure to turn on necessary modules:
# lighttpd-enable-mod fastcgi fastcgi-php Then we need a part of the code to be stored elsewhere (mostly due to escaping which I didn't want to do at this hour :)). In my script it is saved to /root/startup_file.sh, so if you save it elsewhere, please modify the script accordingly.
Save this into /root/startup_file.sh
if test x$PHP_FCGI_CHILDREN = x; then PHP_FCGI_CHILDREN=5fi export PHP_FCGI_MAX_REQUESTSexport FCGI_WEB_SERVER_ADDRS export PHPRCALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS PHPRC" # copy the allowed environment variablesE= for i in $ALLOWED_ENV; do E="$E $i=$(eval echo "\$$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 $FCGISOCKETThe actual script. I saved it to /sbin/www-create so that it is usable to root.
#!/bin/bash
## Create necessary directories and fix permissions ## $1 is domain $2 is user. Remember to adduser before running the script!## See usage at http://macoute.suursavo.org/ mkdir $1mkdir $1/html mkdir $1/includesmkdir $1/logs chown -R $2:$2 $1chown www-data:$2 $1/logs chmod 750 $1mkdir /var/www/fastcgi/$1 chown $2:$2 /var/www/fastcgi/$1chmod 750 /var/www/fastcgi/$1 ## Create startup-script for cgi echo "#!sh #!/bin/sh## 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/$1/$1.socket\"## uncomment the PHPRC line and the one after, if you want to have an extra php.ini for this user ## store your custom php.ini in /var/www/fastcgi/$2/php.ini## with an custom php.ini you can improve your security ## just set the open_basedir to the users webfolder## Example: (add this line in you custom php.ini) ## open_basedir = /var/www/vhosts/$2/html## #PHPRC=\"/var/www/fastcgi/$1/\"#chmod -R 750 \"/var/www/fastcgi/$1/\" ## number of PHP childs to spawn in addition to the default. Minimum of 2. ## Actual childs = PHP_FCGI_CHILDREN + 1## Debian default is 5. PHP_FCGI_CHILDREN=1## 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=$2GROUPID=$2 " > /tmp/beg_startup ## we need temporary files which we combine. After we fix permissions and actually run the startup-file. If you are not ## sure whether you want to allow PHP for every virtual host you might want to comment the last line and activate it per-site cat /root/startup_file.sh >> /tmp/beg_startupmv /tmp/beg_startup /var/www/fastcgi/startup/startup-$1.sh chmod 750 /var/www/fastcgi/startup/startup-$1.sh/var/www/fastcgi/startup/startup-$1.sh ## Last we need the lighttpd-config file for this site. It uses previously created directories and fastcgi-socket. echo "\$HTTP[\"host\"] =~ \"(^|\.)$1\$\" { server.document-root = \"/var/www/vhosts/$1/html\" accesslog.filename = \"/var/www/vhosts/$1/logs/access_log\" fastcgi.server = ( \".php\" => ( ( \"socket\" => \"/var/www/fastcgi/$1/$1.socket\", \"broken-scriptfilename\" => \"enable\" ) ) )} " > /etc/lighttpd/sites/$1.conf## And lastly, force-reload /etc/init.d/lighttpd force-reloadNow we should be done. Let's test our use case - creating a PHP-enabled site with user permissions and all the needed configs for Lighttpd. Remember, you have to be in a certain directory for the script to work.
# pwd/var/www/vhostNice, the correct directory.
# useradd exampleThe user who is going to own the vhost. This can be also (of course) one of your existing users. It should also be possible to use
www-data there, but it is against the idea of my script. It doesn't need to have a home directory (hence
useradd) but it can also be one of your normal users and you can later add a symbolic link to their home directory for the www-directories so that they can modify their files directly from their home directory.
# www-create example.com examplespawn-fcgi: child spawned successfully: PID: 11755 Reloading web server configuration: lighttpd.Voilá! We have a domain
example.com at service. You can verify that PHP is executed as the user (and not the default www-data) by a small php-file (save it to /var/www/vhosts/html/)
<?phpecho "<h1>Testing:</h1>"; echo "<p>Current UID is: ". posix_getuid();echo "<p>Current GID is: ". posix_getgid(); ?>Now, when you go to
example.com/index.php (with or without www, with this config it doesn't matter), you should get UID and GID greater than 1000 (if using Debian, that is).