{"id":22,"date":"2011-03-17T12:38:50","date_gmt":"2011-03-17T19:38:50","guid":{"rendered":"https:\/\/www.alexkorn.com\/blog\/?p=22"},"modified":"2014-08-15T14:35:07","modified_gmt":"2014-08-15T21:35:07","slug":"getting-php-mysql-running-amazon-ec2","status":"publish","type":"post","link":"https:\/\/www.alexkorn.com\/blog\/2011\/03\/getting-php-mysql-running-amazon-ec2\/","title":{"rendered":"Getting PHP and MySQL running on Amazon EC2"},"content":{"rendered":"<p>\nDo you know nothing about Amazon Web Services (AWS) or Linux server administration, but want to get a PHP\/MySQL server set up on AWS? I was once like you, relying upon my web host to have PHP and MySQL installed and configured, so it was a bit daunting initially to work with AWS, but it&#8217;s actually rather simple. Read on and I&#8217;ll show you how to set up PHP and MySQL on one of <a href=\"http:\/\/aws.amazon.com\/free\/\">Amazon&#8217;s free servers<\/a> step by step. You can have a functioning site up and running within half an hour.\n<\/p>\n<h2>Amazon Web Services<\/h2>\n<p>\nFirst things first: Amazon Web Services has a ton of different products, but the one you want is <a href=\"http:\/\/aws.amazon.com\/ec2\/\">Amazon Elastic Compute Cloud<\/a> (<em>EC2<\/em>). Go there, and click &#8220;Sign Up for Amazon EC2&#8221;.\n<\/p>\n<p>\nOnce you&#8217;ve gotten that set up, go to the <a href=\"https:\/\/console.aws.amazon.com\/ec2\/\"><em>AWS Management Console<\/em><\/a>, and click on &#8220;Instances&#8221; in the Navigation panel. An <em>Instance<\/em> is just a virtual server &#8211; so let&#8217;s create one! Click &#8220;Launch Instance&#8221; under &#8220;My Instances&#8221;, and select &#8220;Basic 64-bit Amazon Linux AMI&#8221;. On the <em>Instance Details<\/em> phase, select &#8220;Micro&#8221; (which is Free tier eligible). Continue until you need to enter the &#8220;Name&#8221; &#8211; if you don&#8217;t know what else to call it, just use &#8220;Web\/DB server&#8221;.\n<\/p>\n<p>\nNext you create a <em>Key Pair<\/em> &#8211; this will be the credentials you&#8217;ll use to SSH into the box. The instructions here should be fairly straightforward. Next is the <em>Security Group<\/em>, which will be used to specify the firewall used for your instance. Feel free to use the default Group for now. Continue to the <em>Review<\/em> phase and launch it!\n<\/p>\n<p>\nYou should now be able to SSH into your instance using your .pem file with <code>ssh -i [FILE NAME].pem ec2-user@ec2-[IP ADDRESS].compute-1.amazonaws.com<\/code>. Alright, we&#8217;ve got a server up and running! However, you may notice that this server has very little installed on it. <code>which php<\/code>? Nothing. <code>which mysql<\/code>? The same. Let&#8217;s install some software.\n<\/p>\n<h2>Configuring the Linux Server<\/h2>\n<p>\nBelow I&#8217;ll show you how to set up PHP and MySQL on the server. I&#8217;ve separated PHP and MySQL so that it&#8217;s easier to adapt this to having <a href=\"#twoInstances\">two instances<\/a>.\n<\/p>\n<h3>PHP<\/h3>\n<p>\nFirst, the basics for PHP:\n<\/p>\n<pre>\r\nsudo yum install php-mysql php php-xml php-mcrypt php-mbstring php-cli mysql httpd\r\n<\/pre>\n<p>\nPress &#8216;y&#8217; for each of the prompts that shows up. Note that you&#8217;re logged in as ec2-user, so you need to <em>sudo<\/em> all of these commands.\n<\/p>\n<p>\nYou should now be able to create and run a PHP test file. Next, let&#8217;s get MySQL up and running.\n<\/p>\n<h3>MySQL server<\/h3>\n<p>\nFirst, install and begin running the server:\n<\/p>\n<pre>\r\nsudo yum install mysql-server\r\nsudo \/etc\/init.d\/mysqld start\r\n<\/pre>\n<p>\nNext, set the root password. I&#8217;ve found <a href=\"https:\/\/www.grc.com\/passwords.htm\">this password generator<\/a> to be just dandy.\n<\/p>\n<pre>\r\nmysqladmin -u root password '[PASSWORD]'\r\n<\/pre>\n<p>\nNow we set up two users for MySQL: the administrator, which you&#8217;ll use to create and modify tables; and the app user, which the app will use to query the DB (with more limited privileges). Log into MySQL as <code>root<\/code> (<code>mysql -u root -p<\/code>) and enter each of the following lines:\n<\/p>\n<pre>\r\nCREATE DATABASE [DB NAME];\r\nCREATE USER '[DB NAME]_admin'@'localhost' IDENTIFIED BY '[ADMIN PASSWORD]';\r\nGRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER ON [DB NAME].* TO '[DB NAME]_admin'@'localhost';\r\nCREATE USER '[DB NAME]_user'@'localhost' IDENTIFIED BY '[USER PASSWORD]';\r\nGRANT SELECT, INSERT, UPDATE, DELETE ON [DB NAME].* TO '[DB NAME]_user'@'localhost';\r\n<\/pre>\n<p>\nYou may want to fine-tune your database settings further than this, but this is a good start.\n<\/p>\n<h2>Make it web-accessible<\/h2>\n<p>\nWe now have PHP and MySQL running on the box, but cannot access it through a browser. We need to configure the web server and set up an <em>Elastic IP<\/em>.\n<\/p>\n<h3>Web Server<\/h3>\n<p>\nFirst, let&#8217;s create a test PHP file that will be accessed by the browser. Create directories so that you can put your file in <code>\/opt\/app\/current<\/code><sup><a name=\"note1back\" href=\"#note1\">1<\/a><\/sup>. Make an <code>index.php<\/code> file that contains whatever you want.\n<\/p>\n<p>\nIf you want to FTP transfer files to your server, you&#8217;ll want to give the ec2-user permissions to modify files in your web directory:\n<\/p>\n<pre>sudo chown ec2-user \/opt\/app\/current<\/pre>\n<p>\nTo set up the web server, <em>httpd<\/em>, we need to first modify its configuration file, located at <code>\/etc\/httpd\/conf\/httpd.conf<\/code>. Open it up with <code>vim<\/code>, <code>emacs<\/code>, or your favorite text editor, and go to the bottom of the file. Here you&#8217;ll see a small section on the <em>VirtualHost<\/em> (between <code>&lt;VirtualHost *:80&gt;<\/code> and <code>&lt;\/VirtualHost&gt;<\/code>). Uncomment it out and set DocumentRoot to <code>\/opt\/app\/current<\/code>. Restart (or start) <code>httpd<\/code>:\n<\/p>\n<pre>\r\nsudo \/etc\/init.d\/httpd restart\r\n<\/pre>\n<h3><em>Elastic IP<\/em> and <em>Security Groups<\/em><\/h3>\n<p>\nIn the <em>AWS Management Console<\/em>, click on &#8220;Elastic IPs&#8221;, then &#8220;Allocate New Address&#8221; under &#8220;Addresses&#8221;. Once the address is created, click on it, then &#8220;Associate Address&#8221;. Select the instance and associate it.\n<\/p>\n<p>\nNow click on &#8220;Security Groups&#8221; in the Navigation panel. Select the <em>Security Group<\/em> that you used for the instance (probably the default one). Under the &#8220;Inbound&#8221; tab, add an HTTP rule (port 80). Click &#8220;Apply Rule Changes&#8221;, and you should now be able to access your website! In your browser, go to <code>http:\/\/ec2-[IP ADDRESS].compute-1.amazonaws.com\/<\/code>, where the IP address is the <em>Elastic IP<\/em> you made with periods replaced with hyphens.\n<\/p>\n<h2>Hello World! <span style=\"font-style:italic;\">or<\/span> Putting it all together<\/h2>\n<p>\nWe now have all the pieces we need to access MySQL from PHP and serve that to the browser-accessible website. So let&#8217;s log into <code>mysql<\/code> and create a sample table:\n<\/p>\n<pre>\r\nmysql -u [DB NAME]_admin -p\r\n[type password]\r\nmysql> use [DB NAME];\r\nmysql> CREATE TABLE test (message VARCHAR(255));\r\nmysql> INSERT INTO test (message) VALUES ('Hello world!');\r\n<\/pre>\n<p>\nNow modify your index.php file (<code>\/opt\/app\/current\/index.php<\/code>) to be the following:\n<\/p>\n<pre lang=\"php\">\r\n<?php\r\n$conn =  new mysqli('localhost', '[DB NAME]_user', '[USER PASSWORD]', '[DB NAME]');\r\n$result = $conn->query(\"SELECT message FROM test;\");\r\n$row = $result->fetch_assoc();\r\necho $row['message'];\r\n?>\r\n<\/pre>\n<p>\nWe now have a fully functioning PHP and MySQL server!\n<\/p>\n<h2>Taking it further<\/h2>\n<p>\nThat&#8217;s it for the basics, but there&#8217;s so much more that you can do now.\n<\/p>\n<h3><a href=\"http:\/\/www.phpunit.de\/\">PHPUnit<\/a><\/h3>\n<pre>\r\nsudo pear upgrade\r\nsudo yum install php-pear\r\nsudo pear channel-discover pear.phpunit.de\r\nsudo pear channel-discover pear.symfony-project.com\r\nsudo pear channel-discover components.ez.no\r\nsudo pear install phpunit\/PHPUnit\r\n<\/pre>\n<h3><a href=\"http:\/\/www.phpmyadmin.net\/\">phpMyAdmin<\/a><\/h3>\n<p>\nI&#8217;ve found it handy to set up an administration area for my sites using a different port on the same URL. Note that port 80 is the default for web traffic, but 8080 is also commonly used.\n<\/p>\n<p>\nCreate <code>\/opt\/app\/admin<\/code>. Then, in <em>httpd.conf<\/em>, add the line <code>Listen 8080<\/code> after <code>Listen 80<\/code> and add another <em>VirtualHost<\/em> entry, using <code>&lt;VirtualHost *:8080&gt;<\/code> and pointing to the <code>\/opt\/app\/admin<\/code> directory. Update your <em>Security Group<\/em> to allow traffic over port 8080. Make sure to restart Apache and you should now be able to access your <em>admin<\/em> folder through your browser at <code>yourdomain.com:8080<\/code>.\n<\/p>\n<p>\nYou can then download phpMyAdmin into <code>\/opt\/app\/admin\/pma<\/code> and unzip it. Using the <code>[DB NAME]_admin<\/code> user, you can now manage your databases there through your browser.\n<\/p>\n<p><a name=\"twoInstances\"><\/a><\/p>\n<h3>Using two <em>Instances<\/em><\/h3>\n<p>\nIt can be very beneficial to performance to separate the web server and the DB server. To do this, you&#8217;ll need to set up two <em>Instances<\/em>, one of which has the web server <code>httpd<\/code> running and an <em>Elastic IP<\/em>, and the other of which has the MySQL server <code>mysqld<\/code> running.\n<\/p>\n<p>\nThey can use the same <em>Security Group<\/em>, but you&#8217;ll have to add the MySQL rule (port 3066) for Inbound traffic to allow the servers to talk to each other.\n<\/p>\n<p>\nOn the web box, instead of using &#8220;localhost&#8221; as the MySQL host, use the Internal IP address of the MySQL box. On the DB box, set up your <em>grant<\/em> permissions to allow from anywhere in <code>'%.ec2.internal'<\/code> (or just from your IPs).\n<\/p>\n<h2>Notes<\/h2>\n<p><a name=\"note1\"><\/a><\/p>\n<ol>\n<li>\n<p>\n<code>\/opt\/app\/current<\/code> is a Rails convention that I enjoy. What you should do is put your releases in <code>\/opt\/app\/releases\/[release #]<\/code>, then have <code>\/opt\/app\/current<\/code> be a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Symbolic_link\"><code>symlink<\/code><\/a> to the current release.\n<\/p>\n<p>\nAnother (much more) common standard is to put web-accessible code in <code>\/var\/www\/html<\/code>. Feel free to put your HTML code wherever you want; just make sure to update <code>httpd.conf<\/code> appropriately (and restart Apache).\n<\/p>\n<p><a href=\"#note1back\">^ Back up<\/a><\/p>\n<\/li>\n<\/ol>\n<hr>\n<p>\nThanks to <a href=\"http:\/\/www.twitter.com\/rausanka\">Ryan Ausanka-Crues<\/a> at <a href=\"http:\/\/www.palominolabs.com\/\">Palomino Labs<\/a> for help with this.<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Do you know nothing about Amazon Web Services (AWS) or Linux server administration, but want to get a PHP\/MySQL server set up on AWS? I was once like you, relying upon my web host to have PHP and MySQL installed and configured, so it was a bit daunting initially to work with AWS, but it&#8217;s [&hellip;]<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,15,16],"tags":[12,26,13,17,14,6],"class_list":["post-22","post","type-post","status-publish","format-standard","hentry","category-aws","category-hosting","category-tutorials","tag-amazon","tag-apache","tag-ec2","tag-linux","tag-mysql","tag-php"],"_links":{"self":[{"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/posts\/22","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/comments?post=22"}],"version-history":[{"count":0,"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/posts\/22\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/media?parent=22"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/categories?post=22"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.alexkorn.com\/blog\/wp-json\/wp\/v2\/tags?post=22"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}