Building EC2 Amazon Linux with LAMP

This guide provides full instructions in building a LAMP stack on an Amazon Linux EC2 instance. Besides software installation & configuration, it includes steps on setting up storage, auto-start, security configuration and performance enhancement

For developers looking for a CentOS 5 AMI, Amazon Linux provides one of the best CentOS implementation

Building Amazon EC2 with Amazon Linux AMI (CentOS 5 compatible)

  1. Login to the AWS Management Console
    • Go to the aws.amazon.com
    • Select AWS Management Console under "My Account/Console"
    • Select the Amazon EC2 tag
  2. Create a new Amazon Linux Instance
    • Under Getting Started, select Launch Instance
    • Select Classic Wizard for fine-grained control
    • Select Basic 64-bit Amazon Linux AMI in Quick Start
    • Select your preferred Instance Type & Availability Zone
      Use micro for experimental purpose or larger instance for production system
      Put servers requiring fast inter-node communication into the same availability zone
    • Select Enable CloudWatch (if needed for system monitoring) and select "Prevent against accidental termination"
    • Enter the name for this instance, this serves as the label for the instance
    • Key Pair
      • Use an existing Key Pair OR
      • Create a new Key Pair & save the downloaded key to a secure location
    • Security Group
      • Select an existing Security Group OR
      • Create a new Security Group
        • Add the following rule (Replace the SSH IP with machine(s) that need to access the servers)
          TCP Port (Service)	Source
          80  (HTTP)	        0.0.0.0/0
          443 (HTTPS)	        0.0.0.0/0
          22  (SSH)	        99.1.1.1/32
    • Review the information and then launch the new EC2 instance
  3. Create a new Elastic IP if none is available
    • In the left panel, select Elastic IPs
    • Allocate New Adress
      Select EIP used in "EC2"
  4. Right click on the elastic IP and associate it to the new instance
  5. The new instance will be accessible with the elastic IP address

Access Amazon EC2 instance in Windows using Putty

  1. Download Puttygen from
    http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

    Download the Puttygen (not the putty)

  2. Run the puttygen executable
    1. In puttygen, click load
    2. Next to the File name box, select All Files
    3. Pick the server key pair generated and saved in previous step
    4. Click Save private key
  3. Access EC2 Instance
    1. Download and run Putty
    2. Enter the EC2 instance elastic IP address
    3. Select Connection -> SSH -> Auth & click Browse
    4. Select the .ppk key just generated
    5. Click Open
  4. Login as ec2-user

Using SSH to access EC2

Alternatively, access Amazon EC2 with SSH

ssh -i c:/path/to/server.pem 10.10.10.10 -l ec2-user

Replace the IP address with your own elastic IP address

Copy files remotely using SSH with Amazon EC2

scp -pr -i c:/path/to/server.pem ec2-user@10.10.10.10:/tmp .

Update yum before Installing Software

  1. Putty to the new instance with the .ppk key
  2. Login as user "ec2-user"
    sudo yum update

Install MySQL on Amazon Linux

  1. Login as user "ec2-user" to install MySQL server
    sudo yum install mysql-server mysql

Setup EBS Storage for MySQL Data Storage and PHP

  1. Install XFS support
    sudo yum install xfsprogs 
    grep -q xfs /proc/filesystems || sudo modprobe xfs
  2. Create a EBS Volume in AWS Management Console
    1. Select Amazon EC2 -> Volumes
    2. Click Create Volume
    3. Size = The size you need
    4. Availability Zone = Use the same availability zone for all EC2 instances
  3. Attach the volume to the tool instance
    1. Select the new volume and click Attach Volume when the status change to "available"
    2. Name the device /dev/sdh
  4. Create and mount a file system

    We are using xfs file system for DB server
    sudo mkfs.xfs /dev/sdh
    sudo mkdir /mnt/data
    sudo mount /dev/sdh /mnt/data -o noatime
  5. Create the mount point upon server reboot
    sudo vi /etc/fstab
    /dev/sdh       /mnt/data   xfs    noatime 0       0

Making Data Directory for MySQL

sudo mkdir -p /mnt/data/mysql
sudo chown -R mysql.mysql /mnt/data/mysql

Change MySQL Configuration

  1. sudo vi /etc/my.cnf
  2. Change datadir location to
    [mysqld]
    datadir=/mnt/data/mysql
    ...
  3. Add MySQL Configuration
    [mysqld]
    ...
    skip-external-locking
    long_query_time=1
    slow_query_log
    slow_query_log_file=/var/log/log-slow-queries.log
    log-bin=mysql-bin
    server-id= 1
    ...
    
    [mysqld_safe]
    ...
    myisam_recover_options
    ...
  4. Configure MySQL buffer configuration

    The configuration below is only an example. Skip this step if you are not sure about your DB memory need.
    [mysqld]
    ...
    key_buffer_size = 128M
    max_allowed_packet = 3M
    table_open_cache = 64
    read_buffer_size = 2M
    read_rnd_buffer_size = 8M
    myisam_sort_buffer_size = 16M
    thread_cache_size = 8
    query_cache_size= 32M         
    thread_concurrency = 8
    innodb_buffer_pool_size = 128M
    innodb_log_file_size = 32M
    innodb_additional_mem_pool_size = 8M
    innodb_log_buffer_size = 4M
    ...

    The above setting MUST be changed according to your application memory requirement and your choice of storage engine

  5. Create slow query log
    sudo touch /var/log/log-slow-queries.log
    sudo chown mysql.mysql /var/log/log-slow-queries.log

MySQL Auto Start in EC2 Amazon Linux

sudo /sbin/chkconfig --levels 235 mysqld on
sudo service mysqld start

Secure MySQL

  • Login to MySQL
    mysql -u root
  • Change root password
    USE mysql
    SET PASSWORD FOR 'root'@'localhost' = PASSWORD('somesecret');
  • Remove anonymous user and account without password
    DELETE FROM user WHERE password = '';
    DELETE FROM user WHERE user.user= '';
  • Flush the privileges and drop test DB
    FLUSH PRIVILEGES;
    DROP DATABASE test;

Import DB data (if needed)

Create DB

mysql -u root -p
CREATE DATABASE mydb CHARACTER SET utf8;

Import Data

use mydb
source your_import_file.sql;

Install Apache & PHP Software

Install GCC, Apache and PHP

sudo yum install gcc
sudo yum install make
sudo yum install httpd mod_ssl
sudo yum install php

gcc may be needed to build some PHP extensions

Install PHP extension

Install common extensions required by other PHP extensions

sudo yum install php-devel php-pear
sudo yum install pcre-devel

Install APC on Amazon Linux

sudo yum install httpd-devel
sudo pecl install apc

Accept the default setting for APC when prompted

Enable Extension

sudo vi /etc/php.d/apc.ini
; Enable APC extension module
extension=apc.so

Other

To access MySQL server in PHP code

sudo yum install php-mysql

To access Graphics library in PHP code

sudo yum install php-gd

To add XML and DOM support

sudo yum install php-xml

To add localization support

sudo yum install php-mbstring

Add User

Add a new user owning the PHP source code

sudo useradd -d /mnt/data/myuser -g mygroup -s /bin/bash -m myuser

Change the name of the user and the group

Apache Configuration Changes

Making Apache configuration change: httpd.conf

Apache configuration file location in Amazon Linux

sudo vi /etc/httpd/conf/httpd.conf

Make performance and security change for the Apache

ServerTokens Prod

TraceEnable Off

KeepAlive On
MaxKeepAliveRequests 256
KeepAliveTimeout 10

User myuser
Group apache

<IfModule expires_module>
ExpiresActive on
ExpiresDefault "access plus 1 months"
</IfModule>

FileETag none

Soma parameters above require further tuning subject to the application design

Virtual Hosts Configuration Changes

sudo vi /etc/httpd/conf.d/vhosts.conf
NameVirtualHost 10.xx.xx.xx:80
  • For multiple virtual hosts
    <VirtualHost *:80>
        ServerName myserver.com
        ServerAlias www.myserver.com
        DocumentRoot /mnt/data/myuser
    </VirtualHost>

    Change the IP address

PHP Configuration Changes

php.ini Changes

sudo vi /etc/php.ini

Change security and memory configuration

expose_php = Off

memory_limit = 128M  

error_log = /var/log/php-error.log

date.timezone = "America/Los_Angeles"

Create PHP Error File

Create the PHP error files

sudo touch /var/log/php-error.log
sudo chown myuser.apache /var/log/php-error.log

Log Rotation

sudo vi /etc/logrotate.d/httpd
"/var/log/php-error.log" /var/log/httpd/*log {
    rotate 5
    size=10M
    missingok
    notifempty
    sharedscripts
    delaycompress
    postrotate
        service httpd restart > /dev/null || true
    endscript
}

Auto Start Apache in EC2 Amazon Linux

sudo /sbin/chkconfig --levels 235 httpd on
sudo service httpd start