Comprehensive Instructions to setup a LAMP stack plus Aegir 0.3RC1

You are viewing a wiki page. You are welcome to join the group and then edit it. Be bold!

As a weekend project I setup Aegir 0.3RC1 on a VPS (see the bottom of this page for links to VPS hosts).

I have to take my hat off to Adrian and the rest of the Aegir team - it's amazing. So I wanted to write up the installation procedure in a way that makes it as easy as possible for others to try out...

Setup the LAMP stack

The best route to setup the stack in the first place is to use an appliance from Turnkey Linux - they offer a LAMP stack which has much of the configuration done.
Download the appliance here: http://www.turnkeylinux.org/appliances/lamp

Follow though their setup instructions. Otherwise ensure you have a LAMP server setup with similar specifications - eg
Ubuntu 8.04 Hardy.

Configure the OS

Login to the server as root, and then follow these instructions to do the remaining configuration and some basic hardening for security...

Set locale

For me, this is en_GB, but set your choice of locale:

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

Not a security measure, but worth doing, especially before we do the upgrades etc.

Update and upgrade

sudo apt-get update 
sudo apt-get upgrade 

This is just an initial update/upgrade. On an ongoing basis, Turnkey linux is set to automatically install new OS updates. For info see this page:
http://www.turnkeylinux.org/docs/automatic-security-updates

Now add some basic things:

sudo apt-get install build-essential 
sudo apt-get install wget 
sudo apt-get install aptitude apt-utils
sudo apt-get install cvs subversion 
sudo apt-get install php5-cli php5-gd php-pear
sudo apt-get install openssh-server

We need a mail transfer agent for the server to communicate with the outside world...

sudo apt-get install postfix 

select the option 'internet site' when prompted.
More info on postfix is at:
https://help.ubuntu.com/8.04/serverguide/C/postfix.html
http://www.scalix.com/wiki/index.php?title=HowTos/Complete_Postfix
Sendmail can be used as well, but is regarded by some as less secure.

To configure postfix for using googlemail as the smtp server, use this:
http://prantran.blogspot.com/2007/01/getting-postfix-to-work-on-ubuntu-w...

Restrict access to root user

First, change the password
passwd
And make this a secure password. Record it somewhere safe.

Then add another user (this can be anything you like, I've set it as 'onlyme' here. Don't make it something obvious like 'admin'):
useradd onlyme

Then set the password for this user:
passwd onlyme
Make this a secure password, different from the root login

Grant this user sudo rights:
visudo

Use the arrow keys to go to the last line. Press 'a' to add a line. Type:
onlyme ALL=(ALL) ALL
Hit Esc. Type ':'. type 'wq' and hit ENTER.

Then we want to prevent the root user from being able to login directly:
sudo vim /etc/ssh/sshd_config

and set the settings in file to be as follows (don't remove any other existing settings, just change or add to make the following):

Port 9876
PermitRootLogin no
X11Forwarding no
UseDNS no
UsePAM yes
PasswordAuthentication yes
AllowUsers onlyme

Note that the Port setting is to change the SSH/SFTP port from 22. I've used 9876 to illustrate this, but you can choose something else. This port should then be set in the settings of your SFTP programme to access the server.

Then reload ssh
/etc/init.d/ssh reload

Now logout of your shell session and ftp programme. Try to login again as root. It shouldn't work.
Log in now using the new onlyme user and the onlyme password.
If you need to have root authority in the future, simply issue the su - command in a bash shell and enter the root password. It's just that you can't login directly as root.
Su - to the root user now.

Firewall

Install the iptables firewall (it may turn out to be there already, so this won't do anything)
sudo apt-get install iptables

Open ports should be kept to 80 and 443 (http and https) and 9876 (our custom SSH port) on the external network card. On the internal loopback 3306 also needs to be allowed for MySQL. On outbound allow only port 53 UDP (for DNS) and 80 TCP (for access to updates etc via HTTP). Close down other ports unless absolutely necessary. Set any firewall to drop packets rather than reject them.

Ubuntu has a layer ontop of iptables called UFW, making setting up a basic firewall easier, which we'll enable and configure...

sudo apt-get install ufw 
sudo ufw allow 80/tcp 
sudo ufw allow 443/tcp 
sudo ufw allow 9876/tcp 
sudo ufw logging on 
sudo ufw enable 
sudo ufw status 

This sets up a default deny (DROP) firewall for incoming connections, with all outbound connections allowed with connections tracking.

The ufw framework is capable of doing anything that iptables can do. This is achieved by using several sets of rules files, which are nothing more than iptables-restore compatible text files. Fine-tuning ufw and/or adding additional iptables commands not offered via the ufw command is a matter of editing various text files:
* /etc/default/ufw: high level configuration, such as default policies, IPv6 support and kernel modules to use
* /etc/ufw/before[6].rules: rules in these files are evaluated before any rules added via the ufw command
* /etc/ufw/after[6].rules: rules in these files are evaluated after any rules added via the ufw command

If you do edit any of the above files, activate the new settings with:

sudo ufw disable 
sudo ufw enable 

More Info on UFW:
https://help.ubuntu.com/8.04/serverguide/C/firewall.html
https://wiki.ubuntu.com/UbuntuFirewall

Configure Apache

Users and Groups

One of the first things to ensure is that Apache does not run as root because if Apache is cracked then an attacker could get control of the root account.

To test what user and group apache is running as, type:
ps auwwfx | grep apache
does the first column on the lines say 'www-data'? If so this section is okay, move on.

If it says 'root' you need to do the following:

Add the user and group:
groupadd www-data
useradd -g www-data www-data
vim /etc/apache2/envvars (that's env vars together)
In this file, set the APACHE_RUN_USER and GROUP to 'www-data'.

Do a reload to effect the change:
/etc/init.d/apache2 reload

Permission to serve files

sudo vim /etc/apache2/apache2.conf

Make sure the following are set:
ServerTokens Prod
ServerSignature Off

Do a reload to effect the change:
/etc/init.d/apache2 reload

Enable/Disable some Apache Modules

Some modules aren't needed, so we can disable them for performance and security:

a2dismod cgi 
a2dismod autoindex 

And some modules we'd like to enable.

a2enmod deflate
a2enmod rewrite
a2enmod vhost_alias

Now restart apache
/etc/init.d/apache2 restart

Advanced things to consider for the future:

Install mod_security (http://www.modsecurity.org/)
Install mod_chroot (http://core.segfault.pl/~hobbit/mod_chroot/)

Configure PHP

Get the path to sendmail

Issue the command:
postconf -d sendmail_path
Note down this path.

Edit PHP.ini

All changes need to be performed in both:
/etc/php5/apache2/php.ini
and
/etc/php5/cli/php.ini

Change the settings in these files to read as follows:

safe_mode = Off 
expose_php = Off 
memory_limit = 128m 
display_errors = Off 
log_errors = On 
error_log = /var/log/php/php.log  (or php_cli.log) 
sendmail_path = /usr/sbin/sendmail -t -i

where the sendmail_path is actually the path you noted down above, but keep the -t and -i switches.

Edit Apache/PHP settings

In /etc/apache2/mods-enabled/php5.conf add:
AddType application/x-httpd-php .inc .module .class

so it becomes something like:

<IfModule mod_php5.c> 
  AddType application/x-httpd-php .php .phtml .php3 
  AddType application/x-httpd-php .inc .module .class 
  AddType application/x-httpd-php-source .phps 
</IfModule>

the addition of these additional filetypes to be handled as php scripts means the code of those types of files can't be directly downloaded from webroot folders, revealing site code, passwords etc.

Setup log files

Then

mkdir /var/log/php 
touch /var/log/php/php.log 
touch /var/log/php/php_cli.log 
chown -R www-data:www-data /var/log/php 
chmod -R 0755 /var/log/php 

To make sure that the log files exist and can be written to.

Log files should then be checked regularly to look for problems!

Restart Apache

/etc/init.d/apache2 restart

Configure MySQL

Edit MySQL configuration file

sudo vim /etc/mysql/my.cnf

In the [mysqld] section add this:

set-variable=local-infile=0 

check that

user = mysql 

If this is not set then mysql is set to run as root which is dangerous. A new user needs to be setup, given limited privileges (inc access to the mysql directories) and then specified here. Ubuntu usually has this set by default.

Change Root password and username

Now type

mysql -u root -p 

It will prompt for a password, this is the original root password from when the server was setup, and will show in the vps control panel if setup via a vps image. In more basic settings you may just need to press return here.

We'll change this password now:

mysql> SET PASSWORD FOR root@localhost=PASSWORD('new_password'); 

make a note of this new password.

Now we're changing the 'root' username to 'onlyme' which makes it harder to do brute force dictionary attacks on the password:

mysql> use mysql; 
mysql> update user set user="onlyme" where user="root"; 
mysql> flush privileges; 

Check for crud

SHOW DATABASES;
On a clean install if there are any databases other than mysql or information_schema then delete them - eg test databases.

SHOW GRANTS;
This will show which users have which permissions on the system. Get rid of defaults, demo users etc.

Type exit to log out of mysql.

Remove History

Now we remove the content of the mysql history file in which all executed SQL commands are stored inc passwords in plain text.

cat /dev/null > ~/.mysql_history 

Installing Aegir

Ladies and Gentlemen, it's time for tonight's main attraction - Aegir 0.3RC1...

Other sources of help

There is a screencast here: http://www.developmentseed.org/blog/2009/may/20/aegir-scratch-installing....
Although it's for the previous version, it is worth watching before following the instructions below.

These instructions are for Aegir 0.3 RC1.

Basic documentation for this release is here: http://groups.drupal.org/aegir/0.3-RC1

and the readme.txt (slightly outdated) is here: http://cvs.drupal.org/viewvc.py/drupal/contributions/profiles/hostmaster...

The Aegir Group, for updated info is here: http://groups.drupal.org/aegir-hosting-system

Create a user for aegir to operate as

sudo adduser aegir --home /var/aegir && 
su - aegir 

This will create a new user, asking you to provide a password. Just press enter for anything else it asks you for. This will then log you in as a new user.
For those unfamiliar with shell use, after the && press return, and then type the next line and press return again.

Preparations

Setup CVS repository...

export CVSROOT=:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib 

cvs login 

Download Drush and Provision

cvs -z6 co -d drush -r DRUPAL-6--2-0 contributions/modules/drush 

mkdir ~/.drush 

cvs -z6 co -d .drush/provision -r DRUPAL-6--0-3-RC1 contributions/modules/provision 

At this point we need to gain superuser priveleges to execute the next few commands, so we logout of the aegir session...

logout 

chmod u+x /var/aegir/drush/drush  

ln -s /var/aegir/drush/drush /usr/bin/drush 

su - aegir

We're now back as the aegir user.

Test that the drush setup is working:

drush 

This should list all available drush commands. check that it includes the 'provision' commands. If this doesn't work as expected troubleshooting is needed... check the permissions of the directories and drush file. Try /var/aegir/drush/drush. If that works, then there's a problem with the symlink.

If all is working with drush, let's move on to the next step.

Setup Drupal codebase

We start by checking out the latest drupal 6 release (currently 6.13)...

cd /var 
export CVSROOT=:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal 
cvs login 
cvs co -d aegir/drupal-6.x -r DRUPAL-6-13 drupal 

Get Hostmaster install profile

cd aegir/drupal-6.x/profiles 
export CVSROOT=:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib  
cvs login 
cvs -z6 co -d hostmaster -r DRUPAL-6--0-3-RC1 contributions/profiles/hostmaster 
mkdir -p hostmaster/modules 
mkdir -p hostmaster/themes  
cvs -z6 co -d hostmaster/modules/hosting -r DRUPAL-6--0-3-RC1 contributions/modules/hosting 
cvs -z6 co -d hostmaster/themes/eldir -rDRUPAL-6--0-3-RC1 contributions/themes/eldir 
drush dl admin_menu --destination=/var/aegir/drupal-6.x/profiles/hostmaster/modules 

Configure Apache

Now we'll copy across a file template (with the filename changed from aegir.example.com to the domain name of our aegir install)...

mkdir -p ~/config/vhost.d 
cp hostmaster/apache2.conf.txt ~/config/vhost.d/aegir.example.com 

Edit this file as you wish, but you must ensure the servername, documentroot and directory are all correct for the codebase. So:
vim ~config/vhost.d/aegir.example.com

Next, we'll create some other useful directories...

mkdir /var/aegir/backups 
mkdir /var/aegir/platforms 
cp /var/aegir/drupal-6.x/sites/default/default.settings.php /var/aegir/drupal-6.x/sites/default/settings.php 
chmod 777 /var/aegir/drupal-6.x/sites/default/settings.php 
mkdir /var/aegir/drupal-6.x/sites/default/files 
chmod 777 /var/aegir/drupal-6.x/sites/default/files 
mkdir /var/aegir/drupal-6.x/sites/all/modules 
chmod 777 /var/aegir/drupal-6.x/sites/all/modules 
mkdir /var/aegir/drupal-6.x/sites/all/themes 
chmod 777 /var/aegir/drupal-6.x/sites/all/themes 

And then...
logout 

So we're now back as root. Next we add the aegir user to the www-data group.

sudo adduser aegir www-data 

Now we want to edit apache's main httpd.conf file
sudo vim /etc/apache2/httpd.conf 
To add the following line at the end:
Include /var/aegir/config/vhost.d/* 

Now we want to configure sudo to allow aegir user permission to restart apache:
sudo visudo 
Use the arrow keys to go to the last line. Press 'a' to add a line. Type:
aegir ALL=NOPASSWD: /usr/sbin/apache2ctl 
Hit Esc. Type ':'. type 'wq' and hit ENTER.

Configure MySQL

We'll now setup the necessary users and database in MySQL:

mysql -uonlyme -p 

mysql> CREATE DATABASE hostmaster 
mysql> GRANT ALL ON hostmaster.* TO 'hostmaster'@'localhost' IDENTIFIED BY 'password'; 
mysql> GRANT ALL PRIVILEGES ON *.* TO 'aegir'@'localhost' IDENTIFIED BY 'password'  WITH GRANT OPTION; 
mysql> exit 

Run the installer

First, restart apache:
sudo /etc/init.d/apache2 restart 
Then in a browser, go to http://aegir.example.com where you setup the aegir instance on DNS etc.

Hosting setup

Setup the database with the hostmaster details we setup earlier.

The setup will ask you to enter the path to drush.php. This is:
/var/aegir/drush/drush.php 

The configuration path is:
/var/aegir/config 

And the backup path is:
/var/aegir/backups 

We've already done the step of adding the line to httpd.conf.

On the Database page, enter the details for the aegir database user.

At some point during the install you'll be prompted to enter a drush command to run the hosting setup...

su - aegir 
cd /var/aegir/drupal-6.x 
/var/aegir/drush/drush.php hosting setup 

Configure Aegir

Aegir is now installed, and you can configure it with your preferred settings. Have a browse around. Read the wiki and other posts on here: http://groups.drupal.org/aegir-hosting-system to find out what you can do with it. Prepare to be excited (if you're a geek)!

Adding New Platforms

Platforms are the codebases that Aegir can build sites from, such as drupal-5.10, drupal-6.13, acquia-drupal etc. You can also add new platforms to the system as follows:

cd /var 
drush dl drupal-6.13 

or checkout the latest acquia code via subversion:


(including the '.' at the end)

or get something like the ProsePoint distro, by visiting their website at http://www.prosepoint.org, seeing what the download URL is, and calling it via wget:

wget http://launchpad.net/prosepoint/trunk/0.23/+download/prosepoint-0.23.tar...
tar -zxvf prosepoint-0.23.tar.gz 
rm prosepoint-0.23.tar.gz 

Or you could upload code via sftp.

I choose to store all codebases in the /var/aegir/platforms directory.

And then select 'create new content' and 'add platform' in Aegir.

Getting Support

Hopefully all is working well for you now. Remember that this is just a release candidate so there may be a few bugs to iron out. If you find one, the very first thing to do is visit the project pages of the main Aegir projects:
http://drupal.org/project/drush
http://drupal.org/project/provision
http://drupal.org/project/hostmaster
http://drupal.org/project/hosting
USE THE SEARCH BOX on the left hand side of the page to look for tickets that might relate to your issue. Otherwise click on the number of open issues to go to the issue page and browse for possible similar tickets.
Only when you cannot find a similar ticket should you open a new ticket - but read these guidelines first: http://groups.drupal.org/node/21890

VPS links

I use VPS.net myself, and am very pleased with it so far. They're based in both the UK and USA.
You can go to their webpage direct using: http://www.vps.net.
Or, if you wish, you can use this affiliate link, which means I'll earn some money from them, at no extra cost to you, if you end up being happy with them, and so staying with them for a while. If you do use it, thanks.

Other good VPS hosts I hear positive things about as well are:
http://www.linode.com
http://www.slicehost.com
But I don't have personal experience of them.

** Addendum from a reader (not the author of this fine document) on SSHD security & configuration

There are two schools of thought regarding changing the SSH port from the standard 22: The first says moving it to another port is more secure, because it’s not where the bad guys expect it to be. The other says that a port scan will reveal it anyhow, and thus may draw special attention from the bad guys. I personally fall into the latter camp.

Regardless, one way to harden any SSH system is to use public key encryption and completely disable the password-response challenge mechanism. Password-response is usually very weak, whereas public key is always strong. This allows passwordless connections, but you can still require a password entry on the client machine prior to connecting, if desired, by adding a password to the private key; this simply means a password will be required before the private key is used to authenticate, via public key, with the remote server. The password is not used to authenticate with the remote server. To disable password-response, add/change these lines (from those previously listed):

PasswordAuthentication no
GSSAPIAuthentication no
UsePAM no

Note: If you wish to allow root login, add:

PermitRootLogin without-password

otherwise set it to:
PermitRootLogin no

Also, if you have a fixed IP, you can further restrict access so connections are only accepted from only certain IP addresses:

AllowUsers 111.222.333.444 111.222.333.555

Note: The firewall could also be used to add stealth to the SSH port if all access is from fixed IP addresses.

Don’t forget to add the public key to ~/.ssh/authorized_keys for each account on the server you will be SSHing into. File permissions should be set to 0400 (i.e. only allow read by owner).