Up and Running Fast With LAMP On AWS EC2

This tutorial covers setting up a LAMP stack on a free-tier EC2 instance.

Setting up and managing an Amazon Web Services EC2 server can be a pretty intimidating task the first time around since the process is so much different than other hosting services with little to no options for server configuration (here’s lookin’ at you Hostgator, and GoDaddy.) Worry not! It is not nearly as hard as it seems!

1) If you don’t have one already, create an Amazon account. Once you have created an account or signed in to an existing, you’ll hit the dashboard. This is where a lot of people may feel intimidated with the absolutely insane quantity of choices for web services. We’re just going to look at EC2 virtual server instances, and for most intents and purposes, this is going to be enough!

2) Select ‘EC2’ from the ‘Compute’ menu:

3) Select ‘Launch Instance,’ to create a new virtual server.

4) Select ‘Amazon Linux AMI …’ from the ‘Quick Start’ menu.

5) Select the ‘t2.micro’ server instance then click ‘Review and Launch.’

6) Select ‘Launch.’

7) A dialog will pop up that asks you to create or use an existing key pair for logging into your machine instance over SSH. Here you will want to create a new key pair and assign it a name that will help you identify which server or group it is if you plan to run multiple instances. For the purposes of this tutorial we’ll call it tutorial. Once this is complete and you have downloaded the file, click ‘launch.’ While we are setting up our public key for easy access on our local system,

8) Download and move your key file to somewhere safe that you will not forget! I keep all of my key files under my profile at ~/publickeys

9) Open a terminal window and navigate to the key file.

Tims-MBP:~ tim$ cd ~/publickeys/

10) Change the permission of the public key file so that it will be secure from other profiles on your machine.

Tims-MBP:publickeys tim$ chmod 0500 tutorial.pem

11) Grab your public DNS from the EC2 instances dashboard. We will use the public DNS to SSH into our new server instance using the public key we just downloaded.

12) Now in your terminal window, using your public key you can SSH into your server instance using the username ‘ec2-user’ and your public DNS.

Tims-MBP:publickeys tim$ ssh -i ~/publickeys/tutorial.pem ec2-user@ec2-99-999-999-9.us-west-2.compute.amazonaws.com

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2016.03-release-notes/
9 package(s) needed for security, out of 17 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-99-999-999-9 ~]$ 

13) Success! Now I noticed from the log-in prompt that linux is asking me to install some security updates, so first I will run yum update. This should take less than a minute.

[ec2-user@ip-99-999-999-9 ~]$ sudo yum update
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main/latest                                                      | 2.1 kB     00:00     
amzn-updates/latest                                                   | 2.3 kB     00:00     
Resolving Dependencies
--> Running transaction check
---> Package aws-cfn-bootstrap.noarch 0:1.4-10.5.amzn1 will be updated
---> Package aws-cfn-bootstrap.noarch 0:1.4-11.6.amzn1 will be an update
---> Package ca-certificates.noarch 0:2015.2.4-65.0.1.14.amzn1 will be updated
---> Package ca-certificates.noarch 0:2015.2.6-65.0.1.15.amzn1 will be an update
---> Package curl.x86_64 0:7.40.0-8.54.amzn1 will be updated
---> Package curl.x86_64 0:7.40.0-8.57.amzn1 will be an update
---> Package iputils.x86_64 0:20071127-17.11.amzn1 will be updated
---> Package iputils.x86_64 0:20121221-7.13.amzn1 will be an update
...

14) Using yum we can now install Apache, MySQL and PHP. This may take a minute or two.

[ec2-user@ip-99-999-999-9 ~]$ sudo yum install -y httpd24 php56 mysql56-server php56-mysqlnd
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main/latest                                                       | 2.1 kB     00:00     
amzn-updates/latest                                                    | 2.3 kB     00:00     
Resolving Dependencies
--> Running transaction check
---> Package httpd24.x86_64 0:2.4.18-1.64.amzn1 will be installed
--> Processing Dependency: httpd24-tools = 2.4.18-1.64.amzn1 for package: httpd24-2.4.18-1.64.amzn1.x86_64
--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd24-2.4.18-1.64.amzn1.x86_64
--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd24-2.4.18-1.64.amzn1.x86_64
---> Package mysql56-server.x86_64 0:5.5.46-1.10.amzn1 will be installed
--> Processing Dependency: real-mysql56(x86-64) = 5.5.46-1.10.amzn1 for package: mysql56-server-5.5.46-1.10.amzn1.x86_64
--> Processing Dependency: real-mysql56-libs(x86-64) = 5.5.46-1.10.amzn1 for package: mysql56-server-5.5.46-1.10.amzn1.x86_64
--> Processing Dependency: perl(Data::Dumper) for package: mysql56-server-5.5.46-1.10.amzn1.x86_64
--> Processing Dependency: perl-DBD-MySQL(mysql56) for package: mysql56-server-5.5.46-1.10.amzn1.x86_64
--> Processing Dependency: mysql56(alternatives) for package: mysql56-server-5.5.46-1.10.amzn1.x86_64
--> Processing Dependency: perl(DBI) for package: mysql56-server-5.5.46-1.10.amzn1.x86_64
--> Processing Dependency: mysql-config for package: mysql56-server-5.5.46-1.10.amzn1.x86_64
...

15) Turn the Apache server on.

[ec2-user@ip-99-999-999-9 ~]$ sudo service httpd start
Starting httpd:                                            [  OK  ]

16) It is a good idea to configure the server to start Apache if the server ever gets restarted.

[ec2-user@ip-99-999-999-9 ~]$ sudo chkconfig httpd on

17) Give permissions to yourself and future users of the /var/www directories and add yourself to the www user group.

[ec2-user@ip-99-999-999-9 ~]$ sudo groupadd apache
[ec2-user@ip-99-999-999-9 ~]$ sudo usermod -a -G apache ec2-user
[ec2-user@ip-99-999-999-9 ~]$ sudo chown -R root:apache /var/www
[ec2-user@ip-99-999-999-9 ~]$ sudo chmod 2775 /var/www
[ec2-user@ip-99-999-999-9 ~]$ find /var/www -type d -exec sudo chmod 2775 {} \;
[ec2-user@ip-99-999-999-9 ~]$ find /var/www -type f -exec sudo chmod 0664 {} \;

18) Log out and back in again so that your new permission structure is recognized.

[ec2-user@ip-99-999-999-9 html]$ exit
logout
Connection to ec2-99-999-999-9.us-west-2.compute.amazonaws.com closed.
Tims-MBP:publickeys tim$ ssh -i ~/publickeys/tutorial.pem ec2-user@ec99-999-999-9.us-west-2.compute.amazonaws.com
Last login: Mon May 30 17:39:03 2016 from 999.999.999.999

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2016.03-release-notes/
[ec2-user@ip-99-999-999-9 ~]$ 

19) Create a PHP info file to test your LAMP stack.

[ec2-user@ip-99-999-999-9 ~]$ echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php

20) In the AWS dashboard, you’ll need to configure your security group to allow traffic over the standard HTTP port. From the left menu under ‘Network & Security’ select ‘Security Groups.’ By default the security group setup on our EC2 instance was the launch-wizard-1. To keep it simple, select that and we will modify the rules.

21) Select the ‘Inbound’ tab and click ‘Edit’ then from the dropdown menu under ‘Type’ select ‘HTTP’

22) Create a test script to verify the server is working, back in your terminal window, navigate to /var/www/html/ then fire up nano to create the phpinfo file.

[ec2-user@ip-99-999-999-9 ~]$ cd /var/www/html/
[ec2-user@ip-99-999-999-9 html]$ nano phpinfo.php

23) In nano add the line <?php phpinfo(); ?&rt; then press ‘control’ + ‘x’ then ‘Y’ then ‘return.’

24) Open this script from a web browser using your public DNS to verify that PHP and Apache are working properly. http://ec2-99-999-999-9.us-west-2.compute.amazonaws.com/phpinfo.php If you see the PHP info page everything is working! If your connection times out, you should probably jump back to step 20 and check that your permission settings are correct.

25) Once you have been able to access the phpinfo screen you should delete it. This shows too much data to keep public!

[ec2-user@ip-99-999-999-9 html]$ rm /var/www/html/phpinfo.php

25) Setup and secure the MySQL service. Start the server, then run mysql_secure_installation to set a root password and to remove un-secure features.

[ec2-user@ip-99-999-999-9 html]$ sudo service mysqld start
Initializing MySQL database:  Installing MySQL system tables...
160530 19:03:50 [Note] /usr/libexec/mysql55/mysqld (mysqld 5.5.46) starting as process 27959 ...
OK
Filling help tables...
160530 19:03:50 [Note] /usr/libexec/mysql55/mysqld (mysqld 5.5.46) starting as process 27966 ...
OK
...
[ec2-user@ip-99-999-999-9 html]$ sudo mysql_secure_installation
...
Follow the prompts

26) Configure linux to start the MySQL server on reboot.

[ec2-user@ip-99-999-999-9 html]$ sudo chkconfig mysqld on

You now have a fully functional public LAMP server instance!

ADDENDUM

I have noticed that MySQL will occasionally crash on the the T2.nano instance and I believe this is due to MySQL expecting some swap space available for InnoDB’s storage engine to work correctly. Here’s how to fix that.

1) Configure the instance to use a swap file.

[ec2-user@ip-99-999-999-9 ~]$ sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 14.9658 s, 71.7 MB/s

2) Give the swapfile the correct permissions. It wants 600 but is given 644 by default, (I have no idea why…)

[ec2-user@ip-99-999-999-9 ~]$ sudo chmod 0600 /swapfile

3) Tell linux to use the swapfile.

[ec2-user@ip-99-999-999-9 ~]$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 1048572 KiB
no label, UUID=f218d07f-6332-4d84-8dfe-f31fe6b8e0bd

4) Finally tell linux to use the swapfile on startup, add the line /swapfile swap swap defaults 0 0 to the /etc/fstab file

[ec2-user@ip-99-999-999-9 ~]$ sudo nano /etc/fstab

This should prevent the MySQL process from being killed when InnoDB tries to allocate some memory.