How to build the ultimate Ubuntu/Lighttpd/PHP/MySQL server, and keep it running

How to build the ultimate Ubuntu/Lighttpd/PHP/MySQL server, and keep it running

for those who want to skip to a topic directlyCreate a new user and secure SSH access [page 1]Add some basic aliases to speed up things [page 2]Learn how 'free -m' works [page 2]Update OS, install essential applications [page 2]Install and configure Lighttpd [page 3]Install and configure PHP 5 [page 3]Install and secure MySQL [page 4]Google mail, and get php(mail) working [page 4]Configure IPTables (firewall) [page 5]Speed up your sites performance with etags [page 5]

This is going to be a very long post. Read it thoroughly, it’s very detailed and you can mess things up easily if you forget certain steps, which forces you to start over again.

If you don’t understand something, read it again. If you still don’t understand it, post a comment and I will do my best to explain it. Also DO post a comment if you want to say thank you, I really appreciate it!

OK, fasten your seatbelts and get some coffee. Here we go:

Setup your server or VPS, I won’t go into how hardware or how to install Ubuntu in this guide. If you have a VPS, you can select a Linux distribution in the control panel most of the times, and it will be installed for you automatically. In this guide we’ll use Ubuntu Hardy 8.04, since it’s very stable, and has a very large user community, and long term support.

Create a new user and secure SSH access

Connect to your server via SSH. To do this, you’ll need an SSH client. OS X users can use the built in Terminal application for this purpose. Windows user can use the free program ‘Putty‘.

To connect, type.

ssh root@

Don’t forget to change to your servers IP!

Each time you re-setup your server, the SSH remote host identification changes. If you get a message like “remote host identification has changed”, you need to edit the SSH known_hosts file on your *local*, home, not-server computer and remove any entries that point to your server’s IP address. On OSX, you can do this by typing in the terminal

nano ~/.ssh/known_hosts

or you could just delete the file

sudo rm ~/.ssh/known_hosts

Check if you are really using Ubuntu Hardy by typing

cat /etc/lsb-release

You should see the following


Do you see something else, think twice before you go on. I recommend you to use Ubuntu Hardy. If you have serious reasons for using something else though, you still can use most of this guide, only remember that you may have to modify some (if you use another Ubuntu version, or most if you use a completely different distro) of the commands.

You don’t want to use the root account. Add a new user

adduser ntux

Though you do want to do some things which need root to be done by the root user. To bypass this problem, give yourself ’sudo’ rights


Add this to the file (scroll to the last line with your arrow buttons, press ‘a’ and type the line you see below. Hit ESC and : (or SHIFT + ;), write wq and hit ENTER).

ntux   ALL=(ALL) ALL

After creating the new account, we don’t need to use the root account anymore. Though before you log out of the root session, make sure you change some permissions

nano /etc/ssh/sshd_config

You can tune this config file as you want, but since I don’t think you want to read all man pages, just edit these settings

Port 98765
Protocol 2
PermitRootLogin no
X11Forwarding no

You can press CTRL+W in Nano to search for the strings if you can’t find them. Change the port to a number that’s different from 22, though you still have to type it in often so don’t make it to hard. Append these settings to the end of the file. Of course you need to replace ‘ntux’ with the name of the user you added.

UseDNS no
AllowUsers ntux

In order to enable the setting you changed, you need to reload SSH (don’t logout! just enter the following command)

/etc/init.d/ssh reload

Still understand everything we did? In the last few steps you configured the server to only allow the user ntux to login to the server via SSH, which means that if you logout the root account now, you won’t be able to SSH back in with the root account (until you change the setting again, but that won’t be needed). You can safely close the current SSH connection, but if you want, you may also leave it open until the end of this tutorial. In either case, open a new terminal window (in OS X) and issue this command to connect via SSH with your new user

ssh -p 98765 ntux@

Don’t forget to change the port, username and server IP according to your own configuration.

Add some basic aliases to speed up things

Now you’re logged in, it’s time to add some aliases. These are short cut to command sequences. They are good because you will have to type some long commands many times in the next few weeks :). Type

nano ~/.bashrc

Scroll completely down, ignore all text you see. Add the following rules to the file.

alias free="free -m"
alias update="sudo aptitude update"
alias install="sudo aptitude install"
alias upgrade="sudo aptitude safe-upgrade"
alias remove="sudo aptitude remove"
alias l2r="sudo /etc/init.d/lighttpd restart"

Save the file and quit nano. Type

source ~/.bashrc

Now you reloaded the bashrc file, the commands are working! I’ll explain the first one now, the rest will be explained throughout the tutorial.

Learn how ‘free -m’ works

When you type ‘free’, the command ‘free -m’ will be executed. Do this now


To make things simple, only look at the ‘buffers/cache’ and ’swap’ lines, which shows something like

-/+ buffers/cache:       28       332
Swap:       511       0       511

This means that there is currently 28 MB memory used, and 332 free. No swap is used. A common mistake is to look at the first line and go out crying that all the available memory has been used. Don’t do this, ignore the first ‘Mem:’ line.

It’s a good thing to check the memory use from time to time, and learn from your servers response to configuration file changes.

Update OS, install essential applications

OK, well, we’re almost done setting up our workspace. We still need to update your system. Ubuntu uses a package manager to make updating easier. To use it, you first need to update the list of available packages

sudo aptitude update

You could also enter ‘update’, since we defined the alias in the bashrc file (scroll up and check it).

Before we actually upgrade your system, you need to define a locale. I recommend you to use a standard English locale. The English language won’t hurt you, and since most documentation is in English, you don’t have to translate menu options etc.

sudo locale-gen en_GB.UTF-8
sudo /usr/sbin/update-locale LANG=en_GB.UTF-8

Now update the system

sudo aptitude safe-upgrade

As the name suggest, the safe-upgrade is safe, though this doesn’t mean that the full-upgrade is unsafe. There’s also a full-upgrade, if you want you can run it after the safe-upgrade. If you are curious about the differences, more info about safe and full-upgrade is in the Ubuntu documentation. You don’t need to do it, so if you don’t want to read the manual, just go on with the guide here.

After upgrading all packages, you’ll need some basic things

sudo aptitude install build-essential

It’s also a good thing to install wget, sooner or later you’ll need it anyways and it’s very small

sudo aptitude install wget

Install and configure Lighttpd

Now we are going to install Lighttpd

sudo aptitude install lighttpd lighttpd-doc

Congrats, you now have a working Lighttpd server! We still need to configure some things though

nano /etc/lighttpd/lighttpd.conf

You can just use the default configuration, it’s quite good. Though you may want to change the site’s root directory on your server. I recommend the following layout:


Do not place subdomain directories in your main site’s root. If you do, it’s harder to password protect pages, since you have to protect both and (maybe you never want to do this – it’s still a good idea to learn using a simpler layout).

To use this layout, you have to change your servers root to ~/public_html/, and you have to setup some ‘vhosts’, which will point to the actual website directories. Of course you first need to create the directories (exit nano, by pressing CTRL+X, first of course)

sudo mkdir ~/public_html/
sudo mkdir ~/public_html/site1/
sudo mkdir ~/public_html/site1/www/
sudo mkdir ~/public_html/site1/subdomain1/

You can add as many sites and subdomains as you want. In order to enable a subdomain, you need to create a A/AAAA record in your domain names DNS settings. Set the hostname to the name of you subdomain, the IP address to your sites IP address and the TTL to default. You can also look at the ‘www’ record. www is also a subdomain, so you can use the same settings. It can take some time before the domains will start working, so don’t panic, and get some coffee.

We also create a directory for access and error logs

sudo mkdir ~/public_html/logs/

Now we’re going to edit Lighttpd’s config file

sudo nano /etc/lighttpd/lighttpd.conf

Scroll down all the way and add

$HTTP["host"] =~ "^(www\.)?site1\.com$" {
server.document-root = "/home/ntux/public_html/site1/www/"
server.errorlog = "/home/ntux/public_html/logs/site1_error.log"
accesslog.filename = "/home/ntux/public_html/logs/site1_access.log"
else $HTTP["host"] =~ "(^|\.)subdomain1\.site1\.com$" {
server.document-root = "/home/ntux/public_html/site1/subdomain1/"
server.errorlog = "/home/ntux/public_html/logs/site1_error.log"
accesslog.filename = "/home/ntux/public_html/logs/site1_access.log"

Now press CTRL+X to quit Nano, of course you need to overwrite the file with your new settings. Want to see if everything is working? Create a small html file and restart Lighttpd

sudo echo "Hi!" >> ~/public_html/site1/www/index.html

As you see, because we assigned the alias, you can just type ‘l2r’ to restart Lighttpd, instead of ’sudo /etc/init.d/lighttpd restart’!

Now surf to your website and check if it’s working! If it’s not working, check if you didn’t forget a step, and if your domain name’s DNS is pointing towards your server.

Install and configure PHP 5

The server can only display static files now. We need to install and configure PHP in order to display dynamic PHP files

sudo apt-get install php5-cgi
sudo nano /etc/php5/cgi/php.ini

Add the following line to the php.ini file

cgi.fix_pathinfo = 1

Now edit your Lighttpd config file again

nano /etc/lighttpd/lighttpd.conf

Add the following to the list at the top (server.modules), or uncomment it


And add the following lines just above the vhost lines you’ve added in previous steps

fastcgi.server = ( ".php" => ((
"bin-path" => "/path/to/php-cgi",
"socket" => "/tmp/php.socket"

Restart Lighttpd and PHP will be working! We’ll create a basis php(info) file to check if it’s working

echo "<?PHP phpinfo(); ?>" >> \

Remember that by typing l2r we restart Lighttpd. If you didn’t set the alias, you have to type “sudo /etc/init.d/lighttpd restart”
Now surf to You’ll see the PHP configuration!

It looks quite basic at the moment. It’s possible that you need to install some PHP modules to get your application working, rfer to your applications documentation for this. Most of the times, the installation of a module is very easy. For example, if you want the GD Graphics Library (which is needed to dynamically generate images, like those CAPTCHA’s on forums), you can install it by simply typing

sudo apt-get install php5-gd

On the next page I’ll show you how to add MySQL support.

Install and secure MySQL

We’re going to install MySQL now. Follow the steps on your screen during the installation and configuration

sudo aptitude install php5-mysql
sudo aptitude install mysql-server mysql-client
sudo aptitude install libmysqlclient15-dev

As always, we have to restart Lighttpd after installing something new. Type l2r if you’ve set the alias, or “sudo /etc/init.d/lighttpd restart” if you didn’t. We don’t want to install a MySQL frontend, since the command line interface is great. You don’t have to do this now, just remember the steps, you’ll need them when you want to setup a forum or blog system, or anything that uses a MySQL database.

mysql -u root -p

That command logs you in to the MySQL console. The following commands will commands will create a new user and database. By writing quit you’ll log out the console. Don’t forget the ; !

>  GRANT ALL PRIVILEGES ON *.* TO 'ME'@'localhost'
> create database DBASE;
> quit

Nice, you now have a working Lighttpd server with PHP 5 and MySQL. You still need some things though, like e-mail.

Setup Google mail and het php(mail) working

Let’s deal with email directly. Since we are going to build a light server, you don’t want to run a full blown postfix mail server. Sign up for Google Apps for Domain. There’s a paid and free ad supported version. The ad supported version won’t display ads in your mails, it’s about exactly the same as gmail. It’ll give you free mail storage, similar to GMail. The only difference is that you can change the logo’s and get some extra features! Follow the on screen instructions to setup the email. You need to add some MX Records in the DNS settings of your domain name and have to create a file on the server (you can do this the same way as we have done before, with the echo command). When you’ve done this, the email function will be working!

You won’t be able to use php(mail) though. Since I think you do want to use it (to recieve updates when someone posts a comment on your wordpress blog for example), we’re going to setup a light sendmail server: msmtp.

sudo apt-get install msmtp msmtp-mta
mkdir -p ~/.certs
chmod 0700 ~/.certs
cd ~/.certs
wget --no-check-certificate
cp Thawte\ Server\ Roots/ThawtePremiumServerCA_b64.txt ThawtePremiumServerCA.crt
touch /etc/msmtprc
nano /etc/msmtprc

Paste the following lines in the config file. Make sure you replace account, domain with your Google Apps acount and your domain name. Also take a look at the tls_trust_file line, you need to correct it if you placed the file in a different directory, which you did if you use a different username (replace ntux with your username in that case).

account default
port 587
timeout 30
auth on
password PASSWORD
auto_from off
tls on
tls_starttls on
tls_trust_file /home/ntux/etc/.certs/ThawtePremiumServerCA.crt

Now we’re going to change a line in php.ini

sudo nano /etc/php5/cgi/php.ini
sendmail_path = /usr/bin/msmtp -t -i

Search for the sendmail line with CTRL+W if you can’t find it. Make sure you uncomment (remove the ; ) it.

Restart Lighttpd and PHP(mail) will be working!


Securing the server with a firewall

OK, everything is working now! Don’t start hosting your sites though, first you need a firewall running on your server!

sudo apt-get install iptables

I recommend you to read the manual page (enter man iptables) and learn how IPTables works. If you don’t want to do that, you can still use an online generator though. Let’s use that for now, just make sure to read the man page some day.

First create some rules! Go to and read everything there.

// UPDATE: The site seems down now. Please use in the meantime. It’s maybe even better than the original link I posted. Make sure you choose “Allow Inbound Services” and “Specify a custom port range”, insert your SSH port there and declick the SSH option. Big chance that you also have to choose “Static IP” and fill in your servers IP address.

You should only need to allow http traffic and add your SSH port to the “Extra TCP/IP” port. Hit “Download ‘iptables-restore’ file” at the bottom of the page when you’re done. After generating the rules, you’ll see a page with a lot of text, this it great. Select everything and hit CTRL/CMD+C (copy everything). Go back to you SSH window. Enter

sudo nano /etc/iptables.test.rules

Paste the rules in this file (with right mouse button). Hit CTRL+X to exit nano, save you changes. Now enter

sudo iptables-restore < /etc/iptables.test.rules
iptables -L

With the last command you can review your rules. If you like them, we’re going to save them

sudo iptables-save > /etc/iptables.up.rules

Your server has a firewall running now! One problem though, it’ll be down when you restart the server. To solve this problem, do the following

sudo nano /etc/network/interfaces

Add the following line right after ‘iface lo inet loopback’

auto lo
iface lo inet loopback
pre-up iptables-restore < /etc/iptables.up.rules
# The primary network interface

You now have a fully working and secure webserver, ready to host your sites. I recommend you to read on though. I’ll give some instructions about optimizing the servers performance.

Add etags to enhanche the sites performance

Open the Lighttpd config file again

sudo nano /etc/lighttpd/lighttpd.conf

And uncomment the following module at the top of the file

server.modules = (

Scroll to a nice place in the config file, I recommend just above the vhosts, and add the following code

$HTTP["url"] =~ "(css|js|png|jpg|ico|gif)$" {
 expire.url = ( "" => "access 7 days" )
etag.use-inode = "enable"
etag.use-mtime = "enable"
etag.use-size = "enable"
static-file.etags = "enable"

This caches all css, js, png, jpg, ico and gif files.

OK, that’s it for now folks. I’ll update the guide asap with more info. if you want to see something special, just leave a comment and maybe I’ll add it!

Also, maybe a good idea to subscribe to my twitter, I’ll post some great server/website related tips there from time to time!