Setting up a secure web server

Hi folks.

Today, we are going to set up a secure web server, based on a 12.04 Ubuntu. The aim of this tutorial is to create a secured production sever on which you can deploy a PHP website with a mysql database. I’m writing such a tutorial because I needed desperately it and couldn’t find one. As I’m not a specialist, there may be a few flaws, but keep in mind that I use, among others, recommendations from the NSA.

Before we start: again, I’m not a specialist, what you’re about to read is a huge set of how-tos, compiled into a bigger one. If you have recommendations, then feel free to leave comments!

To do so, we will need:

Let’s go, step by step.

Install Virtual Box and create virtual machine.

We are going to create an average server, with these characteristics: 2Gb RAM, 2*250Gb RAID1 Hard Drive. This is a typical medium sized server for a small production site. Create a first disk, let’s name it DISK1 for the machine to boot. Once done, immediately create another one named DISK2, 250Gb too:

Use the tiny buttons to add a second disk. Now it should look like this:

In the “Network” section, choose “Adapter 1” and set it to “Bridged Adapter”. Connect it to whatever you want. I do this because when the server’s installation is over, we vill use is the same way we use a real server: remotely, using SSH.

Now start the machine. Assuming that we are creating a distant server, we are going to use exclusively command line.

Start the virtual machine, begin installation.

Select your desired language. Set keymap, select regular installation and go for it. I won’t detail basic steps, just do as you would do with any other Ubuntu System.

When asked for a machine name, let’s write “myserver”.

Create users

In this example, our main user will be “foo” and his password “bar”. Note that this is a stupid password that SHOULD NEVER BE USER IN REAL LIFE, this is done on purpose for this tutorial. In a real life environment, you may use something like “1d!$*}4erf&@5§g%e%fez12″…

Partitioning: RAID1+LVM

When asked “What haz I to do wiz yer hardz diskz?”, select manual mode. No matter how you partition your drives, just keep in mind that they must be both EXACTLY THE SAME.

Create a 1Gb partition (this one will contain the kernel, it has to be bootable), a 4Gb (swap) one and a third one with the rest (actual datas). Use RAID each time. You should end up with something like this:

Now select “Configure software RAID”.What we are going to do is associate each partition with its mirror. Select “Create multidisk”, “RAID1”.  You will have to specify the number of active and spare devices. In this example we will have 2 active devices and 0 spare. On this screen, you will have to associate each partition with its mirror: sda1 with sdb1, sda2 with sdb2 and so on.

Go ahead and do it 3 times. You should end up with this:

Select first RAID (the 1Gb one), create /boot, format with ext4. Select second RAID (4Gb one), create swap. Select third RAID (260Gb one), create on / and format with LVM. Phew! You should get this:

At last, we’re done!…Actually, not yet! We still have to create Logical Volumes! This will create “logical partitions”, a very useful way to manage partitions on-the-fly. So select “Configure Logical Volume Manager”. Select “Create new group”, name it “vg00” (vg zero zero). Let’s use /dev/md2 as the partition to use.

now, we are finally going to create the actual partitions! Back to the disk partitioning screen, select “Configure LVM” again and, this time, “Create logical volume”. About the partitions, here’s the NSA recommendations:

  • separate volume for /tmp, 10Gb
  • separate volume for /var, 10Gb
  • separate volume for /var/log, a few Gb
  • separate volume for /var/log/audit, a few Gb
  • separate volume for /home if you plan on using it.

Really, the size of the partition’s up to you. There is no precise recommendations. I personnaly use this scheme:

  • / 10GB
  • /usr 30GB
  • /var 160GB
  • /tmp 10GB
  • /home (what’s left)

All datas fit into /var (websites, databases, services…), and it keeps a bit of space for /home. This is the scheme I’ll use here:

Back to the main partitioning menu, format each partition with ext4 to its respective mount point. don’t forget our RAID n°0 partition, it should be mounted on /boot. Same for RAID n°1, it should be used as swap. This should be the final configuration:

That’s it, we’re done! Let the assistant format, aggregate, install, compute the mass of the universe…At this time, I think you deserve a cup of coffee 😉

Rest of the install process

When asked for update, select “Automatically install security updates”. This will help you keep your system up do date.

Next, the installer may ask you which packages you want to install, choose OpenSSH and LAMP Server. A secure server is a minimal one, so install only what’s necessary.

When asked for MySQL root password, let’s use “mysqlroot”. Here again, dumb password.

Wait peacefully for installation process to end. Once the server has restarted, let’s…

Update packages!

On login, you will often see something like:

This means “time for updates, buddy!”. When it’s the case, use these two commands:


The first one updates packages list, the second one upgrades outdated ones.

SSH to the server

Now, for the rest of this tutorial, we’re going to leave the server running and access it exclusively by SSH. Try ssh foo@your_server_ip, it should work like a charm. Next step, secure Apache!


Apache basic security tips

Apache2’s configuration relies on a few important files:

  • apache2.conf : root configuration file. It’s used to load all the other conf files.
  • envvars: contains Apache’s environment vars
  • httpd.conf: empty, provides retrocompatibility to Apache
  • mods-available: a folder containing numerous .conf/.load files, one pair for every module Apache2 can load.
  • mods-enabled: contains links to the enabled mod’s .conf/.load files.
  • ports.conf: contains the ports Apache2 should listen to, such as port 80.
  • sites-available: folder containing infos files, one for each website Apache2 should  handle.
  • sites-enabled: as with mods-enabled, this folder contains links to the enables sites.
A small set of commands are provided to help:
  • a2ensite: enables a site (ie: creates a logical link in sites-enabled, pointing to a conf file in sites-availables).
  • a2dissite: disables a site (ie: removes a previously created link).
  • a2enmod: enables a mod (I think you got it, no?)
  • a2dismod: disables a mod (still not?)

Step 1: restrict information leakage

To edit apache’s configuration, use:

There you go. First thing to do, restrict information leakage. Here is an example. Open a web brower, type “http://your_server_ip”. You should get something like:

If not, then you might have missed something 😉

Now, try “http://your_server_ip/index.php”, or any page that doesn’t exist yet. This is what you will get:

Here the leakage I’m talking about. Using this popular trick, a hacker know what Apache version is used (2.2.22) and on which kind of server!

To avoid this, simply add these two lines at the end of the apache2.conf file:

Save the file, then restart Apache using this:

Now refresh the page you displayed, you should get this:

Step 2: restrict acces to unuseful conf files

Search for this line:

and disable it:

 As httpd.conf is a legacy of Apache1 and remains for backward compatiblity, disable it if possible.

Step 3: restrict directories

Apache’s root directory must always have the most restrictive configuration enabled: