Ubuntu 12.04 LTS LAMP Server Setup

This will go over getting an Ubuntu 12.04 LTS server up and running for production use. Note: This does not pretend to be an exhaustive resource, particularly around security. Additionally, if your environment is more complex (Separate DB servers, servers across data-centers, different access levels, etc), then your setup can and will vary.

Setup

This will install some basic packages, including php 5.4.

$ sudo apt-get update
$ sudo apt-get install -y vim	# Everyone likes vim, right?
$ sudo apt-get install -y build-essential
$ sudo apt-get install -y python-software-properties

# Run these 2 steps if you want php 5.4, rather than 5.3
$ sudo add-apt-repository ppa:ondrej/php5
$ sudo apt-get update

# Install the LAMP components
$ sudo apt-get install -y php5
$ sudo apt-get install -y apache2
$ sudo apt-get install -y libapache2-mod-php5
$ sudo apt-get install -y mysql-server
$ sudo apt-get install -y php5-mysql
$ sudo apt-get install -y php5-curl
$ sudo apt-get install -y php5-gd
$ sudo apt-get install -y php5-mcrypt

# Set your server name (Avoid error message on reload/restart of Apache)
$ echo 'ServerName localhost' | sudo tee /etc/apache2/httpd.conf

# Enable mod-rewrite
$ sudo a2enmod rewrite

Git

You may need Git on your server depending on your deployment strategy, or to support package managers such as Composer.

$ sudo apt-get install -y git-core

Composer

If you use Composer, you should also have it on your production server to pull in dependencies. Note: For production use, you should lock in your dependency version numbers. That way you won't get any surprises when you update composer packages on your live server.

# Install composer globally
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

Tweaks/Security

Here we'll make some light performance tweaks, and adjust some settings for security.

First, some providers allow root login via SSH. We want to turn that off. I suggest opening a new SSH connection immediately after creating a sudo user (in a separate Terminal session/window) before doing this, just in case you lock yourself out by accident.

If your provider gives you a login other than "root", then you likely have a sudo user already and can skip the step of creating a sudo user. However, you should still ensure that you cannot log in as root.

# Create a new sudo user
$ adduser mysudouser			# Create user
$ usermod -G sudo mysudouser	# Make user a sudo user (sudoer)

# (Log in and make sure this sudo user does indeed have the sudo permissiosn)

# Don't let root login in via ssh
$ sudo vim /etc/ssh/sshd_config	
> PermitRootLogin no 			# Change from yes
$ sudo reload ssh

I typically also create a user for deployment. This user will share the same primary group as apache (www-data), and so will be able to read/write the web-server files. This is not a sudo user.

# Deploy user
$ adduser mydeployuser
$ usermod -g www-data mydeployuser

Here are some performance tweaks for Apache. We'll decrease the timeout time, and allow more keep-alive requests.

# Apache tweaks
$ sudo vim /etc/apache2/apache2.conf
> Timeout 45							# Change from 300
> MaxKeepAliveRequests 200				# Change from 100

Here are security tweaks. We'll turn off how much information about the server is returned in the HTTP headers.

$ sudo nano /etc/apache2/conf.d/security
> ServerTokens Prod						# Change from 'OS' or any other
> ServerSignature Off					# Change from 'On'

These are general PHP settings to tweak. Bump up the file size for file uploads, but decrease how many can be uploaded at once. As a security tweak, also turn off the display of which PHP version is being used.

$ sudo nano /etc/php5/apache2/php.ini
> post_max_size = 8M					# Change to 8M
> upload_max_filesize = 8M				# Change from 2M
> max_file_uploads = 5					# Change from 20
> expose_php = off						# Change fron 'On'
$ sudo service apache2 restart

The directory /var/www is the main web-root. The following will give everything in the web root the Apache user and group. This way Apache and the 'deploy' user are the only ones who can read/write web files. Note: This makes use of group permissions. The following is saying "Users and Groups can read and write these files, but other users can only read them".

# Web-root permissions
$ sudo chown -R www-data:www-data /var/www # make sure same owner:group
$ sudo chmod -R go-rwx /var/www				# Remove all group/other permissions
$ sudo chmod -R g+rw /var/www				# Add group read/write
$ sudo chmod -R o+r /var/www				# Allow other to read only

Virtual Hosts

This is a command-line tool I created for generating a virtual host within Apache (Ubuntu specific). This will enable the use of .htaccess files and turn off index listings by default. It also sets up log files per virtual host.

# vhosts
$ curl https://gist.github.com/fideloper/2710970/raw/6b5fd9de45f75e613178d296e87f586ca5b61220/vhost.sh > /usr/local/bin/vhost
$ chmod guo+x /usr/local/bin/vhost
$ sudo vhost -h # See the available options

Firewall

This is exactly as per here. It will allow port 22 (or current ssh port), 80 and 443 (ssh, web traffic, ssl web traffic respectively). It also gives loopback access, important if your server is virtualized (chances are, it is).

# Run as root or use sudo
$ sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
$ sudo iptables -A INPUT -j DROP
$ sudo iptables -I INPUT 1 -i lo -j ACCEPT

# Install so firewalls are saved through restarts
$ sudo apt-get install -y iptables-persistent
$ sudo service iptables-persistent start

Add MySQL user

This will create a MySQL user for your application to use. Note the example below will grant all permissions. You should be as restrictive as possible, giving only what's necessary. In many instances, MySQL users will will be OK with simply having SELECT, UPDATE, DELETE, and INSERT privileges, but there are many more privileges to choose from. Additionally, any user who will be used to mysqldump will need the LOCK TABLES privilege.

Also note that if you have a MySQL database on a separate server, you'll need to change localhost to the IP or host name of the server connecting to the database. There is also some more work to allow remote connections on MySQL (Editing my.cnf bind-address and using firewalls to only allow MySQL connections on the same local network is one strategy).

$ mysql -u root -p
> CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
> GRANT ALL PRIVILEGES ON database.* TO 'user'@'localhost';

Add SSL

If you need to install an SSL certificate, this has worked for me when installing a (non-premium) SSL. This assumes a 1-year SSL, with 2048 encryption. YMMV.

$ sudo a2enmod ssl    # Enable loading of SSL module
$ sudo service apache2 restart
$ sudo mkdir /etc/apache2/ssl 
$ cd /etc/apache2/ssl
# Change the domain from "yourdomain.com" to what you need
$ sudo openssl req -new -days 365 -nodes -newkey rsa:2048 -keyout yourdomain.com.key -out yourdomain.com.csr
$ sudo chmod 400 yourdomain.com.key
… add csr, get key back
$ sudo vim /etc/apache2/sites-available/your_vhost.conf
> SSLEngine on
> SSLCertificateFile /etc/apache2/ssl/yourdomain.com.crt
> SSLCertificateKeyFile /etc/apache2/ssl/yourdomain.com.key
> SSLCertificateChainFile /etc/apache2/ssl/sf_bundle.crt

And that's it - These steps will get you started on having a usable Ubuntu 12.04 server.