Yesterday we installed Ubuntu, modified our apt-get sources and then installed Ruby, Rubygems and Rails. We even installed MySQL 5 (although I didn't mention much about it - I kinda snuck it in on one of the apt-get commands)! So, we are now ready to continue setting up our Ubuntu / Ruby on Rails / PHP webserver for everyday use and abuse.
The first thing we will want to do today is to install lighttpd, then we will install PHP5 - with cgi capabilities. So reopen your Konsole (if you closed it) and then type the following command:
sudo apt-get install lighttpd libfcgi-dev libfcgi-ruby1.8
Apt-get will quickly download and install lighty for you without much more than a thought. (i Love Apt-get!). Now we have our webserver, and we are almost ready to start configuring for all our hosting needs. But it would be nice to have PHP installed as well - PHP is a valuable asset for our server, so lets set it up.
sudo apt-get install php5-cgi php5-mysql php5-mysqli
Run this first with the -s option (place it before "install") to see what all will be installed. If you try to install the plain ole php5 package apt-get will also try to package apache with it. But if you just go with the php5-cgi package it doesnt try to add any unnecessary stuff.
Now its time to get down to the nitty gritty details of config files and directory setup. All of our applications (sites) will sit in the directory /var/www --- lighty will handle all the mapping, with just minimal help from us. So what do we do now? Lets enable 3 usefull lighttpd modules and then start configuring that lovely lighttpd config file. Do the following:
sudo /usr/sbin/lighty-enable-mod fastcgi
sudo /usr/sbin/lighty-enable-mod simple-vhost
sudo /usr/sbin/lighty-enable-mod auth
Now we have the three modules enabled, we need to make a couple adjustments in their config files. enter the following commands (one after the other):
-EDITED-
sudo nano /etc/lighttpd/conf-enabled/10-fastcgi.conf
sudo nano /etc/lighttpd/conf-enabled/10-simple-vhost.conf
And change your module config files to look something like this:
:module => "fastcgi"
:why? => "to handle both php and rails apps"
## FastCGI programs have the same functionality as CGI programs,
## but are considerably faster through lower interpreter startup
## time and socketed communication
##
## Documentation: /usr/share/doc/lighttpd-doc/fastcgi.txt.gz
## http://www.lighttpd.net/documentation/fastcgi.htmlserver.modules += ( "mod_fastcgi" )
## Start an FastCGI server for php4 (needs the php4-cgi package)
fastcgi.server = ( ".php" =>
((
"bin-path" => "/usr/bin/php5-cgi",
"socket" => "/tmp/php.socket",
"max-procs" => 2,
"idle-timeout" => 20,
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "4",
"PHP_FCGI_MAX_REQUESTS" => "10000"
),
"bin-copy-environment" => (
"PATH", "SHELL", "USER"
),
"broken-scriptfilename" => "enable"
))
)
:module => "simple-vhost"
:why? => "to easily handle multiple site / application hosting"
## Simple name-based virtual hosting
##
## Documentation: /usr/share/doc/lighttpd-doc/simple-vhost.txt
## http://www.lighttpd.net/documentation/simple-vhost.html
server.modules += ( "mod_simple_vhost" )
## The document root of a virtual host isdocument-root =
## simple-vhost.server-root + $HTTP["host"] + simple-vhost.document-root
simple-vhost.server-root = "/var/www/"
simple-vhost.document-root = "/public/"
## the default host if no host is sent
simple-vhost.default-host = "forthecode.com"
In simple-vhost file you will want to change the "simple-vhost.default-host" to the domain name of your main app. Of course, on my server "forthecode.com" will be the default for any requests that do not route correctly. So if anyone types in doesentexist.forthecode.com or something.forthecode.com lighty will route it to www.forthecode.com. Simple-vhost will also allow us to do minimum configuration on our server to enable additional sites (especially php!).
The fastcgi module we modified sets up the php.socket connections in the /tmp directory - and automatically maps all of our .php requests through these sockets. So, we have nothing more to config for the php sites - other than lighttpd itself!
Now let us modify our lighttpd config file:
sudo nano /etc/lighttpd/lighttpd.conf
# Debian lighttpd configuration file
##debug.log-file-not-found = "enable"
#debug.log-request-header = "enable"
#debug.log-response-header = "enable"
#debug.log-request-handling = "enable"############ Options you really have to take care of ####################
## modules to load
# mod_access, mod_accesslog and mod_alias are loaded by default
# all other module should only be loaded if neccesary
# - saves some time
# - saves memoryserver.modules = (
"mod_access",
"mod_alias",
"mod_accesslog",
"mod_rewrite",
"mod_redirect",
)## a static document-root, for virtual-hosting take look at the
## server.virtual-* options
server.document-root = "/var/www/"## where to send error-messages to
server.errorlog = "/var/log/lighttpd/error.log"## files to check for if .../ is requested
index-file.names = ( "index.php", "index.html",
"index.htm", "default.htm" )#### accesslog module
accesslog.filename = "/var/log/lighttpd/access.log"## deny access the file-extensions
#
# ~ is for backupfiles from vi, emacs, joe, ...
# .inc is often used for code includes which should in general not be part
# of the document-root
url.access-deny = ( "~", ".inc" )######### Options that are good to be but not neccesary to be changed #######
## to help the rc.scripts
server.pid-file = "/var/run/lighttpd.pid"## change uid to
(default: don't care)
server.username = "www-data"## change uid to
(default: don't care)
server.groupname = "www-data"#### handle Debian Policy Manual, Section 11.5. urls
#### and by default allow them only from localhost
## document-root =
## virtual-server-root + virtual-server-default-host + virtual-server-docroot or
## virtual-server-root + http-host + virtual-server-docroot
####################################NOTICE!!!!!!
#I DO TELL the app where the PHP socket is in this scenario. Why?
#PHP is by default the value for the config variable fastcgi.server
#(look above in the module for fastcgi - we define PHP there)
#since we set this domain up to host a rails app, we have to point
#lightty to the PHP socket if we want to process PHP too.
##################################NOTICE!!!!!!
#my main rails app, also resolves for localhost
#notice I do not put the Fully Qualified Domain Name!
$HTTP["host"] =~ "forthecode.com|localhost" {
#the most important config line - error-handler must be dispatch.fcgi!!!!!
server.error-handler-404 = "dispatch.fcgi"
fastcgi.server = (".fcgi" =>
("localhost" =>
("socket" => "/tmp/ftc.com",
"min-procs" => 2,
"max-procs" => 4,
#full path to dispatch.fcgi
"bin-path" => "/var/www/forthecode.com/public/dispatch.fcgi",
#set your rails environment!
"bin-environment" => ("RAILS_ENV" => "production")
)
),
".php" =>
("localhost" =>
("socket" => "/tmp/phpftc.sock",
"bin-path" => "/usr/bin/php5-cgi -c /etc/php5/cgi/php.ini",
"min-procs" => 1,
"max-procs" => 1,
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "8",
"PHP_FCGI_MAX_REQUESTS" => "10000"
),
"bin-copy-environment" => (
"PATH", "SHELL", "USER"
),
"broken-scriptfilename" => "enable"
)
)
)
}#my second rails app
$HTTP["host"] =~ "forthephoto.com" {
server.error-handler-404 = "dispatch.fcgi"
fastcgi.server = (".fcgi" =>
("localhost" =>
("socket" => "/tmp/ftp.com",
"min-procs" => 1,
"max-procs" => 2,
"bin-path" => "/var/www/forthephoto.com/public/dispatch.fcgi",
"bin-environment" => ("RAILS_ENV" => "production")
)
)
)
}#here is an example configured php site that uses .htaccess style authentication
##################################NOTICE!!!!!!
#I DO NOT tell the app where the socket is (ie, I do not define the
#fastcgi.server variable - it is already assumed to be PHP)
#, we already did that in the lighttpd module config for fastcgi
##################################NOTICE!!!!!!
#if I did not need password protection I would not need anything in my
#lighttpd config to resolve the php site (no configuration for standard php sites!)$HTTP["host"] =~ "protected.phpapp.net" {
auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/var/www/phpapp.net/.htpasswd"
auth.require = ("" => (
"method" => "basic",
"realm" => "admin",
"require" => "valid-user"
))
}#### external configuration files
## mimetype mapping
include_shell "/usr/share/lighttpd/create-mime.assign.pl"## load enabled configuration files,
## read /etc/lighttpd/conf-available/README first
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
As you can tell, I really cut out a lot of the fluff in the config file. Here is all you will need to successfully host multiple rails and php applications. So, before you ask questions on how all this is going to work, let us move on and come back to lighttpd in a few minutes.
It is now time to move over to our /var/www directory and setup a few application folders that will contain a few test domains. Of course, for these to properly work (other than your localhost domain), your DNS for each domain needs to point to your new Ubuntu server. So, lets do the following (replace the domain names with whatever your domains are, likewise you should do the same with the lighttpd config we modified above):
cd /var/www
sudo mkdir forthecode.com
sudo mkdir forthecode.com/public
sudo mkdir forthephoto.com
sudo mkdir forthephoto.com/public
sudo mkdir phpinfo
sudo mkdir phpinfo/public
sudo mkdir phpapp.net/
sudo mkdir phpapp.net/public
This will give us 4 (four) virtual domains for demonstrating the ease of setup. Forthecode.com is my main rails app, forthephoto.com is my secondary rails app, phpinfo hosts a php application, and phpapp.net (not a real site on my server!) hosts a password protected php application.
So now we need to move our rails apps into our newly created domain folders. If you develop locally this should not be much of a problem (or if you want to create a new one, go ahead and do "sudo rails mynewrailsapp". I, however, develop on another machine and will deploy and sometimes test on this live server. So I need to setup a ftp server that will allow me to access and update these directories, but first:
sudo chown -R www-data.www-data /var/www
That will give lighttpd and ftp server access to these directories without any problems. So, on to the FTP installation. Thanks to apt-get this will be nice and simple to get, then we can edit it to match my config file (i also cut out alot of the fluffy comments in this one):
sudo apt-get install vsftpd
sudo nano /etc/vsftpd.conf
# Example config file /etc/vsftpd.conf
#
# Run standalone? vsftpd can run either from an inetd or as a standalone
# daemon started from an initscript.
listen=YES
#
# Allow anonymous FTP? (Beware - allowed by default if you comment this out).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
local_enable=YES
#
# Uncomment this to enable any form of FTP write command.
write_enable=YES
# Activate directory messages - messages given to remote users when they
# go into a certain directory.
dirmessage_enable=YES
#
# Activate logging of uploads/downloads.
xferlog_enable=YES
#
# Make sure PORT transfer connections originate from port 20 (ftp-data).
connect_from_port_20=YES
# You may fully customise the login banner string:
ftpd_banner=Welcome to ForTheCode FTP service.
# Debian customization
#
# Some of vsftpd's settings don't fit the Debian filesystem layout by
# default. These settings are more Debian-friendly.
#
# This option should be the name of a directory which is empty. Also, the
# directory should not be writable by the ftp user. This directory is used
# as a secure chroot() jail at times vsftpd does not require filesystem
# access.
secure_chroot_dir=/var/run/vsftpd
#
# This string is the name of the PAM service vsftpd will use.
pam_service_name=vsftpd
#
# This option specifies the location of the RSA certificate to use for SSL
# encrypted connections.
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#
# This option specifies the location of the RSA key to use for SSL
# encrypted connections.
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
Great, now we have the ftp server configured, but what user should access and update our public files? Well in my case it was simple - have the www-data user modify the files, he already owns the /var/www/* directories. So, let us setup the password for that account to something very secure (just like all your user account passwords).
sudo passwd www-data
Now, I need to restart the FTP service then connect to the server with my ftp client and upload my project files.
sudo /etc/init.d/vsftpd restart
Great! - its ready, and now that the project files are all ftp'd to the server (2 rails apps, one in forthecode.com-- the other in forthephoto.com; 2 php apps, one in phpinfo/public -- the other in phpapp.net/public ) we can get to business.
Make certain that in your rails apps that your dispatch.fcgi files are executable (chmod 755) and that your database.yml files are configured for your server. Now, restart lighttpd to load up all the config changes we made earlier and to check for any errors.
sudo /etc/init.d/lighttpd restart
If we are lucky (or just plain good) we should see no errors out of lighty's startup sequence. Everything is now up and running for you to view. Go to your main rails app and everything should resolve (assuming you are trying to go to "domain.com" -- without the "www").
But what if you go to your sites via the FQDN (ie. www.forthephoto.com)?
At this point the only Fully Qualified Domain Name that resolves is your main app! *(the one configured as the default in mod simple-vhost)
Your secondary sites FQDN's do not resolve properly and instead route to your main app! (phpinfo, protected.phpapp.net, www.forthephoto.com)
What can I do to fix this?
I thought you would never ask! To get fully qualified domains to resolve to different directories, or to get additional subdomains to resolve to a particular directory--- all you need are links, symbolic links to be exact!
In my case I setup a subdomain to resolve to a different directory for my php app. To do this simply do the following:
sudo ln -s /var/www/forthecode.com www.forthecode.com
sudo ln -s /var/www/forthephoto.com www.forthephoto.com
sudo ln -s /var/www/phpinfo php.forthecode.com
sudo ln -s /var/www/phpapp.net protected.phpapp.net
ls -liah /var/www
The symbolic links simply direct requests for a particular subdomain to the proper account. If I just typed in http://forthephoto.com, lighty would know to look in the directory named "forthephoto.com" for the public folder. By adding the symbolic link for the "www" subdomain - we can tell lighty that the directory forthephoto.com is where to look for this subdomain's public folder. (makes sense right?)
The "ls /var/www" command now displays pretty blue symbolic links that connect the subdomains to their folders. But why don't we make these link point to the public folder inside their target directories?
Lighttpd's mod simple-vhost already maps the server root to /var/www/ --- and if you remember, the config also specifies that the document root is /public/
All we need to do is point lighty to the proper directory that contains the /public/ directory for the fully qualified domain name - mod simple-vhost then takes over
Don't worry, if you dont do it right, lighty will just redirect the visitor to your main site without any errors. Creating symbolic links is usefull if you need to setup multiple subdomains for the same site - and it is very easy to do!
Oh, wait what did I forget to cover - thats right, the apache style .htpasswd authentication. Well, we already setup a sample domain in the lighttpd config that requires authentication. So what does that .htpasswd file look like? No different than a standard apache .htpasswd file --- username:encrypted-password
Wow, that was a LOT of information to cover. And although I thought I would cover all this in 2 posts, I think I will extend the last portion to a seperate post. There is a lot of detail to cover, and I don't want to leave any necessary point out. So, I look forward to posting again very soon. The next post will cover installing and configuring Exim (our mail server which will allow our applications to email us!), CVS (our source code repository so we can collaborate with our fellow developers, or just version our own code), and finally wrap up any loose ends concerning additional gems and settings.
Until next time, happy coding \(^-^)/

Charles said:
A note concerning Directory listing in lighttpd:
The option below, if uncommented and enabled, will cause your rails app not to process. Why? Because the file-not-found error never occurs - so dispatch.fcgi doesn't get a chance to process anything. Instead lighty will just display the directory contents. So, in my case I had to keep this commented out - beside, I dont really need anyone looking through all my directories!
## virtual directory listings
2006-12-24 11:49:33 UTC#dir-listing.encoding = "utf-8"
#server.dir-listing = "enable"
Charles said:
As a note, I updated this article to clear up when you and where you should define ".php" as a fastcgi.server value.
When hosting both PHP and Rails apps on the same domain you have to define the PHP fastcgi.server as well as the Rails fastcgi.server in the same config variable declaration.
PHP is, by default, the fastcgi server. So, if your domain is only using PHP - then you do not have to config anything in the lightty configuration file (absolutely nothing!)
If you need Rails hosting on your domain, you have to define the fastcgi.server in the lighttpd.conf. This overwrites the default php fastcgi.server - and thus requires you to redefine PHP if you want to use it as well.
2006-12-26 17:48:23 UTCCharles said:
Another note - this one specifically concerning PHP... I should have included this package in the install - but dont worry, we can do it now:
sudo apt-get install php5-mcrypt
This will give you the mcrypt function capabilities for encrypting all that sensitive data. Be sure to restart lighttpd after you do this:
sudo /etc/init.d/lighttpd restart
2007-01-15 18:29:41 UTCCharles said:
Thanks Mark for pointing out my typo - you should edit the config files for the lightty enabled modules. They are located in /etc/lighttpd/mods-enabled/
I fixed the typo and hopefully no one else will get caught up on it.
2007-02-02 14:12:20 UTCCharles said:
Does my wii support ajax?
2007-02-13 23:55:58 UTCCharles said:
To enable GD image support for PHP run the following command any time after everything else is setup:
sudo apt-get install php5-gd
Then restart lighttpd!
2007-03-17 20:22:19 UTCArndtinho said:
Hello,
thanks for this really nice tutorial. My PHP- and Rails-Apps are running. The only thing: I can't edit the files in /var/www/. It's obvious to me why but how can I edit my files without the sudo-command?
Regards,
2007-05-16 10:25:41 UTCArndtinho
Charles said:
In my setup I edit all of my rails apps on my personal computer then FTP them to the development server.
Sounds like you are doing your work on your development server - which in this setup will either require you to log in as www-data user, or use the sudo command.
2007-05-31 15:16:14 UTC