<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>WordPress &#8211; Blog of Kliment Andreev &#8211; A place so I won&#039;t forget things</title>
	<atom:link href="https://blog.andreev.it/tag/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.andreev.it</link>
	<description></description>
	<lastBuildDate>Sun, 28 Dec 2025 01:41:07 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>Azure: Run WordPress on managed MySQL and App Services</title>
		<link>https://blog.andreev.it/2021/12/azure-run-wordpress-on-managed-mysql-and-app-services/</link>
					<comments>https://blog.andreev.it/2021/12/azure-run-wordpress-on-managed-mysql-and-app-services/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Wed, 01 Dec 2021 20:47:57 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Azure App]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=8946</guid>

					<description><![CDATA[In this post I&#8217;ll explain how to run a WordPress site using Azure services&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In this post I&#8217;ll explain how to run a WordPress site using Azure services for managed MySQL and App Services for a PHP application.<br />
The basic offerings for MySQL and App Services create these resources in a public subnet, so in order to integrate them with your VNETs, you&#8217;ll have to use the more expensive options. In this post, we&#8217;ll use just that. We&#8217;ll create the MySQL database without any public access and integrate the App Services to connect to the SQL database internally.</p>
<h1>VNET/subnets</h1>
<p>First, we&#8217;ll create a VNET with three subnets. When you integrate an App Services in a VNET, the subnet where the App Services will reside must be empty. The same applies for Flex MySQL servers. You can have multiple Apps in the same dedicated subnet. So, you need a dedicated subnet for both App Service and MySQL Flex, but not for MySQL single server. Single MySQL server can share the subnet with other resources.<br />
For MySQL, there are two options. We can use a private endpoint or a VNET integration. We&#8217;ll go with a private endpoint first. We don&#8217;t need a dedicated subnet for this.<br />
In my case, I&#8217;ll create a VNET with <strong>192.168.100.0/22</strong> CIDR and three subnets, <strong>192.168.100.0/24</strong> for some Infra/MySQL stuff, <strong>192.168.101.0/24</strong> for the App Services and <strong>192.168.102.0/24</strong> for Flex MySQL. I&#8217;ll use a new resource group called <strong>rgWordPress</strong>. The VNET will be called <strong>vnetWordPress</strong> and the subnets, <strong>subInfra</strong>, <strong>subApp</strong> and <strong>subMySQL</strong> respectively.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-01.png"><img fetchpriority="high" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-01.png" alt="" width="1582" height="1178" class="aligncenter size-full wp-image-8948" /></a></p>
<h2>VM</h2>
<p>I will also create a VM in the <strong>subInfra</strong> subnet. This VM is not needed at all, it will be used to test connectivity. In my case, I&#8217;ll spin a new Debian 1CPU, 1GB VM and I&#8217;ll install the MySQL client.</p>
<pre class="brush: bash; title: ; notranslate">sudo apt install default-mysql-client</pre>
<h1>Managed Single server MySQL</h1>
<p>When it comes to MySQL, there are two options: Flexible server and Single server. Look at this <a href="https://docs.microsoft.com/en-us/azure/mysql/select-right-deployment-type" rel="noopener" target="_blank">link</a> to determine what you want to use. In most of the cases, you&#8217;ll use a Flexible server. But there are some limitations in both use cases. For example, a Flexible server can&#8217;t use private endpoints. You are limited to VNET integration and Single server can&#8217;t be VNET integrated. On top of that, only General Purpose and Memory Optimized servers can have private endpoints. The basic single server can be public only. Flex VNET integrated servers require dedicated and empty subnets. There are other limitations as well, so take a look at the link above.<br />
In my case, I am using a General Purpose server.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-02.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-02.png" alt="" width="1514" height="1532" class="aligncenter size-full wp-image-8954" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-02.png 1514w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-02-296x300.png 296w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-02-1012x1024.png 1012w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-02-768x777.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-02-1170x1184.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-02-585x592.png 585w" sizes="(max-width: 1514px) 100vw, 1514px" /></a><br />
Once you create the server, it will be public. As you can see from the <strong>Overview</strong> for the server, there is a public DNS record.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-03.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-03.png" alt="" width="1010" height="356" class="aligncenter size-full wp-image-8956" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-03.png 1010w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-03-300x106.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-03-768x271.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-03-585x206.png 585w" sizes="(max-width: 1010px) 100vw, 1010px" /></a><br />
On the left side/blade, under <strong>Security</strong>, click on <strong>Private endpoint connections</strong> and create one.<br />
Name the private link and put it in the same resource group as the other resources.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-04.png" alt="" width="1568" height="802" class="aligncenter size-full wp-image-8957" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-04.png 1568w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-04-300x153.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-04-1024x524.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-04-768x393.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-04-1536x786.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-04-1170x598.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-04-585x299.png 585w" sizes="(max-width: 1568px) 100vw, 1568px" /></a><br />
For the resource type <strong>Microsoft.DBforMySQL/servers</strong> and you&#8217;ll be able to select the newly created MySQL server from the dropdown under <strong>Resource</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-05.png" alt="" width="1544" height="726" class="aligncenter size-full wp-image-8958" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-05.png 1544w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-05-300x141.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-05-1024x481.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-05-768x361.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-05-1536x722.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-05-1170x550.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-05-585x275.png 585w" sizes="(max-width: 1544px) 100vw, 1544px" /></a><br />
Finally, choose the virtual network and subnet where you want to put the private link. Do not use the subnet for App Services. In addition, make sure that the integration with the private DNS zone is set to <strong>Yes</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-06.png" alt="" width="2056" height="994" class="aligncenter size-full wp-image-8959" /></a><br />
If you log to the server that we just built and try to resolve the public DNS for the MySQL server, you&#8217;ll see that it resolves as a private IP. That&#8217;s because you have a private DNZ zone that takes precedence over the public DNS.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-07.png" alt="" width="1600" height="186" class="aligncenter size-full wp-image-8961" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-07.png 1600w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-07-300x35.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-07-1024x119.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-07-768x89.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-07-1536x179.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-07-1170x136.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-07-585x68.png 585w" sizes="(max-width: 1600px) 100vw, 1600px" /></a><br />
In case, you are still getting the public IP, go to the <strong>Private DNS zone</strong> and make sure that it&#8217;s linked to the actual VNET.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-08.png" alt="" width="1888" height="774" class="aligncenter size-full wp-image-8962" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-08.png 1888w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-08-300x123.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-08-1024x420.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-08-768x315.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-08-1536x630.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-08-1170x480.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-08-585x240.png 585w" sizes="(max-width: 1888px) 100vw, 1888px" /></a><br />
Now you can try to connect to the MySQL database. </p>
<pre class="brush: bash; title: ; notranslate">mysql -u klimenta@mysqlwordpress-single -h mysqlwordpress-single.mysql.database.azure.com -p</pre>
<p>Where <strong>-u</strong> specifies the username and the <strong>-h </strong>is the host. These parameters are under <strong>Overview</strong> on the right side. See the screenshot above.<br />
You might get the following error. ERROR 9002 (28000): SSL connection is required. Please specify SSL options and retry.<br />
In that case, download the SSL certificate and try again. </p>
<pre class="brush: bash; title: ; notranslate">
wget https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem
mysql -u klimenta@mysqlwordpress-single -h mysqlwordpress-single.mysql.database.azure.com -p --ssl-ca=BaltimoreCyberTrustRoot.crt.pem
</pre>
<p>In case you are wondering, wait, why this cert? &#8211; The answer is <a href="https://docs.microsoft.com/en-us/azure/mysql/howto-configure-ssl" rel="noopener" target="_blank">here</a>.<br />
As you can see, I am able to connect now.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-09.png" alt="" width="1620" height="806" class="aligncenter size-full wp-image-8964" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-09.png 1620w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-09-300x149.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-09-1024x509.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-09-768x382.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-09-1536x764.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-09-1170x582.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-09-585x291.png 585w" sizes="(max-width: 1620px) 100vw, 1620px" /></a><br />
It is also recommended to disable the public access. Go to <strong>Connection security </strong>under <strong>Settings</strong> and select <strong>Yes</strong> for <strong>Deny public network access</strong>.</p>
<h1>App Services</h1>
<p>Go to App Services and create one. Make sure you use <strong>Premium</strong> offering so you can do a VNET integration. The initial parameters are self explaining. Use the defaults for the rest of the screens. You won&#8217;t be able to do much with PHP anyway.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-10.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-10.png" alt="" width="1564" height="1458" class="aligncenter size-full wp-image-8967" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-10.png 1564w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-10-300x280.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-10-1024x955.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-10-768x716.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-10-1536x1432.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-10-1170x1091.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-10-585x545.png 585w" sizes="(max-width: 1564px) 100vw, 1564px" /></a><br />
Once the app is provisioned, on the left side/blade, go to the <strong>Networking</strong> menu under <strong>Settings</strong>. You&#8217;ll see that the VNET integration is not configured. Click on the link.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-11.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-11.png" alt="" width="1992" height="1224" class="aligncenter size-full wp-image-8968" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-11.png 1992w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-11-300x184.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-11-1024x629.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-11-768x472.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-11-1536x944.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-11-1920x1180.png 1920w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-11-1170x719.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-11-585x359.png 585w" sizes="(max-width: 1992px) 100vw, 1992px" /></a><br />
Pretty much, you have to select the VNET and an empty subnet. As you can see, I can only select subApp from the dropdown.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-12.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-12.png" alt="" width="1152" height="1054" class="aligncenter size-full wp-image-8970" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-12.png 1152w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-12-300x274.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-12-1024x937.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-12-768x703.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-12-585x535.png 585w" sizes="(max-width: 1152px) 100vw, 1152px" /></a><br />
Close the blade and from the App menu, click on <strong>SSH</strong> under <strong>Development Tools</strong> on the left. This will open a new tab in your browser with a SSH session.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-13.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-13.png" alt="" width="1000" height="524" class="aligncenter size-full wp-image-8971" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-13.png 1000w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-13-300x157.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-13-768x402.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-13-585x307.png 585w" sizes="(max-width: 1000px) 100vw, 1000px" /></a><br />
We have to create the WordPress database now. You can do that from the test server that we used initially or from the actual SSH session. Let&#8217;s use the SSH session. It already comes with mysql client preinstalled.</p>
<pre class="brush: bash; title: ; notranslate">
wget https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem
mysql -u klimenta@mysqlwordpress-single -h mysqlwordpress-single.mysql.database.azure.com -p --ssl-ca=BaltimoreCyberTrustRoot.crt.pem
</pre>
<p>Once in MySQL client, execute these SQL statements.</p>
<pre class="brush: sql; title: ; notranslate">
CREATE DATABASE dbwordpress;
GRANT ALL PRIVILEGES ON dbwordpress.* TO &quot;wordpressuser&quot;@&quot;%&quot; IDENTIFIED BY &quot;SuperSecret&quot;;
FLUSH PRIVILEGES;
EXIT
</pre>
<p>Replace the values with yours for the database name, MySQL host name, username and password.<br />
Now, you can download WordPress and extract it.</p>
<pre class="brush: bash; title: ; notranslate">
cd /home/site/wwwroot
wget -c http://WordPress.org/latest.tar.gz
tar -xzvf latest.tar.gz
mv WordPress/* /home/site/wwwroot/
rm -rf WordPress
rm -rf latest.tar.gz
</pre>
<p>Once completed, go to the URL for the app. It should be under the <strong>Overview</strong>. You have to provide the database name (dbwordpress), username (wordpressuser@mysqlwordpress-single), password (SuperSecret) and the database host (mysqlwordpress-single.mysql.database.azure.com).<br />
Most likely you&#8217;ll see an error. The easiest way is to disable the SSL requirement for the MySQL database from Connection security under Settings for the database.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-14.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-14.png" alt="" width="2218" height="382" class="aligncenter size-full wp-image-8975" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-14.png 2218w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-14-300x52.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-14-1024x176.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-14-768x132.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-14-1536x265.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-14-2048x353.png 2048w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-14-1920x331.png 1920w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-14-1170x202.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-14-585x101.png 585w" sizes="(max-width: 2218px) 100vw, 2218px" /></a><br />
If this doesn&#8217;t work for you, you&#8217;ll have to manually specify the parameters in wp-config.php. You can search this on your own.<br />
Once you are done, specify the values in WordPress install screen and you are all set.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-15.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-15.png" alt="" width="1544" height="996" class="aligncenter size-full wp-image-8976" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-15.png 1544w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-15-300x194.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-15-1024x661.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-15-768x495.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-15-1536x991.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-15-1170x755.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-15-585x377.png 585w" sizes="(max-width: 1544px) 100vw, 1544px" /></a></p>
<h1>Flex MySQL server</h1>
<p>Let&#8217;s see how Flex MySQL server works. Go to Azure MySQL but this time provision a flex server.<br />
This is how my setup looks like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-16.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-16.png" alt="" width="1594" height="1216" class="aligncenter size-full wp-image-8978" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-16.png 1594w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-16-300x229.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-16-1024x781.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-16-768x586.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-16-1536x1172.png 1536w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-16-1170x893.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-16-585x446.png 585w" sizes="(max-width: 1594px) 100vw, 1594px" /></a><br />
&#8230;and this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/11/P156-17.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/11/P156-17.png" alt="" width="1508" height="818" class="aligncenter size-full wp-image-8979" srcset="https://blog.andreev.it/wp-content/uploads/2021/11/P156-17.png 1508w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-17-300x163.png 300w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-17-1024x555.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-17-768x417.png 768w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-17-1170x635.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/11/P156-17-585x317.png 585w" sizes="(max-width: 1508px) 100vw, 1508px" /></a><br />
A flexible MySQL server can&#8217;t have a private endpoint, but it can be VNET integrated, same as the Azure App Services. And if you choose for the flex server to be VNET integrated, you&#8217;ll need a dedicated and empty subnet, same as Azure App Services.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/12/P156-18.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/12/P156-18.png" alt="" width="1524" height="1170" class="aligncenter size-full wp-image-8988" srcset="https://blog.andreev.it/wp-content/uploads/2021/12/P156-18.png 1524w, https://blog.andreev.it/wp-content/uploads/2021/12/P156-18-300x230.png 300w, https://blog.andreev.it/wp-content/uploads/2021/12/P156-18-1024x786.png 1024w, https://blog.andreev.it/wp-content/uploads/2021/12/P156-18-768x590.png 768w, https://blog.andreev.it/wp-content/uploads/2021/12/P156-18-1170x898.png 1170w, https://blog.andreev.it/wp-content/uploads/2021/12/P156-18-585x449.png 585w" sizes="(max-width: 1524px) 100vw, 1524px" /></a><br />
Once you provision the flex MySQL server, you&#8217;ll be able to manage it the same as a single server with a private endpoint. You can also see the entry in the private DNS zone for a flex server, same as with the single server. A flex server also allows you to have a hot standby HA pair but you can&#8217;t use this hot standby as a replica. A HA will double the price and you won&#8217;t be able to create replicas. The HA is in a different zone but in a same region and it allows forced and automatic failovers. And if you want to use a read only replica (up to 10), you have to take care of the SQL proxying using ProxySQL, HAProxy or Nginx.<br />
So, if you want some sort of HA for the MySQL, go with the flexible MySQL. You&#8217;ll have automatic failover within the region. But if you want to recover from a regional failure, use a single MySQL server with a read replica in another region (flexible MySQL can&#8217;t have replica in another region) and when you need to failover, just promote the replica in a standalone server (you&#8217;ll also need an Azure App Service in the DR region). The bad thing is that once you promote a replica in a standalone server and the original regions comes back up, you can&#8217;t revert the DR MySQL server in a replica again. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2021/12/azure-run-wordpress-on-managed-mysql-and-app-services/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Rocky Linux: Install the pre-release on VMware and WordPress</title>
		<link>https://blog.andreev.it/2021/05/rocky-linux-install-the-pre-release-on-vmware-and-wordpress/</link>
					<comments>https://blog.andreev.it/2021/05/rocky-linux-install-the-pre-release-on-vmware-and-wordpress/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sat, 01 May 2021 17:05:50 +0000</pubDate>
				<category><![CDATA[ESX/ESXi]]></category>
		<category><![CDATA[Rocky Linux]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[rocky linux]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=8861</guid>

					<description><![CDATA[Rocky Linux was finally release today (5/1/2021) and I&#8217;ve decided to try it in&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Rocky Linux was finally release today (5/1/2021) and I&#8217;ve decided to try it in my lab. I&#8217;ve downloaded the minimal ISO (Rocky-8.3-x86_64-minimal) and installed it under my vCenter version 6.x.<br />
I chose CentOS 8 as a base OS and after I mounted the ISO, I got an error saying <strong>ERROR Verification failed: (0x1A) Security Violation</strong>. If this is the case, shut down the guest, go to <strong>Settings | VM Options</strong> and if you expand <strong>Boot Options</strong>, change the <strong>Firmware</strong> from <strong>EFI </strong>to <strong>BIOS</strong>. This should do the trick.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/05/P154-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/05/P154-01.png" alt="" width="865" height="472" class="aligncenter size-full wp-image-8864" srcset="https://blog.andreev.it/wp-content/uploads/2021/05/P154-01.png 865w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-01-300x164.png 300w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-01-768x419.png 768w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-01-585x319.png 585w" sizes="(max-width: 865px) 100vw, 865px" /></a><br />
What you&#8217;ll see next is pretty much the same as any other CentOS 7/8 installation.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2021/05/P154-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/05/P154-02.png" alt="" width="792" height="592" class="aligncenter size-full wp-image-8866" srcset="https://blog.andreev.it/wp-content/uploads/2021/05/P154-02.png 792w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-02-300x224.png 300w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-02-768x574.png 768w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-02-585x437.png 585w" sizes="(max-width: 792px) 100vw, 792px" /></a><br />
<strong>NOTE: The current version is not considered for production.</strong><br />
Do the same as you do with any other CentOS install. Partition the hard drive, change the root password, configure the network and add a user.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/05/P154-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/05/P154-03.png" alt="" width="786" height="590" class="aligncenter size-full wp-image-8867" srcset="https://blog.andreev.it/wp-content/uploads/2021/05/P154-03.png 786w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-03-300x225.png 300w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-03-768x576.png 768w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-03-585x439.png 585w" sizes="(max-width: 786px) 100vw, 786px" /></a><br />
Once the server is up, you&#8217;ll see the login prompt.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2021/05/P154-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2021/05/P154-04.png" alt="" width="673" height="451" class="aligncenter size-full wp-image-8868" srcset="https://blog.andreev.it/wp-content/uploads/2021/05/P154-04.png 673w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-04-300x201.png 300w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-04-585x392.png 585w, https://blog.andreev.it/wp-content/uploads/2021/05/P154-04-263x175.png 263w" sizes="(max-width: 673px) 100vw, 673px" /></a><br />
Check the kernel version and the release.</p>
<pre class="brush: bash; highlight: [1,3]; title: ; notranslate">
uname -a
Linux rocky.andreev.local 4.18.0-240.22.1.el8.x86_64 #1 SMP Mon Apr 12 04:29:16 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
cat /etc/redhat-release
Rocky Linux release 8.3
</pre>
<p>By default, both the firewall and SELinux are enabled. </p>
<pre class="brush: bash; title: ; notranslate">
systemctl status firewalld
sestatus
</pre>
<p>You can use <strong>dnf</strong>, <strong>yum </strong>or <strong>rpm </strong>to manage the packages. If you need to change the network settings, use <strong>nmtui</strong>.<br />
Let&#8217;s install WordPress now. As root or using sudo, install Apache, PHP and MariaDB.</p>
<pre class="brush: bash; title: ; notranslate">
dnf install httpd php php-mysqlnd mariadb-server wget php-json
</pre>
<p>Start the Apache and MariaDB and enable them on both to start on reboot.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl enable httpd --now
systemctl enable mariadb --now
</pre>
<p>Open port 80 on the firewall for the Apache. </p>
<pre class="brush: bash; title: ; notranslate">
firewall-cmd --permanent --zone=public --add-service=http --permanent
firewall-cmd --reload
</pre>
<p>Do the initian MariaDB configuration and specify the new root password for the SQL server.</p>
<pre class="brush: bash; title: ; notranslate">
mysql_secure_installation
</pre>
<p>Log as the SQL root user to MariaDB.</p>
<pre class="brush: bash; title: ; notranslate">
mysql -u root -p
</pre>
<p>Create the database and the WordPress user.</p>
<pre class="brush: sql; title: ; notranslate">
CREATE DATABASE wordpress;
GRANT ALL ON wordpress.* TO 'wpadmin'@'localhost' IDENTIFIED BY 'supersecret';
FLUSH PRIVILEGES;
</pre>
<p>Get the latest WordPress release under /tmp, unzip it and copy it where it belongs (root Apache data directory).</p>
<pre class="brush: bash; title: ; notranslate">
cd /tmp
wget https://www.wordpress.org/latest.zip
unzip latest.zip
mv wordpress/* /var/www/html/
chown -R apache:apache /var/www/html
</pre>
<p>Change the SELinux context for the root Apache data directory. </p>
<pre class="brush: bash; title: ; notranslate">
chcon -t httpd_sys_rw_content_t /var/www/html -R
</pre>
<p>At this point, you can access your WordPress install at http://your_IP_or_hostname.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2021/05/rocky-linux-install-the-pre-release-on-vmware-and-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Alibaba Cloud, CentOS: Build WordPress site using NFS, RDS and Load Balancers</title>
		<link>https://blog.andreev.it/2019/04/alibaba-cloud-centos-build-wordpress-site-using-nfs-rds-and-load-balancers/</link>
					<comments>https://blog.andreev.it/2019/04/alibaba-cloud-centos-build-wordpress-site-using-nfs-rds-and-load-balancers/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Mon, 15 Apr 2019 16:50:40 +0000</pubDate>
				<category><![CDATA[Alibaba]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Alibaba cloud]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=5202</guid>

					<description><![CDATA[I got an invitation to attend an event in NYC for the Alibaba cloud,&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>I got an invitation to attend an event in NYC for the Alibaba cloud, so I decided to play a little bit with their cloud offering. I was actually surprised to see that they are doing a really good job. While many features are still not there, the ease and simplicity of Alibaba cloud is a plus. If you are familiar with AWS, it won&#8217;t take you more than 5 minutes to feel comfortable. The interface, although different is very intuitive. You can get a free trial (a credit card and phone verification are needed) and start playing. Visit this <a href="https://us.alibabacloud.com/" rel="noopener noreferrer" target="_blank">link </a>to start. Once you open an account and verify it, you&#8217;ll be presented with a console.<br />
I&#8217;ve decided to demonstrate how to start in Alibaba Cloud by building a WordPress site running on two instances behind a load balancer. The database will be a MySQL RDS offering from Alibaba. They still don&#8217;t offer NFS filesystem, so I had to create an instance for that. First thing first.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-01.png" alt="" width="1792" height="1063" class="aligncenter size-full wp-image-8482" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-01.png 1792w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-01-300x178.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-01-1024x607.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-01-768x456.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-01-1536x911.png 1536w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-01-1170x694.png 1170w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-01-585x347.png 585w" sizes="(max-width: 1792px) 100vw, 1792px" /></a></p>
<h1>VPC</h1>
<p>The ubiquitous VPCs from AWS are named the same in Alibaba and they serve the same purpose. From the top menu choose a region, from the left click on <strong>Virtual Private Cloud</strong> and then click on <strong>Create VPC</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-02.png" alt="" width="451" height="282" class="aligncenter size-full wp-image-8483" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-02.png 451w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-02-300x188.png 300w" sizes="(max-width: 451px) 100vw, 451px" /></a><br />
I&#8217;ll name my VPC, <strong>TestVPC </strong>and the CIDR (size of the VPC in terms of available IPs and subnets) is going to be 192.168.0.0/16 (which is default).<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-03.png" alt="" width="565" height="432" class="aligncenter size-full wp-image-8484" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-03.png 565w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-03-300x229.png 300w" sizes="(max-width: 565px) 100vw, 565px" /></a><br />
If you scroll down, you&#8217;ll see that you&#8217;ll also have to create a <strong>VSwitch</strong>. A <strong>VSwitch </strong>is nothing by a subnet or availability zone (AZ) in AWS terms. My first one will be called VSwitchA in Virginia Zone A and I&#8217;ll carve a smaller subnet 192.168.1.0/24 for that.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-04.png" alt="" width="504" height="469" class="aligncenter size-full wp-image-8485" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-04.png 504w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-04-300x279.png 300w" sizes="(max-width: 504px) 100vw, 504px" /></a><br />
Let&#8217;s create another one, but this time in a different zone. The subnets can&#8217;t overlap. On the left side, you&#8217;ll see the menu for <strong>VSwitches</strong>, so click there and then click on<strong> Create VSwitch</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-05.png" alt="" width="493" height="321" class="aligncenter size-full wp-image-8486" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-05.png 493w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-05-300x195.png 300w" sizes="(max-width: 493px) 100vw, 493px" /></a><br />
Do pretty much the same as previously. Choose the right VPC this time, name the VSwitch, choose the second zone and choose a different subnet. In my case it&#8217;s 192.168.2.0/24.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-06.png" alt="" width="596" height="540" class="aligncenter size-full wp-image-8487" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-06.png 596w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-06-300x272.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-06-585x530.png 585w" sizes="(max-width: 596px) 100vw, 596px" /></a></p>
<h1>Security Groups</h1>
<p>We&#8217;ll need several <strong>Security Groups</strong>. From the top left menu, click on <strong>Security Groups</strong> and the click on <strong>Create Security Group</strong> from the top right.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-07.png" alt="" width="256" height="368" class="aligncenter size-full wp-image-8488" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-07.png 256w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-07-209x300.png 209w" sizes="(max-width: 256px) 100vw, 256px" /></a><br />
For the Load Balancer, we&#8217;ll need a security group that will allow port 80 from everywhere (0.0.0.0/0). For the two instances that will run Apache and PHP, we&#8217;ll allow port 22 only from specific addresses and port 80 allowed from the load balancer only. We don&#8217;t want the actual instances to be exposed on port 80 on the Internet. For the RDS instance, we&#8217;ll create a security group that allows port 3306 (MySQL) from the two instances only. Finally, for the NFS server, we&#8217;ll also allow access from the two instances only on port 2049 (TCP).<br />
Here is an example of what I did for the first security group. I choose a <strong>custom </strong>template, named it <strong>sgLoadBalancer</strong>, added a description and chose my <strong>TestVPC</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-08.png" alt="" width="691" height="454" class="aligncenter size-full wp-image-8489" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-08.png 691w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-08-300x197.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-08-585x384.png 585w" sizes="(max-width: 691px) 100vw, 691px" /></a><br />
You can&#8217;t create the rules like you do in AWS, but once you create the security group, you&#8217;ll see a pop-up reminding you to create the rules. Click on <strong>Create Rules Now</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-09.png" alt="" width="593" height="223" class="aligncenter size-full wp-image-8490" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-09.png 593w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-09-300x113.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-09-585x220.png 585w" sizes="(max-width: 593px) 100vw, 593px" /></a><br />
This is how my rule for HTTP traffic looks like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-10.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-10.png" alt="" width="513" height="479" class="aligncenter size-full wp-image-8491" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-10.png 513w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-10-300x280.png 300w" sizes="(max-width: 513px) 100vw, 513px" /></a><br />
Name the second security group <strong>sgInstances</strong>, but before you create the group copy the security group ID for the first group that you created.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-11.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-11.png" alt="" width="852" height="93" class="aligncenter size-full wp-image-8493" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-11.png 852w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-11-300x33.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-11-768x84.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-11-585x64.png 585w" sizes="(max-width: 852px) 100vw, 852px" /></a><br />
When you add the rules for the 2nd security group for the instances, make sure that you change the <strong>Authorization Type</strong> parameter to <strong>Security Group</strong> instead of <strong>IPv4 CID Block</strong>. This way you can specify that another security group has access to a specific port, not an IP. We don&#8217;t know the IP of the load balancer and it probably changes from time to time.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-12.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-12.png" alt="" width="473" height="432" class="aligncenter size-full wp-image-8494" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-12.png 473w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-12-300x274.png 300w" sizes="(max-width: 473px) 100vw, 473px" /></a><br />
You have to create another rule for the instances. This time for the port 22. I chose to restrict port 22 to my home IP only. This is how those rules actually look like once created.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-13.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-13.png" alt="" width="777" height="245" class="aligncenter size-full wp-image-8495" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-13.png 777w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-13-300x95.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-13-768x242.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-13-585x184.png 585w" sizes="(max-width: 777px) 100vw, 777px" /></a><br />
For the next two security group, copy the security group ID of the newly created group <strong>sgInstances</strong>.<br />
Create two new security groups, <strong>sgRDS </strong>and <strong>sgNFS</strong>. For <strong>sgRDS </strong>allow port <strong>3306 </strong>from the security group ID of <strong>sgInstances </strong>and for <strong>sgNFS </strong>allow port <strong>2049 </strong>for the same security group ID of <strong>sgInstances</strong>.<br />
At the end you should have 4 security groups: sgLoadBalancer, sgInstances, sgRDS and sgNFS. These are the rules.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-14.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-14.png" alt="" width="385" height="131" class="aligncenter size-full wp-image-8496" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-14.png 385w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-14-300x102.png 300w" sizes="(max-width: 385px) 100vw, 385px" /></a><br />
And these security groups should be assigned to these resources.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-15.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-15.png" alt="" width="314" height="106" class="aligncenter size-full wp-image-8497" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-15.png 314w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-15-300x101.png 300w" sizes="(max-width: 314px) 100vw, 314px" /></a></p>
<h1>SSH Keys</h1>
<p>Before we start provisioning the servers, let&#8217;s create a SSH key pair so we can access them. The menu for the creation of SSH keys is bellow <strong>Security Groups</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-16.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-16.png" alt="" width="694" height="269" class="aligncenter size-full wp-image-8498" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-16.png 694w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-16-300x116.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-16-585x227.png 585w" sizes="(max-width: 694px) 100vw, 694px" /></a><br />
Click on <strong>Create SSH Key Pair</strong> in the top right corner. You can import or create your own key pair. I chose to create the key pair.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-17.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-17.png" alt="" width="799" height="322" class="aligncenter size-full wp-image-8499" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-17.png 799w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-17-300x121.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-17-768x310.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-17-585x236.png 585w" sizes="(max-width: 799px) 100vw, 799px" /></a><br />
As a result you&#8217;ll get a certificate file (.pem). Keep this file somewhere safe. If you use putty to connect to your instances, you&#8217;ll have to <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/putty.html#putty-private-key" rel="noopener noreferrer" target="_blank">convert </a>this file to ppk using puttygen.  </p>
<h1>NFS instance</h1>
<p>From the menu, go to <strong>Instances </strong>and then from the top right, click <strong>Create Instance</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-18.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-18.png" alt="" width="730" height="281" class="aligncenter size-full wp-image-8500" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-18.png 730w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-18-300x115.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-18-585x225.png 585w" sizes="(max-width: 730px) 100vw, 730px" /></a><br />
I am going with <strong>Pay-As-You-Go</strong> model and <strong>Random </strong>zone. Choose your instance type. The cheapest are under <strong>Entry-Level (Shared)</strong>. I went with 1 CPU and 1GB RAM and 20GB disk on CentOS 7.6 x-64. Looks like 20GB is minimum, I couldn&#8217;t choose anything below 20GB for the disk. Click <strong>Next: Networking</strong> when you are done here.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-19.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-19.png" alt="" width="1366" height="1612" class="aligncenter size-full wp-image-8501" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-19.png 1366w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-19-254x300.png 254w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-19-868x1024.png 868w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-19-768x906.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-19-1302x1536.png 1302w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-19-1170x1381.png 1170w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-19-585x690.png 585w" sizes="(max-width: 1366px) 100vw, 1366px" /></a><br />
On the Networking screen, I have these settings. The defaults for the VPC and the zone, click to <strong>Assign public IP</strong> and click to select a security group. For some reason, I was able to select only one security group, so select <strong>sgInstances </strong>as a security group.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-20.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-20.png" alt="" width="1366" height="1012" class="aligncenter size-full wp-image-8502" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-20.png 1366w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-20-300x222.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-20-1024x759.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-20-768x569.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-20-1170x867.png 1170w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-20-585x433.png 585w" sizes="(max-width: 1366px) 100vw, 1366px" /></a><br />
If you click next, you&#8217;ll see the <strong>System Configuration </strong>page. Specify the key that you&#8217;ve selected, name the instance so it shows up properly in the console, add a description if you want and enter the hostname (optional). From here, you can accept the default and next-through all the way to the end. Alibaba will create the instance for you in 1-3 minutes.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-21.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-21.png" alt="" width="1366" height="893" class="aligncenter size-full wp-image-8504" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-21.png 1366w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-21-300x196.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-21-1024x669.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-21-768x502.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-21-1170x765.png 1170w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-21-585x382.png 585w" sizes="(max-width: 1366px) 100vw, 1366px" /></a><br />
After the instance is create, go back to the <strong>Security Groups</strong> menu and find the <strong>sgNFS </strong>group. Click on <strong>Manage Instances</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-22.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-22.png" alt="" width="1088" height="114" class="aligncenter size-full wp-image-8505" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-22.png 1088w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-22-300x31.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-22-1024x107.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-22-768x80.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-22-585x61.png 585w" sizes="(max-width: 1088px) 100vw, 1088px" /></a><br />
From the top right, click on <strong>Add Instance</strong> and add the <strong>nfs </strong>instance. This way, we&#8217;ll have both <strong>sgInstances </strong>and <strong>sgNFS </strong>securty groups attached to the <strong>nfs </strong>server.<br />
Go back to your instances and you&#8217;ll see the instance is up and running. SSH to its public IP and specify the SSH key to log in. Your username is <strong>root</strong> and the ppk file is your password.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-23.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-23.png" alt="" width="1102" height="112" class="aligncenter size-full wp-image-8506" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-23.png 1102w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-23-300x30.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-23-1024x104.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-23-768x78.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-23-585x59.png 585w" sizes="(max-width: 1102px) 100vw, 1102px" /></a><br />
Once you are in, you&#8217;ll be greeted with the Alibaba banner.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-24.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-24.png" alt="" width="418" height="170" class="aligncenter size-full wp-image-8507" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-24.png 418w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-24-300x122.png 300w" sizes="(max-width: 418px) 100vw, 418px" /></a><br />
Now you are ready to install the NFS filesystem that will be used as a shared disk for both WordPress instances. I already have a small tutorial for this, so go to this <a href="https://blog.andreev.it/?p=4180" rel="noopener noreferrer" target="_blank">link </a>and do the server part. You can skip the part for the firewall (last two commands). The firewall is not enabled by default on Alibaba CentOS. SELinux is also disabled. Once you are done, we have to download WordPress and extract it under the <strong>nfs </strong>share. Then, we we build the webservers we&#8217;ll mount this directory and point our webserver there.</p>
<pre class="brush: bash; title: ; notranslate">
cd /nfs
wget https://www.wordpress.org/latest.tar.gz
tar xzvf latest.tar.gz --strip 1
</pre>
<h1>RDS</h1>
<p>We&#8217;ll use the PaaS offering from Alibaba for our MySQL database. From the menu on the left, click <strong>AsparaDB for RDS</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-25.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-25.png" alt="" width="316" height="208" class="aligncenter size-full wp-image-8508" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-25.png 316w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-25-300x197.png 300w" sizes="(max-width: 316px) 100vw, 316px" /></a><br />
Click <strong>Create Instance</strong> in the top right corner. This is what I chose for my database. Make sure <strong>Pay-As-You-Go</strong> is selected and then choose the RDS instance in the same region as your other instances. The engine is MySQL 5.7 with no HA. I chose a small 1 CPU/1GB DB instance with 20GB storage.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-26.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-26.png" alt="" width="1299" height="1325" class="aligncenter size-full wp-image-8509" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-26.png 1299w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-26-294x300.png 294w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-26-1004x1024.png 1004w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-26-768x783.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-26-1170x1193.png 1170w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-26-585x597.png 585w" sizes="(max-width: 1299px) 100vw, 1299px" /></a><br />
Click <strong>Buy Now</strong> and then <strong>Pay Now</strong> when you are done. If you go to the console, you won&#8217;t see your database. Just wait for a minute or two and it will show up with a status of <strong>Creating</strong>. After 3-5 mins, once the status changes to <strong>Running</strong>, click on the database. Let&#8217;s assign a security group first. Click on <strong>Basic Infomation</strong> on the left and then click on <strong>Set Whitelist</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-27.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-27.png" alt="" width="581" height="306" class="aligncenter size-full wp-image-8510" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-27.png 581w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-27-300x158.png 300w" sizes="(max-width: 581px) 100vw, 581px" /></a><br />
Look at the bottom right, where it says <strong>Add to Security Group</strong>. The names won&#8217;t show up, so get your security group ID for <strong>sgRDS </strong>from the <strong>Security Groups</strong> menu first. Unlike AWS, you can assign only one security group per DB instance. If you get an error that this operation is not supported, do not assign a security group. Just whitelist the VPC subnet. Click <strong>Add a Whitelist Group</strong> and add the VPC subnet 192.168.0.0/16.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-28.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-28.png" alt="" width="595" height="490" class="aligncenter size-full wp-image-8511" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-28.png 595w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-28-300x247.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-28-585x482.png 585w" sizes="(max-width: 595px) 100vw, 595px" /></a><br />
Now, go to the <strong>Accounts </strong>menu on the left and click <strong>Create Account</strong> on the right. I&#8217;ve created a superuser called <strong>dbmaster</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-29.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-29.png" alt="" width="1119" height="916" class="aligncenter size-full wp-image-8512" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-29.png 1119w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-29-300x246.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-29-1024x838.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-29-768x629.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-29-585x479.png 585w" sizes="(max-width: 1119px) 100vw, 1119px" /></a><br />
Again, go to <strong>Databases </strong>menu on the left and click <strong>Create Database</strong> on the right. Type the name of the database <strong>dbwordpress </strong>and click to create a new account. You&#8217;ll be back at the accounts menu. This time create a user called <strong>wordpress </strong>and make it a standard user. It&#8217;s kind of kludgy, but now you have to go back to the <strong>Databases </strong>menu, click <strong>Create Database</strong> again, fill the name <strong>dbwordpress </strong>again, but this time you can choose the account that you just created.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-30.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-30.png" alt="" width="697" height="496" class="aligncenter size-full wp-image-8513" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-30.png 697w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-30-300x213.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-30-585x416.png 585w" sizes="(max-width: 697px) 100vw, 697px" /></a><br />
Finally, go to the <strong>Basic Information</strong> menu and choose the menu next to Intranet address. Here you have to create a whitelist group of IPs that can access the database. By default, only 127.0.0.1 is allowed. We have to enter our VPC CIDR.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-31.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-31.png" alt="" width="509" height="193" class="aligncenter size-full wp-image-8514" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-31.png 509w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-31-300x114.png 300w" sizes="(max-width: 509px) 100vw, 509px" /></a><br />
Once you do that, you&#8217;ll see your RDS hostname.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-32.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-32.png" alt="" width="662" height="334" class="aligncenter size-full wp-image-8515" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-32.png 662w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-32-300x151.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-32-585x295.png 585w" sizes="(max-width: 662px) 100vw, 662px" /></a></p>
<h1>WordPress instances</h1>
<p>We&#8217;ll create two instances, install Apache + PHP, mount the NFS system and configure the web server. First, create two instances, each in a different zone. Use the section above for the NFS server. Name the servers <strong>web1 </strong>and <strong>web2 </strong>and assign the <strong>sgInstances </strong>security group to both of them. Make sure you choose <strong>Pay-As-You-Go</strong> model and assign public IPs so you can log in. And choose the SSH key pair that we created. Log to both of the instances.<br />
First, mount the NFS system. Replace the IP with the IP of your NFS server in the <strong>mount </strong>command. </p>
<pre class="brush: bash; title: ; notranslate">
yum -y install nfs-utils
mount 192.168.1.91:/nfs /var/www/html
echo &quot;192.168.1.91:/nfs       /var/www/html    nfs     defaults 0 0&quot; &gt;&gt; /etc/fstab
chown -R apache:apache /var/www/html
</pre>
<p>Then, check if you can reach the RDS MySQL server. You should receive some garbage.</p>
<pre class="brush: bash; highlight: [1,2]; title: ; notranslate">
yum -y install telnet
telnet rm-2evrh4h3aq9tk800z.mysql.rds.aliyuncs.com 3306
Trying 172.16.1.41...
Connected to rm-2evrh4h3aq9tk800z.mysql.rds.aliyuncs.com.
Escape character is '^]'.
N
5.7.20-log▒F5;I!]:p]H3R&#x5B;^mysql_native_password
</pre>
<p>Second, install Apache and all PHP modules on both servers. I&#8217;ll install PHP 5.4 because it&#8217;s already in the default repo. You should install PHP 7.x, it&#8217;s a little bit more work.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install httpd php php-common php-mysql php-gd php-xml php-mbstring php-mcrypt
systemctl enable httpd
systemctl start httpd
</pre>
<p>Now, we have to configure the Apache server. It&#8217;s a simple change in <strong>/etc/httpd/conf/httpd.conf</strong> file. You&#8217;ll probably want to use virtual hosts, but in interest of keeping this short, I&#8217;ll use a single site config. Find the directive that says #ServerName www.example.com:80 and remove the comment.</p>
<pre class="brush: bash; title: ; notranslate">
sed -i '/ServerName www/s/^#//g' /etc/httpd/conf/httpd.conf
</pre>
<h1>Load Balancer</h1>
<p>From the menu on the left, click on <strong>Server Load Balancer</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-33.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-33.png" alt="" width="232" height="337" class="aligncenter size-full wp-image-8516" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-33.png 232w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-33-207x300.png 207w" sizes="(max-width: 232px) 100vw, 232px" /></a><br />
Once the screen shows up, click on <strong>Create SLB Instance</strong>. Then choose the specs. Make sure it is in the same region with your instances and in the same zones (VSWitches). Name the load balancer too, e.g. <strong>lbWordPress</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-34.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-34.png" alt="" width="868" height="731" class="aligncenter size-full wp-image-8517" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-34.png 868w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-34-300x253.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-34-768x647.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-34-585x493.png 585w" sizes="(max-width: 868px) 100vw, 868px" /></a><br />
Once it&#8217;s ready, click on <strong>Add Backend Servers</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-35.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-35.png" alt="" width="1005" height="102" class="aligncenter size-full wp-image-8518" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-35.png 1005w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-35-300x30.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-35-768x78.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-35-585x59.png 585w" sizes="(max-width: 1005px) 100vw, 1005px" /></a><br />
From the list of the available servers, choose web1 and web2 in the <strong>Default Server Group</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-36.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-36.png" alt="" width="664" height="291" class="aligncenter size-full wp-image-8519" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-36.png 664w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-36-300x131.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-36-585x256.png 585w" sizes="(max-width: 664px) 100vw, 664px" /></a><br />
Click on <strong>Next: Set Weight and Port</strong> button and click <strong>OK</strong> to accept the defaults. Go back to the load balancer and this time click <strong>Configure Listener</strong> (above <strong>Add Backend Servers</strong>).<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-37.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-37.png" alt="" width="1063" height="134" class="aligncenter size-full wp-image-8520" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-37.png 1063w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-37-300x38.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-37-1024x129.png 1024w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-37-768x97.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-37-585x74.png 585w" sizes="(max-width: 1063px) 100vw, 1063px" /></a><br />
Choose HTTP traffic, port 80, click <strong>Modify </strong>next to <strong>Advanced </strong>and <strong>Enable Session Persistence</strong>. Click <strong>Next</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-38.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-38.png" alt="" width="640" height="511" class="aligncenter size-full wp-image-8521" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-38.png 640w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-38-300x240.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-38-585x467.png 585w" sizes="(max-width: 640px) 100vw, 640px" /></a><br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-39.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-39.png" alt="" width="394" height="208" class="aligncenter size-full wp-image-8522" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-39.png 394w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-39-300x158.png 300w" sizes="(max-width: 394px) 100vw, 394px" /></a><br />
On this screen click on <strong>Default Server Group</strong>, type port <strong>80 </strong>for the servers and click <strong>Next</strong>. You can accept the defaults in the next screen or make a change if you like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-40.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-40.png" alt="" width="1010" height="499" class="aligncenter size-full wp-image-8523" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-40.png 1010w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-40-300x148.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-40-768x379.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-40-585x289.png 585w" sizes="(max-width: 1010px) 100vw, 1010px" /></a><br />
Open a browser and go to your load balancer IP. It might take up a minute for the LB to configure so be patient if your browser is just sitting there.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-41.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-41.png" alt="" width="397" height="126" class="aligncenter size-full wp-image-8524" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-41.png 397w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-41-300x95.png 300w" sizes="(max-width: 397px) 100vw, 397px" /></a><br />
If you used my username and database names, fill out the config page like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2019/04/P130-42.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2019/04/P130-42.png" alt="" width="776" height="567" class="aligncenter size-full wp-image-8525" srcset="https://blog.andreev.it/wp-content/uploads/2019/04/P130-42.png 776w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-42-300x219.png 300w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-42-768x561.png 768w, https://blog.andreev.it/wp-content/uploads/2019/04/P130-42-585x427.png 585w" sizes="(max-width: 776px) 100vw, 776px" /></a><br />
&#8230;and pretty much that&#8217;s it.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2019/04/alibaba-cloud-centos-build-wordpress-site-using-nfs-rds-and-load-balancers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>FreeBSD: Install nginx &#8211; virtual hosts, PHP, MySQL and WordPress</title>
		<link>https://blog.andreev.it/2017/01/107-freebsd-install-nginx-virtual-hosts-php-mysql-wordpress/</link>
					<comments>https://blog.andreev.it/2017/01/107-freebsd-install-nginx-virtual-hosts-php-mysql-wordpress/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sun, 29 Jan 2017 15:40:02 +0000</pubDate>
				<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[virtual hosts]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=3030</guid>

					<description><![CDATA[I&#8217;ve decided to play with nginx to see how different is from Apache. The&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>I&#8217;ve decided to play with nginx to see how different is from Apache. The best way to experiment is to have an end goal, e.g. a working WordPress site. I will be using FreeBSD 11.0 and for that  I&#8217;ve created a public server in AWS cloud. The hostname for my server is <strong>test.iandreev.com</strong> and I also have 4 different hostnames that point to the same IP (test1, test2, test3 and test4).<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/01/P085-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/01/P085-01.png" alt="" width="1068" height="214" class="aligncenter size-full wp-image-7638" srcset="https://blog.andreev.it/wp-content/uploads/2017/01/P085-01.png 1068w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-01-300x60.png 300w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-01-1024x205.png 1024w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-01-768x154.png 768w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-01-585x117.png 585w" sizes="(max-width: 1068px) 100vw, 1068px" /></a></p>
<h1>Installation</h1>
<p>To install nginx, type:</p>
<pre class="brush: bash; title: ; notranslate">
pkg install nginx
</pre>
<p>Make sure it starts at boot by adding <strong>nginx_enable=&#8221;YES&#8221;</strong> in <strong>/etc/rc.conf</strong>.<br />
To see the version, type:</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
nginx -v
nginx version: nginx/1.10.2
</pre>
<p>To see the modules that were installed with the package, type:</p>
<pre class="brush: bash; title: ; notranslate">
nginx -V
</pre>
<p>You can start and stop the service with the standard <strong>service </strong>command. When making changes in the config file, use reload, e.g. <strong>service nginx reload</strong>.<br />
By default, nginx creates the log files under <strong>/var/log/nginx</strong>. There are two files, <strong>access.log</strong> and <strong>error.log</strong>. The config files are under <strong>/usr/local/etc/nginx</strong>. The main config file is <strong>nginx.conf</strong>.<br />
Let&#8217;s start the nginx.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
service nginx start
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Starting nginx.
</pre>
<p>If everything is OK, you can <strong>telnet localhost 80</strong>. Type something and hit ENTER and you&#8217;ll see a response. </p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
asdf
HTTP/1.1 400 Bad Request
Server: nginx/1.10.2
Date: Sun, 29 Jan 2017 13:56:04 GMT
Content-Type: text/html
Content-Length: 173
Connection: close

&lt;html&gt;
&lt;head&gt;&lt;title&gt;400 Bad Request&lt;/title&gt;&lt;/head&gt;
&lt;body bgcolor=&quot;white&quot;&gt;
&lt;center&gt;&lt;h1&gt;400 Bad Request&lt;/h1&gt;&lt;/center&gt;
&lt;hr&gt;&lt;center&gt;nginx/1.10.2&lt;/center&gt;
&lt;/body&gt;
&lt;/html&gt;
Connection closed by foreign host.
</pre>
<p>Check the nginx process.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
ps -waux | grep nginx
root     778   0.0  0.7 29640 6984  -  Is   13:55    0:00.00 nginx: master process /usr/local/sbin/nginx
www      779   0.0  0.7 29640 7452  -  I    13:55    0:00.00 nginx: worker process (nginx)
</pre>
<p>As you can see the master process runs as root, but then it forks the connections to the www user.</p>
<h1>Single host</h1>
<p>This is the easiest setup. You don&#8217;t have to do anything except the steps above. nginx works right out of the box with the default configuration. Go to http://server_IP_or_hostname and you&#8217;ll see the welcome page.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/01/P085-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/01/P085-02.png" alt="" width="555" height="227" class="aligncenter size-full wp-image-7639" srcset="https://blog.andreev.it/wp-content/uploads/2017/01/P085-02.png 555w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-02-300x123.png 300w" sizes="(max-width: 555px) 100vw, 555px" /></a><br />
But, this scenario has no real use, so we&#8217;ll create two virtual hosts, test1 and test2.</p>
<h1>Virtual hosts</h1>
<p>First, we&#8217;ll create the two directories for the virtual hosts and put some index files there. I use the same root directory as Apache. Make sure that the locations of the virtual hosts are owned by the user <strong>www </strong>and group <strong>www</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/www
mkdir test1.iandreev.com
mkdir test2.iandreev.com
echo &quot;test1&quot; &gt; test1.iandreev.com/index.htm
echo &quot;test2&quot; &gt; test2.iandreev.com/index.htm
chown -R www:www test*
</pre>
<p>Now, we have to edit the main config file and tell nginx where to look for these sites.<br />
Go to <strong>/usr/local/etc/nginx/</strong> and edit <strong>nginx.conf</strong>. Change the values for <strong>worker_processes</strong> from 1 to auto and uncomment <strong>gzip on</strong> directive. See what worker_processes mean <a href="http://nginx.org/en/docs/ngx_core_module.html#worker_processes" target="_blank" rel="noopener noreferrer">here</a>. By uncommenting gzip directive, you are enabling compression on the pages. To test if your web server serves compressed pages, check <a href="http://www.whatsmyip.org/http-compression-test/" target="_blank" rel="noopener noreferrer">this </a>website.<br />
Next, we have to add our two virtual hosts. Scroll all the way down, just before the last accolade &#8220;}&#8221; and add these lines.</p>
<pre class="brush: bash; title: ; notranslate">
    server {
        access_log /var/log/nginx/test1.iandreev.access.log;
        error_log  /var/log/nginx/test1.iandreev.error.log;
        listen 80;
        server_name     test1.iandreev.com;
        location / {
            root /usr/local/www/test1.iandreev.com;
            index index.htm index.html;
        }
    }
    server {
        access_log /var/log/nginx/test2.iandreev.access.log;
        error_log  /var/log/nginx/test2.iandreev.error.log;
        listen 80;
        server_name test2.iandreev.com;
        location / {
            root /usr/local/www/test2.iandreev.com;
            index index.htm index.html;
        }
    }
</pre>
<p>Reload the config with:</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
service nginx reload
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
</pre>
<p>and make sure everything is OK.<br />
If everything is OK, you should be able to browse to your virtual sites.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/01/P085-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/01/P085-03.png" alt="" width="298" height="166" class="aligncenter size-full wp-image-7640" /></a><br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/01/P085-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/01/P085-04.png" alt="" width="289" height="226" class="aligncenter size-full wp-image-7641" /></a></p>
<p>If you check one of the error logs, you&#8217;ll see an error that favicon.ico is missing for the site. You can ignore this as it&#8217;s not an error, it&#8217;s just a warning that you don&#8217;t have a favicon for your site.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
tail test2.iandreev.error.log
2017/01/29 14:18:59 &#x5B;error] 838#100084: *4 open() &quot;/usr/local/www/test2.iandreev.com/favicon.ico&quot; failed (2: No such file or directory), client: 240.14.17.24, server: test2.iandreev.com, request: &quot;GET /favicon.ico HTTP/1.1&quot;, host: &quot;test2.iandreev.com&quot;
</pre>
<p>You can get a favicon icon from <a href="http://www.freefavicon.com/freefavicons/objects/" target="_blank" rel="noopener noreferrer">this </a>website or you can generate one from <a href="http://www.favicon-generator.org/" target="_blank" rel="noopener noreferrer">this </a>one.</p>
<h1>nginx and PHP</h1>
<p>Unlike Apache and the php module, nginx is using PHP-FPM as a proxy to requests PHP dynamic code over FCGI protocol. PHP-FPM comes bundled with PHP, so let&#8217;s install php 5.6.</p>
<pre class="brush: bash; title: ; notranslate">
pkg install php56
</pre>
<p>Add this line in <strong>/etc/rc.conf</strong> so PHP-FPM starts on boot.</p>
<pre class="brush: bash; title: ; notranslate">
php_fpm_enable=&quot;YES&quot;
</pre>
<p>Create the <strong>php.ini</strong> file from <strong>php.ini-production</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini
</pre>
<p>Now, edit <strong>/usr/local/etc/php-fpm.conf</strong> and make these changes. Replace <strong>listen = 127.0.0.1:9000</strong> with <strong>listen = /var/run/php-fpm.sock</strong>. In addition, uncomment these three lines.</p>
<pre class="brush: bash; title: ; notranslate">
listen.owner = www
listen.group = www
listen.mode = 0660
</pre>
<p>Finally, start the php-fpm service.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
service php-fpm start
Performing sanity check on php-fpm configuration:
&#x5B;28-Jan-2017 23:41:31] NOTICE: configuration file /usr/local/etc/php-fpm.conf test is successful
</pre>
<p>Let&#8217;s create a test website that will serve PHP content.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/www
mkdir test3.iandreev.com
echo &quot;&lt;?php phpinfo(); ?&gt;&quot; &gt; test3.iandreev.com/index.php
chown -R www:www test3.iandreev.com
</pre>
<p>Add a new virtual host in nginx.</p>
<pre class="brush: bash; title: ; notranslate">
server {
        access_log /var/log/nginx/test3.iandreev.access.log;
        error_log  /var/log/nginx/test3.iandreev.error.log;
        listen       80;
        server_name  test3.iandreev.com;
        root /usr/local/www/test3.iandreev.com;
        index index.php index.html index.htm;
        location / {
            try_files $uri $uri/ =404;
        }
        error_page      500 502 503 504  /50x.html;
        location = /50x.html {
            root /usr/local/www/nginx-dist;
        }
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $request_filename;
                include fastcgi_params;
        }
    }
</pre>
<p>and reload the config changes.</p>
<pre class="brush: bash; title: ; notranslate">
service nginx reload
</pre>
<p>Go to your new virtual host, in my case http://test3.iandreev.com and you should see this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/01/P085-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/01/P085-05.png" alt="" width="1204" height="514" class="aligncenter size-full wp-image-7642" srcset="https://blog.andreev.it/wp-content/uploads/2017/01/P085-05.png 1204w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-05-300x128.png 300w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-05-1024x437.png 1024w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-05-768x328.png 768w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-05-1170x499.png 1170w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-05-585x250.png 585w" sizes="(max-width: 1204px) 100vw, 1204px" /></a></p>
<h1>nginx and WordPress</h1>
<p>Now that we have PHP support we can create a WordPress site. We&#8217;ll use MySQL as a DB backend. Please see my other <a href="https://blog.andreev.it/?p=1309#MySQL" target="_blank" rel="noopener noreferrer">post </a>on how to install MySQL first.<br />
Once you have the MySQL installed, create the database. Replace the values of <strong>wordpress</strong>, <strong>wpuser </strong>and <strong>secret </strong>to suit your needs.</p>
<pre class="brush: sql; title: ; notranslate">
CREATE DATABASE wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO &quot;wpuser&quot;@&quot;localhost&quot; IDENTIFIED BY &quot;secret&quot;;
FLUSH PRIVILEGES;
QUIT;
</pre>
<p>Install the following php modules, otherwise when you start WordPress you&#8217;ll be presented with a blank page.</p>
<pre class="brush: bash; title: ; notranslate">
pkg install php56-extensions php56-mysql php56-mysqli php56-xml php56-hash php56-gd php56-curl php56-tokenizer php56-zlib php56-zip
</pre>
<p>Download the latest WordPress install. If you don&#8217;t have wget, install it first with <strong>pkg install wget</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/www
wget www.wordpress.org/latest.zip --no-check-certificate
unzip latest.zip
mv wordpress test4.iandreev.com
chown -R www:www test4.iandreev.com
rm latest.zip
</pre>
<p>Add the following in nginx.conf to create the virtual host for the WordPress site.</p>
<pre class="brush: bash; title: ; notranslate">
server {
        access_log /var/log/nginx/test4.iandreev.access.log;
        error_log  /var/log/nginx/test4.iandreev.error.log;
        listen       80;
        server_name  test4.iandreev.com;
        root /usr/local/www/test4.iandreev.com;
        index index.php index.html index.htm;
        location / {
            try_files $uri $uri/ =404;
        }
        error_page      500 502 503 504  /50x.html;
        location = /50x.html {
            root /usr/local/www/nginx-dist;
        }
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $request_filename;
                include fastcgi_params;
        }
    }
</pre>
<p>Reload the config and restart php-fpm service.</p>
<pre class="brush: bash; title: ; notranslate">
service nginx reload
service php-fpm restart
</pre>
<p>Go to your website and you&#8217;ll be presented with the WordPress install page.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/01/P085-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/01/P085-06.png" alt="" width="574" height="823" class="aligncenter size-full wp-image-7643" srcset="https://blog.andreev.it/wp-content/uploads/2017/01/P085-06.png 574w, https://blog.andreev.it/wp-content/uploads/2017/01/P085-06-209x300.png 209w" sizes="(max-width: 574px) 100vw, 574px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2017/01/107-freebsd-install-nginx-virtual-hosts-php-mysql-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress: Execute custom code in a post without plugins</title>
		<link>https://blog.andreev.it/2016/09/96-wordpress-execute-custom-code-in-a-post-without-plugins/</link>
					<comments>https://blog.andreev.it/2016/09/96-wordpress-execute-custom-code-in-a-post-without-plugins/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Thu, 15 Sep 2016 19:50:51 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[execute command]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=2763</guid>

					<description><![CDATA[I wanted to run a custom code from a WordPress post and I was&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>I wanted to run a custom code from a WordPress post and I was looking around. I&#8217;ve found a nice plugin but it was running PHP only. It&#8217;s not that I needed more, but I stumbled when I tried to combine HTML elements and the PHP script with this plugin. So, at the end I&#8217;ve found a much more elegant solution, that pretty much runs any code. All I had to do is to embed the HTML page as an object.</p>
<p>So, let&#8217;s say I have a custom code in a PHP page called test.php that&#8217;s in the root of my WordPress installation. All is needed is this code in WordPress (use the Text tab, not Visual).</p>
<pre class="brush: xml; title: ; notranslate">
&lt;object data=&quot;https://blog.andreev.it/test.php&quot; width=&quot;800&quot; height=&quot;600&quot;&gt;&lt;/object&gt;
</pre>
<p><a href="https://blog.andreev.it/wp-content/uploads/2016/09/P075-01.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2016/09/P075-01.jpg" alt="" width="775" height="199" class="aligncenter size-full wp-image-7567" srcset="https://blog.andreev.it/wp-content/uploads/2016/09/P075-01.jpg 775w, https://blog.andreev.it/wp-content/uploads/2016/09/P075-01-300x77.jpg 300w, https://blog.andreev.it/wp-content/uploads/2016/09/P075-01-768x197.jpg 768w, https://blog.andreev.it/wp-content/uploads/2016/09/P075-01-585x150.jpg 585w" sizes="(max-width: 775px) 100vw, 775px" /></a><br />
And this is how my <strong>test.php</strong> page looks like. I won&#8217;t comment the code, but it has an input label and a button. Type a hostname and it will ping it and then render the output as an HTML array. </p>
<div style="border:1px solid red; padding:16px;">
<p style="text-align:center;"><strong><span style="color:#800000;">NOTE</span> </strong></p>
<p style="text-align:center;">If you are executing code that needs root access, this solution won&#8217;t work, because the code runs under the Apache username (which normally is not root).
</p>
</div>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE HTML&gt;
&lt;html&gt;
&lt;head&gt;
&lt;style&gt;
.error {color: #FF0000;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;?php
// define variables and set to empty values
$hostErr = &quot;&quot;;
$host = &quot;&quot;;

if ($_SERVER&#x5B;&quot;REQUEST_METHOD&quot;] == &quot;POST&quot;) {
  if (empty($_POST&#x5B;&quot;host&quot;])) {
    $host = &quot;Host is required&quot;;
  } else {
    $host = test_input($_POST&#x5B;&quot;host&quot;]);
    // only letters and numbers are allowed
    if (!preg_match(&quot;/^&#x5B;a-zA-Z0-9.]*$/&quot;,$host)) {
      $hostErr = &quot;Only letters and numbers allowed&quot;;
    }
  }
}

function test_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}
?&gt;

&lt;h2&gt;Online ping (ICMP) probe&lt;/h2&gt;
&lt;p&gt;&lt;span class=&quot;error&quot;&gt;* required field.&lt;/span&gt;&lt;/p&gt;
&lt;form method=&quot;post&quot; action=&quot;&lt;?php echo htmlspecialchars($_SERVER&#x5B;&quot;PHP_SELF&quot;]);?&gt;
&quot;&gt;
  Host: &lt;input type=&quot;text&quot; name=&quot;host&quot; value=&quot;&lt;?php echo $host;?&gt;&quot;&gt;
  &lt;span class=&quot;error&quot;&gt;* &lt;?php echo $hostErr;?&gt;&lt;/span&gt;
  &lt;br&gt;&lt;br&gt;
  &lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;Submit&quot;&gt;
&lt;/form&gt;

&lt;?php
        if(isset($_POST&#x5B;'submit']))
        {
                echo &quot;&lt;h2&gt;Output:&lt;/h2&gt;&quot;;
                echo $host;
                echo &quot;&lt;br&gt;&quot;;
                exec(&quot;ping -c 3 $host&quot;, $output, $status);
                echo '&lt;pre&gt;';
                print_r($output);
                echo '&lt;pre&gt;';

        }
?&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>The code in action. Type some host on the internet (e.g www.whatever.com), click the button and see the result. </p>
<p><object data="https://blog.andreev.it/ping.php" width="800" height="600"></object></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2016/09/96-wordpress-execute-custom-code-in-a-post-without-plugins/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWS: Create WordPress blog using the console and AWS CLI</title>
		<link>https://blog.andreev.it/2015/12/80-amazon-aws-create-wordpress-blog-using-the-console-and-cli/</link>
					<comments>https://blog.andreev.it/2015/12/80-amazon-aws-create-wordpress-blog-using-the-console-and-cli/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Fri, 11 Dec 2015 00:08:03 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[AWS CLI]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=2217</guid>

					<description><![CDATA[In this post I&#8217;ll describe how to create a fully functional WordPress blog on&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In this post I&#8217;ll describe how to create a fully functional WordPress blog on Amazon AWS. The blog will run on a server that can scale up or down depending on the load. The database will reside on Amazon RDS, not on a separate server. I&#8217;ll use both the AWS console and CLI to show how things work. Some of the steps are optional and you may choose more or less resources or redundancy and different type of security. See the following <a href="https://blog.andreev.it/?p=1905" target="_blank" rel="noopener noreferrer">post </a>if you plan to use CLI and you don&#8217;t have that configured. Do not execute the CLI commands if you created/deleted something from the console. It won&#8217;t work. Also, it won&#8217;t work if you just blindly copy and paste the CLI commands. Pretty much all of them are tied with unique ids for the AMIs, security groups, scaling groups&#8230; </p>
<h1>Security Groups</h1>
<p>First, we&#8217;ll create two security groups, <strong>sgBlogEC2 </strong>and <strong>sgBlogRDS</strong>. The first one will be used for the servers and the second one for the database. The first one will allow ports 22 (ssh) and port 80 (http) from anywhere and the second one will allow port 3306 from <strong>sgBlogEC2 </strong>only. This means that you can manage any of the VM servers from anywhere, the blog can be accessed from anywhere and the database can be accessed only from the servers. </p>
<p>Go to <strong>Compute </strong>| <strong>EC2</strong>.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-01.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-01.jpg" alt="" width="325" height="254" class="aligncenter size-full wp-image-7403" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-01.jpg 325w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-01-300x234.jpg 300w" sizes="(max-width: 325px) 100vw, 325px" /></a><br />
Then, under <strong>NETWORK &#038; SECURITY</strong>, click <strong>Security Groups</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-02.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-02.jpg" alt="" width="182" height="146" class="aligncenter size-full wp-image-7404" /></a><br />
Click on <strong>Create Security Group </strong>and fill the blanks. We&#8217;ll use the default VPC. Then, click <strong>Add Rule </strong>and add both rules for port 22 (ssh) and port 80 (http). Click <strong>Create </strong>when done.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-03.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-03.jpg" alt="" width="998" height="547" class="aligncenter size-full wp-image-7405" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-03.jpg 998w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-03-300x164.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-03-768x421.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-03-585x321.jpg 585w" sizes="(max-width: 998px) 100vw, 998px" /></a><br />
Do the same for the 2nd security group. This time add only port 3306 (MYSQL/Aurora) and for the source specify the Group ID of the first group that you&#8217;ve created.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-04.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-04.jpg" alt="" width="972" height="652" class="aligncenter size-full wp-image-7406" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-04.jpg 972w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-04-300x201.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-04-768x515.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-04-585x392.jpg 585w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-04-263x175.jpg 263w" sizes="(max-width: 972px) 100vw, 972px" /></a><br />
Using CLI, we have to find the default VPC ID first. </p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
aws ec2 describe-vpcs
{
    &quot;Vpcs&quot;: &#x5B;
        {
            &quot;VpcId&quot;: &quot;vpc-c2d645a6&quot;,
            &quot;InstanceTenancy&quot;: &quot;default&quot;,
            &quot;State&quot;: &quot;available&quot;,
            &quot;DhcpOptionsId&quot;: &quot;dopt-ca3593af&quot;,
            &quot;CidrBlock&quot;: &quot;172.31.0.0/16&quot;,
            &quot;IsDefault&quot;: true
        }
    ]
} 
</pre>
<p>In my case, the ID is <strong>vpc-c2d645a6</strong>. Now, we can create the groups.</p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 create-security-group --group-name sgBlogEC2 --description &quot;Security Group for the WordPress servers&quot; \ 
--vpc-id vpc-c2d645a6
aws ec2 create-security-group --group-name sgBlogRDS --description &quot;Security Group for the WordPress database&quot; \ 
--vpc-id vpc-c2d645a6
</pre>
<p>When you execute these commands, you&#8217;ll get the security group ID as an output. Get the <strong>GroupId</strong>, you&#8217;ll need them now. In my case, the <strong>GroupIds </strong>were <strong>sg-37535351 </strong>and <strong>sg-3b53535d</strong>. We have the groups created, but we need the inbound rules. </p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 authorize-security-group-ingress --group-id sg-37535351 --protocol tcp --port 22 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id sg-37535351 --protocol tcp --port 80 --cidr 0.0.0.0/0
</pre>
<p>    and for the second group</p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 authorize-security-group-ingress --group-id sg-3b53535d --protocol tcp --port 3306 --source-group sg-37535351
</pre>
<h1>Database</h1>
<p>WordPress requires a MySQL compatible database to work. We can install the database on the WordPress server, but if we want to use more than one server in a load-balanced configuration, this scenario won&#8217;t work. So, we&#8217;ll just use a database instance separate from the servers. </p>
<p>From the main AWS menu, go to <strong>Database </strong>| <strong>RDS</strong>. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-05.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-05.jpg" alt="" width="308" height="230" class="aligncenter size-full wp-image-7407" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-05.jpg 308w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-05-300x224.jpg 300w" sizes="(max-width: 308px) 100vw, 308px" /></a><br />
Click on <strong>Instances </strong>and then <strong>Launch DB Instance</strong>.</p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-06.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-06.jpg" alt="" width="503" height="252" class="aligncenter size-full wp-image-7408" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-06.jpg 503w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-06-300x150.jpg 300w" sizes="(max-width: 503px) 100vw, 503px" /></a><br />
I&#8217;ll be using MariaDB, but you can choose Amazon Aurora or MySQL.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-07.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-07.jpg" alt="" width="889" height="641" class="aligncenter size-full wp-image-7409" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-07.jpg 889w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-07-300x216.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-07-768x554.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-07-585x422.jpg 585w" sizes="(max-width: 889px) 100vw, 889px" /></a><br />
On the next screen, Amazon recommends to use Multi-AZ deployment and PIOPS for production databases. The benefit is that if one zone goes down, you&#8217;ll still have your database running in the other zone. And the PIOPS is just a faster SSD. I don&#8217;t need any of these so I&#8217;ll go with the Free Usage Tier option.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-08.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-08.jpg" alt="" width="774" height="389" class="aligncenter size-full wp-image-7410" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-08.jpg 774w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-08-300x151.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-08-768x386.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-08-585x294.jpg 585w" sizes="(max-width: 774px) 100vw, 774px" /></a><br />
On this screen, you have to specify the details for the database, such as the resources (in my case 1CPU, 1GB RAM), 5GB of storage (you&#8217;ll probably need 10 or more GB) and the username and password that will have full access to the instance.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-09.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-09.jpg" alt="" width="749" height="730" class="aligncenter size-full wp-image-7411" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-09.jpg 749w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-09-300x292.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-09-585x570.jpg 585w" sizes="(max-width: 749px) 100vw, 749px" /></a><br />
In the advanced settings dialog, make sure you choose your default VPC, disable the public access, choose the security group that we created for this database and name the database.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-10.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-10.jpg" alt="" width="575" height="656" class="aligncenter size-full wp-image-7412" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-10.jpg 575w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-10-263x300.jpg 263w" sizes="(max-width: 575px) 100vw, 575px" /></a><br />
I&#8217;ve used the defaults for the backup options.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-11.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-11.jpg" alt="" width="735" height="318" class="aligncenter size-full wp-image-7413" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-11.jpg 735w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-11-300x130.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-11-585x253.jpg 585w" sizes="(max-width: 735px) 100vw, 735px" /></a><br />
If you click on View DB Instance and then on the magnifying glass icon, you&#8217;ll see that the endpoint is not yet available.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-12.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-12.jpg" alt="" width="947" height="533" class="aligncenter size-full wp-image-7414" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-12.jpg 947w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-12-300x169.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-12-768x432.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-12-585x329.jpg 585w" sizes="(max-width: 947px) 100vw, 947px" /></a><br />
Wait for a couple of minutes until the endpoint shows up. We&#8217;ll need this when we install WordPress. </p>
<p>Using CLI, you can accomplish the same.</p>
<pre class="brush: bash; title: ; notranslate">
aws rds create-db-instance \
--db-instance-identifier dbiWordPress \
--db-name dbWordPress \
--allocated-storage 5 \
--db-instance-class db.t2.micro \
--engine MariaDB \
--vpc-security-group-ids sg-3b53535d \
--master-username db_owner \
--master-user-password T0pS3cr3tP4ssw0rd \
--storage-type gp2 \
--no-publicly-accessible \
--no-multi-az
</pre>
<p>This is what we need when we install WordPress.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-13.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-13.jpg" alt="" width="754" height="409" class="aligncenter size-full wp-image-7415" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-13.jpg 754w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-13-300x163.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-13-585x317.jpg 585w" sizes="(max-width: 754px) 100vw, 754px" /></a></p>
<h1>Key Pairs</h1>
<p>If you already have a SSH key pair that you want to use, you can skip this step. If not, continue reading. </p>
<p>Go to <strong>Compute </strong>| <strong>EC2</strong><br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-14.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-14.jpg" alt="" width="325" height="254" class="aligncenter size-full wp-image-7416" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-14.jpg 325w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-14-300x234.jpg 300w" sizes="(max-width: 325px) 100vw, 325px" /></a><br />
Then, under <strong>NETWORK &#038; SECURITY</strong>, click <strong>Key Pairs</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-15.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-15.jpg" alt="" width="188" height="145" class="aligncenter size-full wp-image-7417" /></a><br />
Click on <strong>Create Key Pair</strong> and enter the name. I used <strong>kpWordPressEC2</strong>. Save the provided .pem file somewhere. You&#8217;ll need this file to access the servers using ssh. </p>
<p>Using AWS CLI, you can create the key pair using the following command.</p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 create-key-pair --key-name kpWordPressEC2 --query &quot;KeyMaterial&quot; --output text &gt; kpWordPress.pem
</pre>
<p>If you open this file, which is basically a text file, you&#8217;ll see something like this. </p>
<pre class="brush: plain; title: ; notranslate">
-----BEGIN RSA PRIVATE KEY-----
EXAMPLEKEYKCAQEAy7WZhaDsrA1W3mRlQtvhwyORRX8gnxgDAfRt/gx42kWXsT4rXE/b5CpSgie/
vBoU7jLxx92pNHoFnByP+Dc21eyyz6CvjTmWA0JwfWiW5/akH7iO5dSrvC7dQkW2duV5QuUdE0QW
Z/aNxMniGQE6XAgfwlnXVBwrerrQo+ZWQeqiUwwMkuEbLeJFLhMCvYURpUMSC1oehm449ilx9X1F
G50TCFeOzfl8dqqCP6GzbPaIjiU19xX/azOR9V+tpUOzEL+wmXnZt3/nHPQ5xvD2OJH67km6SuPW
oPzev/D8V+x4+bHthfSjR9Y7DvQFjfBVwHXigBdtZcU2/wei8D/HYwIDAQABAoIBAGZ1kaEvnrqu
/uler7vgIn5m7lN5LKw4hJLAIW6tUT/fzvtcHK0SkbQCQXuriHmQ2MQyJX/0kn2NfjLV/ufGxbL1
mb5qwMGUnEpJaZD6QSSs3kICLwWUYUiGfc0uiSbmJoap/GTLU0W5Mfcv36PaBUNy5p53V6G7hXb2
bahyWyJNfjLe4M86yd2YK3V2CmK+X/BOsShnJ36+hjrXPPWmV3N9zEmCdJjA+K15DYmhm/tJWSD9
81oGk9TopEp7CkIfatEATyyZiVqoRq6k64iuM9JkA3OzdXzMQexXVJ1TLZVEH0E7bhlY9d8O1ozR
oQs/FiZNAx2iijCWyv0lpjE73+kCgYEA9mZtyhkHkFDpwrSM1APaL8oNAbbjwEy7Z5Mqfql+lIp1
YkriL0DbLXlvRAH+yHPRit2hHOjtUNZh4Axv+cpg09qbUI3+43eEy24B7G/Uh+GTfbjsXsOxQx/x
p9otyVwc7hsQ5TA5PZb+mvkJ5OBEKzet9XcKwONBYELGhnEPe7cCgYEA06Vgov6YHleHui9kHuws
ayav0elc5zkxjF9nfHFJRry21R1trw2Vdpn+9g481URrpzWVOEihvm+xTtmaZlSp//lkq75XDwnU
WA8gkn6O3QE3fq2yN98BURsAKdJfJ5RL1HvGQvTe10HLYYXpJnEkHv+Unl2ajLivWUt5pbBrKbUC
gYBjbO+OZk0sCcpZ29sbzjYjpIddErySIyRX5gV2uNQwAjLdp9PfN295yQ+BxMBXiIycWVQiw0bH
oMo7yykABY7Ozd5wQewBQ4AdSlWSX4nGDtsiFxWiI5sKuAAeOCbTosy1s8w8fxoJ5Tz1sdoxNeGs
Arq6Wv/G16zQuAE9zK9vvwKBgF+09VI/1wJBirsDGz9whVWfFPrTkJNvJZzYt69qezxlsjgFKshy
WBhd4xHZtmCqpBPlAymEjr/TOlbxyARmXMnIOWIAnNXMGB4KGSyl1mzSVAoQ+fqR+cJ3d0dyPl1j
jjb0Ed/NY8frlNDxAVHE8BSkdsx2f6ELEyBKJSRr9snRAoGAMrTwYneXzvTskF/S5Fyu0iOegLDa
NWUH38v/nDCgEpIXD5Hn3qAEcju1IjmbwlvtW+nY2jVhv7UGd8MjwUTNGItdb6nsYqM2asrnF3qS
VRkAKKKYeGjkpUfVTrW0YFjXkfcrR/V+QFL5OndHAKJXjW7a4ejJLncTzmZSpYzwApc=
-----END RSA PRIVATE KEY-----
</pre>
<p>Follow this <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/putty.html" target="_blank" rel="noopener noreferrer">article </a>on how to connect to your AWS EC2 instances. </p>
<h1>Servers</h1>
<p>Now that we have the database ready, we&#8217;ll go ahead and create one server that will be used as a template. I&#8217;ll use the Amazon Linux AMI, which is based on Red Hat 6. </p>
<p>Go to <strong>Compute </strong>| <strong>EC2</strong><br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-16.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-16.jpg" alt="" width="325" height="254" class="aligncenter size-full wp-image-7418" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-16.jpg 325w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-16-300x234.jpg 300w" sizes="(max-width: 325px) 100vw, 325px" /></a><br />
Click on <strong>Instances </strong>under <strong>Instances</strong> and then click <strong>Launch Instance</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-17.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-17.jpg" alt="" width="215" height="325" class="aligncenter size-full wp-image-7419" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-17.jpg 215w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-17-198x300.jpg 198w" sizes="(max-width: 215px) 100vw, 215px" /></a><br />
Choose the first choice, Amazon Linux AMI, then choose the type (I&#8217;ll use the t2.micro), accept the defaults for the instance.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-18.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-18.jpg" alt="" width="880" height="583" class="aligncenter size-full wp-image-7420" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-18.jpg 880w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-18-300x199.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-18-768x509.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-18-780x516.jpg 780w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-18-585x388.jpg 585w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-18-263x175.jpg 263w" sizes="(max-width: 880px) 100vw, 880px" /></a><br />
Specify the amount of storage you want. I used 8GB which is more than enough because the database is not on the servers.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-19.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-19.jpg" alt="" width="1190" height="240" class="aligncenter size-full wp-image-7421" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-19.jpg 1190w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-19-300x61.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-19-1024x207.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-19-768x155.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-19-1170x236.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-19-585x118.jpg 585w" sizes="(max-width: 1190px) 100vw, 1190px" /></a><br />
Tag the instance if you want and make sure you select the security group that we created for the servers.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-20.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-20.jpg" alt="" width="1243" height="781" class="aligncenter size-full wp-image-7422" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-20.jpg 1243w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-20-300x188.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-20-1024x643.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-20-768x483.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-20-1170x735.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-20-585x368.jpg 585w" sizes="(max-width: 1243px) 100vw, 1243px" /></a><br />
Choose the key pair and launch the instance.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-21.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-21.jpg" alt="" width="697" height="426" class="aligncenter size-full wp-image-7424" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-21.jpg 697w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-21-300x183.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-21-585x358.jpg 585w" sizes="(max-width: 697px) 100vw, 697px" /></a></p>
<p>Using AWS CLI, the same thing can be accomplished with:</p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 run-instances --image-id ami-60b6c60a --security-group-ids sg-37535351 --count 1 \ 
--instance-type t2.micro --key-name kpWordPressEC2
</pre>
<p>We will need the public IP for the server. From the console, click the newly created server and you&#8217;ll see the public IP.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-22.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-22.jpg" alt="" width="1009" height="588" class="aligncenter size-full wp-image-7425" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-22.jpg 1009w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-22-300x175.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-22-768x448.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-22-585x341.jpg 585w" sizes="(max-width: 1009px) 100vw, 1009px" /></a><br />
Or, type:</p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 describe-instances
</pre>
<p>and look for &#8220;<strong>PublicIp</strong>&#8221; line. </p>
<h1>DNS &#8211; Route 53</h1>
<p>The blog that I will create will reside at <strong>blog.andreev.us</strong>. We need to create a DNS record that will point this child domain to the IP of the server that we just built. Use your domain management panel to change this. I purchased my domain (andreev.us) through GoDaddy, but I can still delegate the subdomain blog.andreev.us to be managed from Route 53. All you have to do is tell GoDaddy or whatever your domain hosting company is, to look for this subdomain somewhere else. This is how my domain management panel at GoDaddy looks like. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-23.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-23.jpg" alt="" width="897" height="286" class="aligncenter size-full wp-image-7426" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-23.jpg 897w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-23-300x96.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-23-768x245.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-23-585x187.jpg 585w" sizes="(max-width: 897px) 100vw, 897px" /></a><br />
Back to AWS, go to <strong>Networking </strong>and then click <strong>Route 53</strong>. Click on <strong>Create Hosted Zone</strong>. Fill the blanks with your blog&#8217;s name and click <strong>Create</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-24.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-24.jpg" alt="" width="468" height="306" class="aligncenter size-full wp-image-7427" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-24.jpg 468w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-24-300x196.jpg 300w" sizes="(max-width: 468px) 100vw, 468px" /></a></p>
<p>You will get your hosted zone and you&#8217;ll see your Name Servers. These are the servers that you want to put under your domain management panel if you purchased your domain somewhere else.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-25.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-25.jpg" alt="" width="657" height="383" class="aligncenter size-full wp-image-7428" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-25.jpg 657w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-25-300x175.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-25-585x341.jpg 585w" sizes="(max-width: 657px) 100vw, 657px" /></a><br />
You are not finished yet. You just created your zone and got your name servers, but they have no clue where the actual host is. What you have to do now is to create an <strong>A </strong>record. Click on <strong>Create Record Set</strong> and put the IP of the server there.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-26.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-26.jpg" alt="" width="494" height="513" class="aligncenter size-full wp-image-7429" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-26.jpg 494w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-26-289x300.jpg 289w" sizes="(max-width: 494px) 100vw, 494px" /></a><br />
Once you create your A record, wait between 5 mins and 30 mins and make sure that your domain resolves to your IP. The easiest way is to ping. You won&#8217;t get a response, which is fine, but you <strong>should </strong>get the IP. </p>
<pre class="brush: vb; highlight: [1]; title: ; notranslate">
ping blog.andreev.us
Pinging blog.andreev.us &#x5B;52.90.209.108] with 32 bytes of data:
Request timed out.
</pre>
<p>And doing the same thing with AWS CLI.</p>
<pre class="brush: bash; title: ; notranslate">
aws route53 create-hosted-zone --name blog.andreev.us --hosted-zone-config Comment=&quot;blog.andreev.us&quot; \ 
--caller-reference 2015-12-09-14:00
</pre>
<p>If you look at the output, you&#8217;ll see your Zone Id that looks like this.</p>
<pre class="brush: bash; title: ; notranslate">
&quot;Id&quot;: &quot;/hostedzone/Z3F33MZHA3FTIL&quot;,
</pre>
<p>Now, add the A record with this command.</p>
<pre class="brush: bash; title: ; notranslate">
aws route53 change-resource-record-sets --hosted-zone-id Z3F33MZHA3FTIL --change-batch file://C:\add-record.json
</pre>
<p>but before running the command create a file called <strong>add-record.json</strong> and add the following inside. Replace the IP and the domain name with yours. </p>
<pre class="brush: bash; title: ; notranslate">
{
  &quot;Comment&quot;: &quot;Adding A record&quot;,
  &quot;Changes&quot;: &#x5B;
    {
      &quot;Action&quot;: &quot;CREATE&quot;,
      &quot;ResourceRecordSet&quot;: {
        &quot;Name&quot;: &quot;blog.andreev.us&quot;,
        &quot;Type&quot;: &quot;A&quot;,
        &quot;TTL&quot;: 300,
        &quot;ResourceRecords&quot;: &#x5B;
          {
            &quot;Value&quot;: &quot;52.90.209.108&quot;
          }
        ]
      }
    }
  ]
}
</pre>
<h1>WordPress installation</h1>
<p>Once you have your instance up and running, ssh to it and log as <strong>ec2-user</strong>. If you are using some other OS flavor, the username ec2-user might not apply. Also, the following steps differ between various Linux/BSD systems. I&#8217;ll describe how to install Apache, PHP and WordPress on AWS Linux AMI. The procedure is the same for Red Hat 6 and CentOS 6, but differs for FreeBSD, Fedora, Ubuntu, etc&#8230;</p>
<p>First, install the Apache web server and PHP.</p>
<pre class="brush: bash; title: ; notranslate">
sudo yum install httpd php php-zlib php-iconv php-gd php-mbstring php-fileinfo php-curl php-mysql  
</pre>
<p>Let&#8217;s make sure Apache starts on boot.</p>
<pre class="brush: bash; title: ; notranslate">
sudo chkconfig httpd on
</pre>
<p>We need to make some configuration changes to the web server. Go to the Apache config directory and edit the configuration file <strong>httpd.conf</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/httpd/conf 
sudo vi httpd.conf
</pre>
<p>Scroll all the way down (Shift + G) and add the following lines at the very end. My test blog will be called <strong>blog.andreev.us</strong> and I am creating a virtual web directory for that. You have to replace this with your blog name.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;VirtualHost *:80&gt;
     ServerAdmin klimenta@andreev.us
     DocumentRoot /var/www/blog.andreev.us
     ServerName blog.andreev.us
     ErrorLog logs/blog.andreev.us-error_log
     CustomLog logs/blog.andreev.us-access_log combined 
&lt;/VirtualHost&gt;
</pre>
<p>Let&#8217;s download WordPress install file, unzip it and start the web server. </p>
<pre class="brush: bash; title: ; notranslate">
cd /var/www
sudo wget www.wordpress.org/latest.zip
sudo unzip latest.zip
sudo rm latest.zip
sudo mv wordpress blog.andreev.us
sudo chown -R apache:apache blog.andreev.us 
sudo apachectl start
</pre>
<p>After this, you can access your blog. Go to http://blog.whatever.com or whatever you named your blog and you should see the WordPress page. Fill up the blanks with the values that we got previously. Your DB host name is the endpoint.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-27.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-27.jpg" alt="" width="880" height="596" class="aligncenter size-full wp-image-7430" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-27.jpg 880w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-27-300x203.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-27-768x520.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-27-585x396.jpg 585w" sizes="(max-width: 880px) 100vw, 880px" /></a><br />
Congrats! You have your WordPress blog on AWS now. But, we have a lot of other cool features to implement. </p>
<h1>Creating AMI</h1>
<p>Now that we have the blog up and running, just create a new post and publish it. The posts and comments are stored in the database, but if you decide to change a theme you have to know that the themes and plugins are stored on the local file system. We plan to run the blog on multiple servers based on a template, so once we create the template, anytime you decide to change your theme, you&#8217;ll have to create a new AMI. So, before creating the AMI template, do all of your customization and install all plugins that you intend to use.</p>
<p>Let&#8217;s create the template now. The server will reboot when creating a template. Go to the EC2 dashboard, right click on the server, click <strong>Image </strong>then <strong>Create Image</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-28.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-28.jpg" alt="" width="808" height="402" class="aligncenter size-full wp-image-7431" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-28.jpg 808w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-28-300x149.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-28-768x382.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-28-585x291.jpg 585w" sizes="(max-width: 808px) 100vw, 808px" /></a><br />
Enter a name, description and choose the size of the disk.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-29.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-29.jpg" alt="" width="1011" height="535" class="aligncenter size-full wp-image-7432" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-29.jpg 1011w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-29-300x159.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-29-768x406.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-29-585x310.jpg 585w" sizes="(max-width: 1011px) 100vw, 1011px" /></a><br />
After a minute, you can see your AMI (template) under IMAGES | AMIs.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-30.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-30.jpg" alt="" width="1190" height="451" class="aligncenter size-full wp-image-7433" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-30.jpg 1190w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-30-300x114.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-30-1024x388.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-30-768x291.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-30-1170x443.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-30-585x222.jpg 585w" sizes="(max-width: 1190px) 100vw, 1190px" /></a><br />
When the <strong>status </strong>is <strong>available</strong>, you can go ahead and terminate your original instance. We won&#8217;t need it, because we&#8217;ll go ahead and use auto scaling to create the new servers from the template.</p>
<p>Using AWS CLI you can create a template with:</p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 describe-instances
</pre>
<p>Get the <strong>InstanceId</strong> from the output above and create an AMI with:</p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 create-image --instance-id i-f2022a42 --name &quot;Word Press Template&quot; --description &quot;AMI for WordPress Blog&quot; 
</pre>
<p>Make sure that you&#8217;ve deleted the original instance and that your blog is not accessible before going to the next step. </p>
<h1>Auto Scaling</h1>
<p>Go to <strong>EC2</strong> | <strong>AUTO SCALING</strong> | <strong>Launch Configurations</strong>. Click on <strong>Create Auto Scaling group</strong>. If you don&#8217;t have a launch configuration, you&#8217;ll have to create one. Click on <strong>Create launch configuration</strong>. When you see a list of a bunch of AMIs, click on My AMIs on the left.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-31.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-31.jpg" alt="" width="1198" height="423" class="aligncenter size-full wp-image-7434" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-31.jpg 1198w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-31-300x106.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-31-1024x362.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-31-768x271.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-31-1170x413.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-31-585x207.jpg 585w" sizes="(max-width: 1198px) 100vw, 1198px" /></a><br />
Select the AMI that you&#8217;ve created, choose resources (I&#8217;ll use t2.micro) and then name your <strong>Launch Configuration</strong> . Click on <strong>Next: Add Storage</strong></p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-32.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-32.jpg" alt="" width="847" height="321" class="aligncenter size-full wp-image-7435" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-32.jpg 847w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-32-300x114.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-32-768x291.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-32-585x222.jpg 585w" sizes="(max-width: 847px) 100vw, 847px" /></a><br />
Specify the size of the storage for the AMI (I used 8GB which is the default) and choose the security group for the EC2 servers that we created.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-33.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-33.jpg" alt="" width="1251" height="769" class="aligncenter size-full wp-image-7436" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-33.jpg 1251w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-33-300x184.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-33-1024x629.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-33-768x472.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-33-1170x719.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-33-585x360.jpg 585w" sizes="(max-width: 1251px) 100vw, 1251px" /></a><br />
Click on <strong>Review</strong> to check for any errors and then click on <strong>Create launch configuration</strong>. Select the key pair and create the <strong>Launch Configuration</strong>. You&#8217;ll be immediately redirected to create the <strong>Auto Scaling Group</strong>. In my case, I just named the group and used all of the available subnets in that region.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-34.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-34.jpg" alt="" width="992" height="468" class="aligncenter size-full wp-image-7437" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-34.jpg 992w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-34-300x142.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-34-768x362.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-34-585x276.jpg 585w" sizes="(max-width: 992px) 100vw, 992px" /></a><br />
Select <strong>Use scaling policies to adjust the capacity of this group</strong> and change to scale between 1 and 2 or whatever instances you like to have max.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-35.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-35.jpg" alt="" width="794" height="212" class="aligncenter size-full wp-image-7438" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-35.jpg 794w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-35-300x80.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-35-768x205.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-35-585x156.jpg 585w" sizes="(max-width: 794px) 100vw, 794px" /></a></p>
<p>For the Auto Scaling policy, where it says <strong>Take the action</strong> change 0 to 1, so you&#8217;ll be adding/removing 1 instance depending on the load. I also named my policies spIncrease and spDecrease. Click on <strong>Add New alarm</strong> under <strong>Increase Group Size.</strong><br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-36.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-36.jpg" alt="" width="1191" height="548" class="aligncenter size-full wp-image-7439" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-36.jpg 1191w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-36-300x138.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-36-1024x471.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-36-768x353.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-36-1170x538.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-36-585x269.jpg 585w" sizes="(max-width: 1191px) 100vw, 1191px" /></a><br />
Uncheck the notification checkmark if you don&#8217;t want to receive notifications (email, pager&#8230;) whenever there is a change in the number of instances and put 80 for the threshold. Name the alarm and click on <strong>Create Alarm</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-37.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-37.jpg" alt="" width="928" height="432" class="aligncenter size-full wp-image-7440" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-37.jpg 928w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-37-300x140.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-37-768x358.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-37-585x272.jpg 585w" sizes="(max-width: 928px) 100vw, 928px" /></a><br />
Do the same for the <strong>Decrease Group Size</strong>. This time use less or equal 30 percent as shown below.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-38.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-38.jpg" alt="" width="917" height="433" class="aligncenter size-full wp-image-7441" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-38.jpg 917w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-38-300x142.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-38-768x363.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-38-585x276.jpg 585w" sizes="(max-width: 917px) 100vw, 917px" /></a><br />
Or, this means, whenever the average CPU utilizations of all instance is greater or equal than 80%, add another instance. When the same average CPU utilization is less or equal than 30%, remove one instance. Sudden burst of CPU utilization won&#8217;t have any effect, because the utilization has to last 5 minutes. If you have more than 10 instances, you don&#8217;t add one or two instances whenever there is a change in the utilization. Instead you add a percentage of the total number of the instances. For example if you have 20 instances, you won&#8217;t add one extra instance. It won&#8217;t make any difference. You&#8217;ll add 20% of the instances, which is four.</p>
<p>OK, click next and if you want to receive notifications when the resources are added or removed, you can configure them here, but I&#8217;ll skip this step. Click next and use the tags if you want to and finally click <strong>Review</strong>  and then <strong>Create Auto Scaling group</strong>. If you go to the EC2 Dashboard, you&#8217;ll see that one server already started. That&#8217;s because we have specified a minimum of one server. </p>
<p>Using AWS CLI, we can create the launch configuration first. Make sure you specify the ID of your AMI that we created.</p>
<pre class="brush: bash; title: ; notranslate">
aws autoscaling create-launch-configuration --launch-configuration-name lcWordPress --image-id ami-176f267d \ 
--instance-type t2.micro --security-groups sg-37535351
</pre>
<p>In order to create an auto scaling group, we&#8217;ll need to know the subnets. Look for <strong>SubnetId</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
aws ec2 describe-subnets
</pre>
<p>Create the auto scaling group.</p>
<pre class="brush: bash; title: ; notranslate">
aws autoscaling create-auto-scaling-group --auto-scaling-group-name asgWordPress --launch-configuration-name \ 
lcWordPress --min-size 1 --max-size 2 --vpc-zone-identifier \ 
&quot;subnet-994e5eb2,subnet-1d40fb20,subnet-fb01cd8d,subnet-3c876164&quot;
</pre>
<p>Create the scaling policies.</p>
<pre class="brush: bash; title: ; notranslate">
aws autoscaling put-scaling-policy --auto-scaling-group-name asgWordPress --policy-name spIncrease \ 
--scaling-adjustment 1 --adjustment-type ChangeInCapacity
aws autoscaling put-scaling-policy --auto-scaling-group-name asgWordPress --policy-name spDecrease \ 
--scaling-adjustment -1 --adjustment-type ChangeInCapacity
</pre>
<p>The output of these two commands will be two <strong>PolicyARN</strong>s. One looks like this.</p>
<pre class="brush: bash; title: ; notranslate">
{
    &quot;PolicyARN&quot;: &quot;arn:aws:autoscaling:us-east-1:076270756661:scalingPolicy:d1d03
001-c9a6-4097-bd41-dc1a27ab7286:autoScalingGroupName/asgWordPress:policyName/spD
ecrease&quot;
}
</pre>
<p>Make sure you get them both, because we&#8217;ll need them now when we create the alarm and associate it with the policy.</p>
<pre class="brush: bash; title: ; notranslate">
c:\&gt;aws cloudwatch put-metric-alarm --alarm-name alWordPress-High-CPU-Utilization --metric-name CPUUtilization \ 
--namespace AWS/EC2 --statistic Average --period 600 --threshold 80 \ 
--comparison-operator GreaterThanOrEqualToThreshold --dimensions &quot;Name=AutoScalingGroupName,Value=asgWordPress&quot; \
--evaluation-periods 1 --alarm-actions arn:aws:autoscaling:us-east-1:076270756661:scalingPolicy:830f183a-585d
4b8ea1c26f3c0581021c:autoScalingGroupName/asgWordPress:policyName/spIncrease
</pre>
<p>where 600 is 5 minutes. See the parameters when we did the same from the console. Do the same for the second policy with the seconds PolicyARN.</p>
<h1>CloudWatch</h1>
<p>Go to the AWS home page, click on <strong>CloudWatch</strong> and then look under <strong>Alarms</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-39.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-39.jpg" alt="" width="613" height="309" class="aligncenter size-full wp-image-7442" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-39.jpg 613w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-39-300x151.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-39-585x295.jpg 585w" sizes="(max-width: 613px) 100vw, 613px" /></a><br />
If the instance is running less than 5 min, the alarms should be under <strong>INSUFFICIENT</strong>. Click on the label <strong>INSUFFICIENT</strong> or <strong>OK</strong>. If you click to <strong>Modify</strong> one of the alarms, you&#8217;ll see the same threshold and actions that we defined before. This is actually where you create new alarms and modify existing ones and change the actions needed.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-40.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-40.jpg" alt="" width="929" height="692" class="aligncenter size-full wp-image-7443" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-40.jpg 929w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-40-300x223.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-40-768x572.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-40-585x436.jpg 585w" sizes="(max-width: 929px) 100vw, 929px" /></a></p>
<h1>Testing the scaling</h1>
<p>Go to the <strong>Auto Scaling Groups</strong> menu, click on <strong>Scaling Policies</strong>, then click on <strong>Actions</strong> and then click <strong>Execute</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-41.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-41.jpg" alt="" width="1228" height="784" class="aligncenter size-full wp-image-7444" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-41.jpg 1228w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-41-300x192.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-41-1024x654.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-41-768x490.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-41-1170x747.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-41-585x373.jpg 585w" sizes="(max-width: 1228px) 100vw, 1228px" /></a><br />
Enter any number that&#8217;s greater than 80 and wait for 5 minutes. We&#8217;ll kick the policy that says, add another instance if the average CPU utilization is greater than 80 and it lasts for more than 5 mins.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-42.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-42.jpg" alt="" width="549" height="185" class="aligncenter size-full wp-image-7445" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-42.jpg 549w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-42-300x101.jpg 300w" sizes="(max-width: 549px) 100vw, 549px" /></a><br />
After 5 mins, you&#8217;ll see another instance showing up. You don&#8217;t have to do anything. The instance will remove itself after another 5 mins, because the actual usage is less than 30% (that was the 2nd policy).</p>
<p>Using CLI:</p>
<pre class="brush: bash; title: ; notranslate">
aws autoscaling execute-policy --auto-scaling-group-name asgWordPress --policy-name spIncrease \ 
--metric-value 95 --breach-threshold 80
</pre>
<h1>Elastic Load Balancer</h1>
<p>Now that we have a scaling policy working, we can create the Load Balancer. </p>
<p>From the EC2 menu, click on <strong>Load Balancers </strong>under <strong>LOAD BALANCING</strong>.<br />
Click on <strong>Create Load Balancer</strong> and name it. Leave the port 80.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-43.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-43.jpg" alt="" width="1248" height="427" class="aligncenter size-full wp-image-7446" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-43.jpg 1248w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-43-300x103.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-43-1024x350.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-43-768x263.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-43-1170x400.jpg 1170w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-43-585x200.jpg 585w" sizes="(max-width: 1248px) 100vw, 1248px" /></a><br />
Assign the security group for the servers. NOTE: A proper way would be to create a new security group for the load balancer and then modify the server security group to accept port 80 only from that LB security group, very similar with what we did with the RDS security group.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-44.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-44.jpg" alt="" width="860" height="383" class="aligncenter size-full wp-image-7447" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-44.jpg 860w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-44-300x134.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-44-768x342.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-44-585x261.jpg 585w" sizes="(max-width: 860px) 100vw, 860px" /></a><br />
Skip step 3 and remove <strong>index.html</strong> under <strong>Ping Path</strong> on step 4.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-45.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-45.jpg" alt="" width="701" height="429" class="aligncenter size-full wp-image-7448" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-45.jpg 701w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-45-300x184.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-45-585x358.jpg 585w" sizes="(max-width: 701px) 100vw, 701px" /></a><br />
You can skip step 5, we don&#8217;t need to add the instances yet. Same with step 6, skip. Click <strong>Review and Create</strong> and then click <strong>Create</strong>. Once the LB is created, look for the DNS name under the description tab.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-46.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-46.jpg" alt="" width="1012" height="543" class="aligncenter size-full wp-image-7449" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-46.jpg 1012w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-46-300x161.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-46-768x412.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-46-585x314.jpg 585w" sizes="(max-width: 1012px) 100vw, 1012px" /></a><br />
Now, we have to associate our Auto Scaling Group with the Load Balancer. Go to the <strong>Auto Scaling Group </strong>menu, notice how the <strong>Load Balancers </strong>entry is blank and click <strong>Edit </strong>to fix it.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-47.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-47.jpg" alt="" width="1044" height="651" class="aligncenter size-full wp-image-7450" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-47.jpg 1044w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-47-300x187.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-47-1024x639.jpg 1024w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-47-768x479.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-47-585x365.jpg 585w" sizes="(max-width: 1044px) 100vw, 1044px" /></a><br />
Click anywhere on the blank line and our load balancer will show up. Click <strong>Save</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-48.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-48.jpg" alt="" width="671" height="256" class="aligncenter size-full wp-image-7451" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-48.jpg 671w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-48-300x114.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-48-585x223.jpg 585w" sizes="(max-width: 671px) 100vw, 671px" /></a><br />
Go back to the <strong>Load Balancers</strong> menu and click on the <strong>Instances</strong> tab.<br />
Wait for 2-3 minutes and the status should turn into <strong>InService</strong>. If it says OutOfService, you&#8217;ll have to investigate. The easiest way is to ssh to the server and check the log files for the Apache. If you scroll all the way up, you&#8217;ll see that we defined the log files for our web site.</p>
<pre class="brush: bash; title: ; notranslate">
ErrorLog logs/blog.andreev.us-error_log
CustomLog logs/blog.andreev.us-access_log combined 
</pre>
<p>Look at the access log and you&#8217;ll see that every 30 seconds there is a hit from the load balancer. If the return code is not 200, which is OK in HTML, then you have to troubleshoot.</p>
<p>And the same thing with AWS CLI.</p>
<pre class="brush: bash; title: ; notranslate">
aws elb create-load-balancer --load-balancer-name lbWordPress \ 
--listeners &quot;Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=80&quot; \ 
--security-groups sg-37535351 --subnets subnet-3c876164 subnet-fb01cd8d subnet-1d40fb20 subnet-994e5eb2
</pre>
<p>Configure LB health-check.</p>
<pre class="brush: bash; title: ; notranslate">
aws elb configure-health-check --load-balancer-name lbWordPress \ 
--health-check Target=HTTP:80/,Interval=30,UnhealthyThreshold=2,HealthyThreshold=10,Timeout=5
</pre>
<p>Associate the Auto Scaling Group with the Load Balancer.</p>
<pre class="brush: bash; title: ; notranslate">
aws autoscaling attach-load-balancers --load-balancer-names lbWordPress --auto-scaling-group-name asgWordPress
</pre>
<h1>Final change</h1>
<p>Now that everything is up &#038; running, we just have to point the DNS record of blog.andreev.us to point to the load balancer.</p>
<p>Go to Route 53 console, select the domain name, select your <strong>A</strong> record, click on <strong>Yes</strong> for the <strong>Alias</strong> and select the DNS name for the load balancer from the drop down <strong>Alias Target</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/12/P060-49.jpg"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/12/P060-49.jpg" alt="" width="1012" height="423" class="aligncenter size-full wp-image-7454" srcset="https://blog.andreev.it/wp-content/uploads/2015/12/P060-49.jpg 1012w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-49-300x125.jpg 300w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-49-768x321.jpg 768w, https://blog.andreev.it/wp-content/uploads/2015/12/P060-49-585x245.jpg 585w" sizes="(max-width: 1012px) 100vw, 1012px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2015/12/80-amazon-aws-create-wordpress-blog-using-the-console-and-cli/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CentOS: Install LAMP (Linux, Apache, MySQL, PHP) + WordPress on CentOS 7</title>
		<link>https://blog.andreev.it/2015/05/centos-7-install-lamp-linux-apache-mysql-php-wordpress/</link>
					<comments>https://blog.andreev.it/2015/05/centos-7-install-lamp-linux-apache-mysql-php-wordpress/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sun, 31 May 2015 20:49:07 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[LAMP]]></category>
		<category><![CDATA[MySQL PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=1962</guid>

					<description><![CDATA[In one of my previous posts, I&#8217;ve explained how to install LAMP on CentOS&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>In one of my previous <a href="https://blog.andreev.it/?p=1010" target="_blank" rel="noopener noreferrer">posts</a>, I&#8217;ve explained how to install LAMP on CentOS 6.4. Things changed a little bit in version 7, because of <a href="http://www.freedesktop.org/wiki/Software/systemd/" target="_blank" rel="noopener noreferrer">systemd</a>.</p>
<h1>Hostname</h1>
<p>First, let&#8217;s verify that we have a valid hostname and that it resolves properly. Type:</p>
<pre class="brush: bash; title: ; notranslate">
hostname
</pre>
<p>and make sure you have the FQDN of your server. If not, edit <strong>/etc/hostname</strong> and enter it there. In my case, it will be master.iandreev.us</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
cat /etc/hostname
master.iandreev.us
</pre>
<p><strong>NOTE: Highlighted numbers are what you type. The rest is the response from the server. </strong><br />
Restart the service, so the changes take effect if you changed your hostname.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart systemd-hostnamed
</pre>
<h1>Install Apache</h1>
<p>Apache can be installed by executing:</p>
<pre class="brush: bash; title: ; notranslate">
yum install httpd
</pre>
<p>Once installed, go to <strong>/etc/httpd/conf</strong> and edit <strong>httpd.conf</strong>. This is the main configuration file for Apache. Change and remove the comment (#) from the following directives, <strong>ServerAdmin </strong>and <strong>ServerName</strong>. In my case it looks like this.</p>
<pre class="brush: bash; title: ; notranslate">
ServerAdmin klimenta@iandreev.us
ServerName master.iandreev.us
</pre>
<p>This command will enable Apache to start on boot.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl enable httpd
</pre>
<p>This command will start Apache</p>
<pre class="brush: bash; title: ; notranslate">
systemctl start httpd
</pre>
<p>Now, let&#8217;s test Apache from the server. Type the following command and then some text:</p>
<pre class="brush: bash; highlight: [1,5]; title: ; notranslate">
telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is &#039;^]&#039;.
asdfd
&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML 2.0//EN&quot;;&gt;
&lt;html&gt;&lt;head&gt;
&lt;title&gt;501 Not Implemented&lt;/title&gt;
&lt;/head&gt;&lt;body&gt;
&lt;h1&gt;Not Implemented&lt;/h1&gt;
&lt;p&gt;asdfd to / not supported.&lt;br /&gt;
&lt;/p&gt;
&lt;/body&gt;&lt;/html&gt;
Connection closed by foreign host.
</pre>
<p>If you see the response like above, you are OK. If not check the log files under <strong>/var/log/httpd</strong>.<br />
Now, from a browser on another computer, go to your server IP or name, in my case http://master.iandreev.us. Nothing will happen. That&#8217;s because there is a firewall enabled.<br />
Check the firewall status.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
systemctl status firewalld
firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled)
   Active: active (running) since Sun 2015-05-31 13:49:37 UTC; 5h 37min ago
 Main PID: 403 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─403 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

May 31 13:49:36 master.iandreev.us systemd&#x5B;1]: Starting firewalld - dynamic ....
May 31 13:49:37 master.iandreev.us systemd&#x5B;1]: Started firewalld - dynamic f....
May 31 13:57:04 master.iandreev.us systemd&#x5B;1]: Started firewalld - dynamic f....
Hint: Some lines were ellipsized, use -l to show in full.
</pre>
<p>Let&#8217;s poke a hole for Apache. We&#8217;ll verify that the public zone is the default first, then add the http service to be allowed, then reload the rules and finally list the allowed services.</p>
<pre class="brush: bash; highlight: [1,3,5,7]; title: ; notranslate">
firewall-cmd --get-default-zone
public
firewall-cmd --add-service=http --permanent
success
firewall-cmd --reload
success
firewall-cmd --list-services
dhcpv6-client http ssh
</pre>
<p>You can also check the rules with:</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
iptables -L -n | grep 80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 ctstate NEW
</pre>
<p>If you go to your page now, you&#8217;ll see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/05/P054-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/05/P054-01.png" alt="" width="1256" height="632" class="aligncenter size-full wp-image-7351" srcset="https://blog.andreev.it/wp-content/uploads/2015/05/P054-01.png 1256w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-01-300x151.png 300w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-01-1024x515.png 1024w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-01-768x386.png 768w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-01-1170x589.png 1170w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-01-585x294.png 585w" sizes="(max-width: 1256px) 100vw, 1256px" /></a></p>
<h2>Apache Virtual hosts</h2>
<p>The scenario described above works fine but only if you plan to run one single server. If you want to host different web apps, you&#8217;ll have to configure virtual hosts. The module for virtual hosts is enabled by default, so we&#8217;ll just have to define the virtual hosts. Go to <strong>/etc/httpd/conf.d</strong> and create a file called <strong>httpd-vhosts.conf</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
cd /etc/httpd/conf.d
touch httpd-vhosts.conf
</pre>
<p>We&#8217;ll define two virtual hosts (<strong>blog.iandreev.us</strong> and <strong>mail.iandreev.us</strong>). Consider these URLs as two different web applications. Make sure that you have both of these hosts in the DNS so they resolve to the same IP of your server. Apache knows that these hosts are different by analyzing host headers. In my case <strong>httpd-vhosts.conf</strong> looks like this.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;VirtualHost *:80&gt;
    ServerAdmin klimenta@iandreev.us
    DocumentRoot &quot;/var/www/blog.iandreev.us&quot;
    ServerName blog.iandreev.us
    ErrorLog &quot;/var/log/httpd/blog.iandreev.us-error_log&quot;
    CustomLog &quot;/var/log/httpd/blog.iandreev.us-access_log&quot; common
    &lt;Directory &quot;/var/www/blog.iandreev.us&quot;&gt;
        Options All
        AllowOverride All
        Require all granted
    &lt;/Directory&gt;
&lt;/VirtualHost&gt;
&lt;VirtualHost *:80&gt;
    ServerAdmin klimenta@iandreev.us
    DocumentRoot &quot;/var/www/mail.iandreev.us&quot;
    ServerName mail.iandreev.us
    ErrorLog &quot;/var/log/httpd/mail.iandreev.us-error_log&quot;
    CustomLog &quot;/var/log/httpd/mail.iandreev.us-access_log&quot; common
    &lt;Directory &quot;/var/www/mail.iandreev.us&quot;&gt;
        Options All
        AllowOverride All
        Require all granted
    &lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p>It&#8217;s pretty much self-explanatory, you have the server name, the location of log files, the root directories for the servers, admin&#8217;s e-mail etc.<br />
Now, let&#8217;s create the two web sites. For each web-site I&#8217;ll specify a simple text file, just so you can see the difference.</p>
<pre class="brush: bash; title: ; notranslate">
cd /var/www
mkdir blog.iandreev.us mail.iandreev.us
echo &quot;blog.iandreev.us&quot;&gt; blog.iandreev.us/index.html
echo &quot;mail.iandreev.us&quot;&gt; mail.iandreev.us/index.html
chown -R apache:apache blog.iandreev.us/ mail.iandreev.us/
chmod -R 755 blog.iandreev.us/ mail.iandreev.us/
systemctl reload httpd
</pre>
<p>So, I&#8217;ve created two root directories, then created two text files that will be the main page for each site and finally I changed the owner and permissions. At the end, I&#8217;ve restarted Apache because we made changes to the configuration file for the virtual hosts.<br />
Now, go to each of these web sites, in my case http://blog.iandreev.us and http://mail.iandreev.us and you&#8217;ll see that the main page is different. </p>
<h2>SSL virtual hosts</h2>
<p>First, we have to install mod_ssl and restart Apache.</p>
<pre class="brush: bash; title: ; notranslate">
yum install mod_ssl
apachectl restart
</pre>
<p>SSL uses certificates to test the authenticity, so you can buy one or for the purpose of testing, you can generate your own fake certificate authority (CA), request a certificate from the CA and then sign it.<br />
Let&#8217;s say that we want another virtual host called https://test.iandreev.us that will run on port 443.<br />
Let&#8217;s generate the certificate.</p>
<pre class="brush: bash; title: ; notranslate">
openssl genrsa -out test.iandreev.us.key 1024
openssl req -new -key test.iandreev.us.key -out test.iandreev.us.csr
openssl x509 -req -days 365 -in test.iandreev.us.csr -signkey test.iandreev.us.key -out test.iandreev.us.crt
</pre>
<p>Fill out the questions asked. The most important thing is “Common Name (eg, your name or your server’s hostname)”. Enter the FQDN of the domain in our case test.iandreev.us. The file with the .crt extension is your server certificate. Copy the certificate file *.crt under <strong>/etc/pki/tls/certs</strong> directory and copy the key file under <strong>/etc/pki/tls/private</strong>.<br />
The definition for the SSL virtual hosts have the same structure as regular hosts on port 80, except that you have to specify the certificate path and the key path. Also, you have to specify the port 443, very similar to a regular host.<br />
In our case, it will be.</p>
<pre class="brush: bash; title: ; notranslate">
&lt;VirtualHost *:443&gt;
        SSLEngine on
        SSLCertificateFile /etc/pki/tls/certs/test.iandreev.us.crt
        SSLCertificateKeyFile /etc/pki/tls/private/test.iandreev.us.key
        ServerAdmin klimenta@iandreev.us
        DocumentRoot /var/www/test.iandreev.us
        ServerName test.iandreev.us
        ErrorLog logs/test.iandreev.us-error_log combined
        CustomLog logs/test.iandreev.us-access_log combined
&lt;/VirtualHost&gt;
</pre>
<p>See above (firewall-cmd &#8211;add-service=https &#8211;permanent &#038;&#038; firewall-cmd &#8211;reload) how to open a firewall port. Replace <strong>service=http</strong> with <strong>service=https</strong> and you are all set. </p>
<h1>MySQL or MariaDB</h1>
<p>We&#8217;ll use MariaDB which is a drop-in binary replacement for MySQL.</p>
<pre class="brush: bash; title: ; notranslate">
yum install mariadb-server mariadb
systemctl enable mariadb
systemctl start mariadb
mysql_secure_installation
</pre>
<p>The first command installs the server and the client, the second line enables the server to start on boot, the third line starts the server and the fourth line configures MySQL/MariaDB for the first time.<br />
Check my previous post. MySQL initial config is exactly the same.<br />
There is no need to allow MySQL/MariaDB outside, so we won&#8217;t configure the firewall for MySQL.</p>
<h1>PHP</h1>
<p>We will install PHP and the MySQL module for PHP using:</p>
<pre class="brush: bash; title: ; notranslate">
yum install php php-mysql php-extensions php-curl php-zlib
</pre>
<p>Restart Apache after that.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart httpd
</pre>
<p>BTW, you can also use <strong>apachectl </strong>command to start, stop or reload Apache. The syntax is <strong>apachectl stop</strong> or <strong>apachectl start</strong>, etc&#8230;<br />
Now, let&#8217;s go to one of the virtual hosts that we created earlier and create a small PHP file.</p>
<pre class="brush: bash; title: ; notranslate">
cd /var/www/blog.iandreev.us
echo &quot;&lt;?php phpinfo(); ?&gt;&quot;&gt; index.php
</pre>
<p>If you go to your web-site now, you&#8217;ll see something like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/05/P054-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/05/P054-02.png" alt="" width="618" height="593" class="aligncenter size-full wp-image-7352" srcset="https://blog.andreev.it/wp-content/uploads/2015/05/P054-02.png 618w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-02-300x288.png 300w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-02-585x561.png 585w" sizes="(max-width: 618px) 100vw, 618px" /></a><br />
Congrats, if you made it, now you have a full LAMP stack installed. To see a working example, we&#8217;ll install WordPress. Pretty much all web-apps based on PHP are installed this way. You configure your virtual host, create the database and point your browser to the install or index file. The rest is just simple configuration.</p>
<h1>WordPress</h1>
<p>Let&#8217;s delete our blog directory first.</p>
<pre class="brush: bash; title: ; notranslate">
cd /var/www
rm -Rf blog.iandreev.us
</pre>
<p>Get the latest WordPress install file.</p>
<pre class="brush: bash; title: ; notranslate">
wget http://www.wordpress.org/latest.zip
</pre>
<p>The default CentOS doesn&#8217;t come up with unzip, so get unzip first and then unpack the archive.</p>
<pre class="brush: bash; title: ; notranslate">
yum install unzip
unzip latest.zip
</pre>
<p>You&#8217;ll see a directory called wordpress. Just rename it so it becomes a root folder for the virtual host.<br />
In my case, I&#8217;ll rename the <strong>wordpress </strong>folder to <strong>blog.iandreev.us</strong>, because that&#8217;s what I have as a <strong>DocumentRoot </strong>in my config file for the virtual hosts.</p>
<pre class="brush: bash; title: ; notranslate">
mv wordpress blog.iandreev.us
chown -R apache:apache blog.iandreev.us
</pre>
<p>Let&#8217;s create the required database. We&#8217;ll specify the database name (<strong>wordpress</strong>), the user that will have owner rights (<strong>wpuser</strong>) and its password (<strong>secret</strong>).</p>
<pre class="brush: bash; title: ; notranslate">
mysql -u root -p
</pre>
<p>Type your root password and then type the following SQL commands.</p>
<pre class="brush: sql; title: ; notranslate">
CREATE DATABASE wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO &quot;wpuser&quot;@&quot;localhost&quot; IDENTIFIED BY &quot;secret&quot;;
FLUSH PRIVILEGES;
QUIT;
</pre>
<p>Go to http://blog.iandreev.us, choose the default language and when prompted enter the values that you used when you created the database.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2015/05/P054-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2015/05/P054-03.png" alt="" width="733" height="486" class="aligncenter size-full wp-image-7353" srcset="https://blog.andreev.it/wp-content/uploads/2015/05/P054-03.png 733w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-03-300x199.png 300w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-03-585x388.png 585w, https://blog.andreev.it/wp-content/uploads/2015/05/P054-03-263x175.png 263w" sizes="(max-width: 733px) 100vw, 733px" /></a><br />
Click <strong>Submit</strong>, then <strong>Run Install</strong> and you are all set.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2015/05/centos-7-install-lamp-linux-apache-mysql-php-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress: Migrating WordPress site from one server to another</title>
		<link>https://blog.andreev.it/2014/11/migrating-wordpress-site-from-one-server-to-another/</link>
					<comments>https://blog.andreev.it/2014/11/migrating-wordpress-site-from-one-server-to-another/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Wed, 05 Nov 2014 15:10:29 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=1591</guid>

					<description><![CDATA[First, make sure that you have Apache, PHP and MySQL (MariaDB) installed and properly&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>First, make sure that you have Apache, PHP and MySQL (MariaDB) installed and properly configured. In order to avoid any problems down the road, make sure that you have the same version of the software. There are some WordPress plugins that allow you to backup/restore the database and the content, but we&#8217;ll do this manually.  </p>
<p>Let&#8217;s say that I want to migrate <strong>www.iandreev.com</strong> from one server to another. First, change the DNS so the hostname points to the new IP. Create a test HTML file and see that you can actually browse to the new web site. Once completed, stop the Apache web server and MySQL database on the old server. Go to the root folder where your WordPress installation is and open the <strong>wp-config.php</strong> file. These are the values that you will need.  </p>
<pre class="brush: sql; title: ; notranslate"> 
/** The name of the database for WordPress */ 
define('DB_NAME', 'wwwiandreevcom'); 
/** MySQL database username */ 
define('DB_USER', 'username); 
/** MySQL database password */ 
define('DB_PASSWORD', 'password'); 
/** MySQL hostname */ 
define('DB_HOST', 'localhost'); 
</pre>
<p>Backup this database with: </p>
<pre class="brush: bash; title: ; notranslate">
mysqldump -u &lt;username&gt;  -p &lt;password&gt; databasename &gt; /somewhere/dbname.sql 
</pre>
<p><em>Note: Don&#8217;t leave a space between &#8220;-p&#8221; and the password. </em></p>
<p>Once you have the database backed up, transfer it to the new server using <strong>scp</strong> or whatever you use to transfer files between servers. In my case I typed this command on the old server. </p>
<pre class="brush: bash; title: ; notranslate">
scp wwwiandreevcom.sql myusername@www.iandreev.com: 
</pre>
<p>Where <strong>wwwiandreevcom.sql</strong> is the backup file, <strong>myusername</strong> is the username that I use on both servers and <strong>www.iandreev.com</strong> is the new server hostname. </p>
<p>Create the database on the new server and grant necessary rights. </p>
<pre class="brush: sql; title: ; notranslate">
create database wwwiandreevcom; 
grant all privileges on wwwiandreevcom.* to &quot;username&quot;@&quot;localhost&quot; identified by &quot;password&quot;; 
flush privileges; 
</pre>
<p>Make sure that the database name, username, password and host are the same as on the old server.<br />
Now, restore the database. </p>
<pre class="brush: sql; title: ; notranslate">
mysql -u username -p wwwiandreevcom &lt; wwwiandreevcom.sql 
</pre>
<p>Where <strong>wwwiandreevcom</strong> is the database being restored and <strong>wwwiandreevcom.sql</strong> is the dump file of the database that we transferred from the old server.  </p>
<p>There is no need to install WordPress from scratch on the new server, so go back to the old server and compress the WordPress installation folder.  </p>
<pre class="brush: bash; title: ; notranslate">
tar czvf zipfile.tgz www.iandreev.com 
</pre>
<p>Where <strong>www.iandreev.com</strong> is my WordPress installation directory. Transfer the tarball to the new server. </p>
<pre class="brush: bash; title: ; notranslate">
scp zipfile.tgz myusername@www.iandreev.com: 
</pre>
<p>Move the file where your new installation will be and unpack it.  </p>
<pre class="brush: bash; title: ; notranslate">
tar xvf zipfile.tgz 
</pre>
<p>Make sure to change the owner to the user that runs Apache if needed. In my case I had to do: </p>
<pre class="brush: bash; title: ; notranslate">
chown -R www:www www.iandreev.com 
</pre>
<p>That&#8217;s it. Go to www.whatever.com and you&#8217;ll see your website/blog back in action.<br />
<strong>Note: If you receive the following error:</strong></p>
<pre class="brush: bash; title: ; notranslate">
Your PHP installation appears to be missing the MySQL extension which is required by WordPress.
</pre>
<p>Then install the following Apache modules and restart Apache.</p>
<pre class="brush: bash; title: ; notranslate">
pkg install php5-pdo_mysql
apachectl graceful
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2014/11/migrating-wordpress-site-from-one-server-to-another/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
