Choose Language

Mateusz Marchel

I'm doing PHP development since 2012. I'm passionate about new technologies and for couple years I like WordPress very much. If you think that I can help you, please send me an e-mail. I love new challenges!

Privately I have beautiful wife Edyta, I like good music and I play guitar in my free time.

Archives

Tag: Series

Series summary

In this series my goal was to give you information sufficient to launch your own WordPress on AWS EC2 platform. I wanted to keep balance between detailed descriptions of what and why I do something, and length of the posts. Do i made it? I hope that you give me some feedback in comments below. I’ll do my best to take your opinion into account when I’ll be writing next posts.

What we have done?

We lunched new EC2 instance

We done some basic configuration of our system

We talked a bit about security

We installed Apache, PHP-FPM and MySQL

We talked a bit about WP-CLI, createed new MySQL database and installed WordPress

We investigated what and why not working correctly and we solve those issues

In fact it’s quite a lot! 🙂
However I must say, that this series omitted some things. We doesn’t talk about further optimization, backup strategies or versioning. There is also so much more to say in subject of security. If you want to use this system in production environment you should do some more work but this is out of scope of this series so i won’t dive into this topic. Below i present list of terms you can search for. As I wrote in introduction: if you know how to do something better or just have another opinion about something, please leave your comment. I’m constantly learning and improving my skill set so I’ll be happy to look on something from different point of view than mine.

What else need your WordPress?

WordPress use some additional modules for Apache and PHP. Unfortunately I haven’t found many information about what is actually needed and for what purpose. There are some articles on this subject, but they’re quite old. In this section I’ll show you couple of WordPress features which don’t work in our environment and how to fix it.

Pretty URLs

So let’s begin with turning on preety URLs. This feature help us make our URLs more readable and SEO friendly. In our WordPress Dashboard find tab Settings->Permalinks. There let’s choose one of option we like and save settings. Let’s go back to home page and try to click on post title. Whoops…

In this case the problem is disabled rewrite module in Apache. Let’s enable it:

1

2

sudo a2enmod rewrite

sudo service apache2 restart

Much better now. 🙂

wp_mail

In previous part I wrote that our WordPress can’t send emails and I suggest installing plugin which allows us send messages through SMTP. Let’s install it then from dashboard. We can of course do it also using WP-CLI or upload files manually. Before we proceed to plugin installation, let’s install first another PHP module. It’s not necessary now because WordPress can work without it, but some plugins could not.

1

2

3

sudo apt-get install php5-curl

sudo php5enmod curl

sudo service php5-fpm restart

Okay, now we can install Easy WP SMTP (or any other with similar functionality). Configuration is very straightforward – just like configuration any e-mail client like Outlook or Thunderbird.

This plugin have feature which help us examine if everything is correct by sending test email. If you’re using another plugin which doesn’t have this kind of functionality you can for example change password for your user. WordPress should automatically send e-mail with information about password change to e-mail address attached to your account.

Images scaling and cropping

When we upload image to our WordPress media library, they are automatically processed and we can use different image sizes in our posts. Additionally we can use built-in image editor which help us crop image for example. So at least it should work that way but now if we try to put image into post we can use only full image size.

This is because we don’t have PHP module called imagick. Let’s install it then. We’ll also install module called GD. In fact for WordPress itself imagick is sufficient, but some plugins could use GD for image manipulation.

1

2

3

sudo apt-get install php5-gd php5-imagick

sudo php5enmod gd imagick

sudo service php5-fpm restart

Now if you upload new image it should be possible to use different image sizes and built-in image editor.

Additional modules

Some plugins are using module called mcrypt so we can install it by the way:

1

2

3

sudo apt-get install php5-mcrypt

sudo php5enmod mcrypt

sudo service php5-fpm restart

This set of extensions should be sufficient in most cases.

So we actually done. In last part I’ll summarize everything what we’ve done and make some additional comments.

WordPress installation

In this part we install WordPress itself on our environment. I’ll use for this purpose WP-CLI. It’s very handy tool for managing WordPress from command line. If you haven’t hear about WP-CLI I recommend to do some research on it.

In this part I assume that you own domain name for your WordPress. You should change A record for your domain to reflect IP address of your instance. Remember that such change could be visible after couple of hours. If you have any doubts about this process, contact with your service provider.

Apache Virtual Host

We’ll start from writing another piece of configuration. For now our server is configured to serve files from /var/www/html for every request. We can change it with virtual host configuration. We can then route users which are comes to our machine to different places based on some predefined criteria. The most common way of segregating users is domain name which user types in address bar of his browser. We can then add new configuration for our WordPress website. I will use domain wordpress.marchel.it. Let’s create configuration file. You can name it anything you want but file should ends with “.conf”.

sudo nano /etc/apache2/sites-available/wordpress-marchel-it.conf

wordpress-marchel-it.conf

1

2

3

4

5

6

7

8

9

10

11

12

<VirtualHost *:80>

ServerName wordpress.marchel.it

ServerAlias www.wordpress.marchel.it

DocumentRoot /var/www/wordpress-marchel-it/public_html

<Directory /var/www/wordpress-marchel-it/public_html>

Options -Indexes +FollowSymLinks

AllowOverride All

Require all granted

</Directory>

</VirtualHost>

What is going on here?VirtualHost opens section where we’ll define all settings about our virtual host. Asterisk symbol means that we check for connections that are coming through any IP address that is attached to our server (in our case there’s only one public IP, but could be more). Colon i separator and number 80 is port number for HTTP service, where our server are pending connections.ServerName is used for identification that this is the host for which browser is asking. It should be just your domain name.ServerAlias gives us possibility of defining additional Server Names. In example above I’ve added www prefix so if someone will enter address with this prefix in his browser, server will know that following rules also applies here.DocumentRoot is used to define root directory for our site. I came up with /var/www/wordpress-marchel-it/public_html. This path of course should exists so let’s create it and give it appropriate permissions.

First two lines obviously creates directories. In third line we changed owner of public_html directory for www-data user. We also assigned this directory to www-data group. Owner of files should be user with which privileges all PHP scripts will be running. In our case this user is www-data. Without this settings we won’t be able for example to install plugins directly from dashboard.

Warning!
If you running more than one site on your server this kind of configuration can by dangerous! In this case you should consider creating user for every application which owns this application files and with which privileges application will be running.

In last line we changed permissions for public_html directory. It’s available for read, write and execute for owner and group.

Directory opens section where we can configure some options for provided path.Options give us ability to turn on or off some additional server features. In this case we turn off directory listing – if some folder doesn’t contain index file, it won’t be listed and instead of that error 403 will be returned – access forbidden. Additionally we set ability to follow symlinks which will be needed for pretty urls in WordPress.AllowOverride All give us ability to overwrite server settings with .htaccess files which WordPress use.Require All Granted permit anyone to have read access to folder which is obviously needed if we want to publish our website.

We can save this file and we’ll back to it in a while.

PHP-CLI and WP-CLI installation

Installed previously PHP version works only with Apache server. We can’t manually run PHP script from terminal. Because WP-CLI is written in PHP we should provide environment in which we can use it. This time there won’t be painful configuration. Just one line:

sudo apt-get install php5-cli

Great! Let’s download WP-CLI following instructions on project website. It’s worth to change directory to your home directory if you are somewhere else (you can do it by running command cd ~/).

Now it’s good to make WP-CLI globally accessible so we need to give it execution permission and move it to directory which is included in PATH variable.

1

2

chmod +x wp-cli.phar

sudo mv wp-cli.phar /usr/local/bin/wp

Now if you run command wp --info you should see the same result.

Creating new MySQL database.

Last step before WordPress installation is to create empty database where our blog will store all of it’s data. Let’s do this then. We should log in as root to our MySQL server. We can do this like this:

1

mysql -u root -p

This means that we are logging in as user root and we’ll be asked for password which we are previously defined during installation process.

First one creates database named db_name with utf8mb4 charset. You can find very good explanation of character encoding subject here.

Second grants all permissions to manage database called “db_name” to user called “user_name” which authenticates with password “password” . If this user doesn’t exists it will be created.

Third query reload privileges. Just for sure.

Next we exit MySQL console with simple command exit.

Time for WordPress

Finally we came to what this series is all about so to the WordPress installation. As I mention before we use WP-CLI for this purpose. We have already create directory where we want to install our blog, so change our working directory to this folder. In my case it will be:

1

cd /var/www/wordpress-marchel-it/public_html

Now we need to download WordPress files:

1

wp core download

If you want to look closer to some WP-CLI command you can add word help at the beginning, for example wp help core, or wp help core download. Above command will download newest version of WordPress with en_US language pack. If you want to download another language version (Polish for instance) you can add parameter –locale=pl_PL

Now we need to generate wp-config.php file, where among others database credentials will be stored. We should provide at least database name, database user and password. By default for all tables prefix wp_ will be used but we can of course change this by adding appropriate arguments.

In URL filed we should provide address where our blog will be publicly available. For me it’s wordpress.marchel.it.title is simply title of our site. If you have spaces in it you should enclose it with double quotes.admin_user is field where we can set name for our useradmin_password will set up password for our useradmin_email is email address which will be used for administrative purposes

During installation probably you’ve seen this information:

sh: 1: /usr/sbin/sendmail: not found

It means only that software used by WordPress to sending emails is not installed in our system. I won’t cover in this tutorial configuration of sendmail which is default transport for WordPress emails. Instead of that I suggest to use one of available plugins which enable WordPress to send emails through SMTP. I’m using Easy WP SMTP. Configuration of this plugin is very easy – you just need to provide login and password for your email account and SMTP server address along with encryption settings. You are doing exactly the same when you configure Outlook or Thunderbird.

So everything is ready. Now we should enable configuration we prepared in first section of this part and just visit our site. 🙂

1

2

sudo a2ensite wordpress-marchel-it.conf

sudo service apache2 reload

Perfect! We just launched our WordPress! In next part I’ll show you that however everything looks good, some features won’t work as it should. We also fix all of the problems of course.

Apache, PHP, MySQL

To launch WordPress we need to have some additional tools. First of all we need to install server which will pending requests from users browsers and sending them responses. WordPress is written in PHP so we also need to install interpreter of this language. Last but not least we need database server because our blog can’t work without it. WordPress is designed to work with MySQL so we need to install this one.

Apache installation

To install apache you need to SSH your instance and run following command:

sudo apt-get update && sudo apt-get install apache2

As I mention in previous part sudo apt-get update will fetch information about software available in Ubuntu repository. The && operator stands as: “if command on the left side will ran successfully, run command on the right side”. Command sudo apt-get install apache2 launch installation of package apache2.

After this operation when you type IP address of your instance to browser address bar, following page should appears. This indicates that our server works. 🙂

Before we continue it’s worth to look if apache is using mpm-events module instead of mpm-prefork. It’s about performance. My installation has this module installed and activated by default. You can check this with command which lists all loaded modules:

To get this installation to work with apache we should install another apache module. Because of license incompatibilities this module is available in multiverse repository which is disabled by default so we need to enable it. About differences between types of repositories you can read here. Please open file /etc/apt/sources.list in your favorite text editor (I will use nano).

sudo nano /etc/apt/sources.list

We should uncomment appropriate lines (URLs can be different for different regions):

Now we can run command

sudo apt-get update
sudo apt-get install libapache2-mod-fastcgi

After installation module should be enabled automatically and apache should be restarted.

If that is not true in your case, you can anytime enable module and restart server yourself running following commands:

sudo a2enmod fastcgi
sudo service apache2 restart

CAUTION!If you have had installed mod_php previously you should turn it off. You can do this similarly:

sudo a2dismod php5
sudo service apache2 restart

Now we’ll configure apache a bit. I assume that only one site will be running on our instance. Configuration provided below is very simple then. Let’s enable another two modules which we’ll need:

sudo a2enmod alias actions
sudo service apache2 restart

Now we should create configuration file which tells apache what should be done with PHP files. All of apache configuration files are stored in /etc/apache2/conf-available directory so we put our file here also. I will name it php5-fpm.conf. We can do this for example with nano:

Couple words of explanation:IfModule checks if module is active and if yes performs instructions in block.AddHandler tells apache which action it should take for described files – in this case for files with php extension, action php5-fcgi will be firedAction defines program to which request will be passed when action is fired – in this case for action php5-fcgi request will be routed to /php5-fcgi pathAlias is used to map paths – in this case we define that path /php5-fcgi from previous line is actually /usr/lib/cgi-bin/php5-fcgiFastCgiExternalServer indicates how to handle file which we catch with the above lines – in this case it will be run by server pending on unix socket on /var/run/php5-fpm.sock path. This path is defined in php-fpm configuration file. You can find it here: /etc/php5/fpm/pool.d/www.conf. Option -pass-header gives us ability to pass to the script http headers which won’t be passed by default. For example Authorization Header.Directory defines path in which following settings will apply.Require all granted gives permission to read localization by all – we need to add this line because otherwise we’ll see “Access denied” instead of results of any PHP script.

How to make your instance more secure?

This post is obviously not complete security guide and it’s not meant to be. However I want to talk about some basics which I think are minimum in subject of securing our Linux. I must emphasize that you have complete control of your instance and it’s your responsibility to take care about security of your data and your site users. I definitely encourage to constantly learn about server administration.

Updates

One of the most important things are regular updates of the system and other installed software. Unfortunately vulnerabilities happened everywhere (famous example of vulnerability in OpenSSL library from 2014) so we should install every security updates as fast as possible. Before we continue let’s update our system.

The first step will be following command:

sudo apt-get update

In this way we ensure that our system “knows” about all the updates available but nothing will be installed yet.

Next we can do this:

sudo apt-get upgrade

or this:

sudo apt-get dist-upgrade

There is significant difference between those two. In first case only packages that were already installed will be updated. However common practice is that one package depends on others. If new version of installed software depends on package which was not required previously and this package is not available in system, update will fail. All information about the problems will be printed to the console.

In second case dependencies are resolved automatically and some packages can be deleted or new packages can be installed. Now it really doesn’t matter because we just launch our instance and we don’t using it for any purpose yet. However when we start web server, database and our site will be made public, we won’t want something stop working because of update. It doesn’t mean of course that we shouldn’t update our system. It only means that we always need to know what we are doing and why. We probably should consider launching stage environment and check any modifications there first. In AWS ecosystem it’s really easy to duplicate EC2 instance.

Some of you probably notice that though installation of all updates, OpenSSL library which I mention remains in version 1.0.1f, which is theoretically vulnerable to HeartBleed attack. In fact it’s not true. This version was patched by Ubuntu maintainers the same day which vulnerability was disclosed. More information here.

Now we should reboot our instance.

sudo reboot

When you run this command your connection will be interrupted. Wait minute or two and try to connect again.

Change the default SSH port

It’s worth to consider change the default SSH port from 22 to some other number grater than 1023. Many bots which are used to automatic attacks search for open SSH port, but they limit themselves to default port. It of course won’t stop all intrusion attempts but can help reduce the number of them. We can change port in SSH configuration file. We must edit it as root so we run command:

sudo nano /etc/ssh/sshd_config

Of course you can use your favorite text editor instead of nano. 🙂
Lets find following line in file

Our current connection should not be interrupted but from now on every new connection to our instance must be on port which we put to config file. As you remember we define some security rules in our EC2 dashboard so we need to go back there and open up this port.

In group “Network & Security” we need to find tab called “Security Groups” and then right click group which our instance belongs to. From menu choose “Edit inbound rules”. Now in place of SSH we select “Custom TCP Rule” and enter the new port number. Remember to save the changes.

Now we should be able to start new connection. If you’re using console you should add “-p” followed by port number. In my case it will be:

ssh -i ~/.ssh/test1-keys.pem ubuntu@52.29.70.252 -p 56321

If you’re connecting by putty, find on list of saved sessions your instance and load settings. Now you should change port number and save your session again.

Summary

After this part our system is up to date and SSH works on different than default port number. As I mention it’s not guarantee that you are 100% secure. I recommend that you read about some tools which can help you in process of hardening your system. In next part we’ll install software which is essential to run our virtual machine as web server.

How to connect to my instance

In previous post we launch our virtual machine so now is the time to log in via SSH. In this part we attach Elastic IP which will be our public IP address and we connect to our instance using previously downloaded private key.

How to attach Elastic IP

You can attach one public IP to any single instance without additional costs. This IP will be linked with our AWS account so we can easily attach and detach it from one instance to another as we need. One virtual machine can also have more than one public IP address if we need this kind of configuration for some reason. This address is reserved for us as long as we won’t release it. Theoretically our instance have public address attached in time of launching but it’s randomly picked so when we stop our machine it will be released and new address will be attached on resume.

In our case we want that our address will persist forever and ever and if we need to scale up in the future we probably want to have possibility of transfer this IP address to another machine. Fortunately this process is very easy. 🙂

Let’s find Elastic IPs tab in our EC2 dashboard. There we will click Allocate New Address and confirm.

Next let’s right click on IP and choose action Associate Address. We can do the same thing from Actions dropdown. Click on input called Instance should revealed list of our instances where we can choose that we are recently created. We can also filter this list by instance ID or Name tag. Select your instance and then click Associate button.

If you check your list of instances you should see that this new address was really attached to your machine.

Connect through SSH

Linux / Mac

If you work on Linux or Mac, just add downloaded private key to your .ssh directory i home directory:

mv /path/to/your/key.pem ~/.ssh

If you doesn’t have this folder, create it:

mkdir ~/.ssh

Private key should have very restrictive settings of permissions. Let’s set 400 then (available only for reading, only for file owner).

chmod 400 ~/.ssh/your_key.pem

Now you should be able to connect to your instance. Default user name for Ubuntu is… ubuntu. My private key are in test1-keys.pem file in .ssh directory and IP address of my instance is 52.29.70.252, so i type following command:

ssh -i ~/.ssh/test1-keys.pem ubuntu@52.29.70.252

I wrote down key fingerprint from server logs so now I can verify if I’m really connecting to my instance. If yes I can confirm that I want to connect. From now on my computer “knows” my virtual machine so I won’t need to check this fingerprint for every connection. If everything was fine you just logged in to your instance. Congratulations! 🙂

Windows

If you’re working on Windows, you’ll need to use additional tools. First of all Windows don’t support SSH natively (probably something will change about this in near future as we can read here). I use and recommend PuTTY as SSH client for Windows. Additionally we can’t use private key as it is, we need to convert it to format which can be read by PuTTY. We can do this with tool called PuTTYgen, which we can download here.

Let’s open PuTTYgen and load our private key. Next we click on Save private key button. We’ll be asked if we really want to save our private key without password protection. There are different opinions on this subject. Here you can read interesting discussion about it. Everyone should take this decision himself. One thing I want to tell is that if your key is not password protected, anyone who can read your key file, can access your instance also. I’m not creating password for sake of this tutorial.

Where to save the new key file? I’ll follow the “Linux” way and create .ssh folder in my user directory, but you can place it anywhere you want. However it’s important to remember that if you are not the only user of this computer you should place it in directory not accessible by other users.

So last thing is to use PuTTY to log in on our machine. User name in Ubuntu is by deafult ubuntu nad IP address of my instance is 52.29.70.252. In Host Name I should type ubuntu@52.29.70.252 and in SSH -> Auth tab I need to select private key file.

Now it is worth to save this settings so i won’t need to retype them in future.

When you click Open button security alert pop-up should appear with information that this server is not known. If you wrote down key fingerprints you can verify if they’re match. If yes confirm that you want to connect and you should be in. Next time this verification will not be required.

Summary

So we have established SSH connection to our EC2 instance. We are step closer to run WordPress. In next part we will talk a little bit about configuration of our server in terms of security.

How to launch EC2 instance

After login on the top right corner we should choose region in which we will operate. The best choice should be region geographically nearest place from which we expect most of the traffic. Next we should go to EC2 dashboard and click Launch Instance. We’ll be taken to the wizard, where we’ll be able to configure and launch our virtual server.

Step 1 – Choose an Amazon Machine Image (AMI)

Instances are based on Amazon Machine Images (AMIs) which are prepared images of operating system. We can choose from wide range of images. Some of these have pre-installed environment for WordPress and WordPress itself. It’s worth to look on AWS Marketplace and Community AMIs tabs to be aware of how many prepared images you can use out of the box. My pick will be clean Ubuntu Server 14.04 LTS as I wrote in previous part. It’s the newest LTS release in time of writing.

Step 2 – Choose an Instance Type

When you register new account to AWS you can use free tier for one year, which includes t2.micro instance, so I will focus on this type of machine. However you should know limitations of it. If you expecting high traffic on your blog you should consider launching more powerful instance. You can find the exact specifications and characteristics of various types of instances here and price list is here.

When you choose appropriate option you can click “Next: Configure Instance” button.

Step 3 – Configure Instance Details

If this is your first server, probably most of the default options will be perfect for you so i won’t explain everything in detail. Some of this settings are self explanatory (like Number of instances), some are needed only on specific situations but these are out of scope of this tutorial. However I would like to mention two of them which is good to know:

“Shutdown behavior” – this option indicates how our machine will behave, when we run for example following command:

sudo shutdown -h now

If we set “stop” value, instance will be stopped and it will be possible to resume it in any moment of the future in the same state as it was. When server is stopped there is also no fee for usage – we pay only for running hours.

If we set “terminate” value, instance will be erased. In our case this machine will act as webserver, so probably we don’t want this kind of situation.

Second option which is worth mentioning here is “Enable termination protection”. We can manipulate state of our instance not only by SSH but for example also from EC2 dashboard. There we can in any moment terminate (erase) our virtual machine. To be 100% sure that we won’t do this by accident, let’s check this option.

Step 4 – Add Storage

To let our instance work, we’ll need some storage, where operating system will be installed and where we store all of our files and data such as WordPress files. By default wizard give us 8GB on one partition. We can use up to 30GB for free in free tier so we can grab more space it there is need for it. We can also do it later but this will remain shutting down our server for couple minutes. We can of course add additional drives if we want separate OS from database for example.

“Delete on Termination” is quite important setting. Because drives we are using are virtual, we can easily attach and detach them from particular instances. Therefor sometimes we might don’t want to erase all our data on instance termination. In this case we can deselect this option. Because in previous step I made sure that I won’t accidentally erase my machine, I will leave this option as it is. I don’t want to preserve my virtual drive with OS and I can easily transfer all of WordPress data to another server before i eventually delete my instance. If I’ll change my mind, I can change this behavior later following instructions here.

To sum up: I leave default values and I’m going to the next step.

Step 5 – Tag Instance

In this step it’s all about organization. In case of single instance it doesn’t very important, but if you manage large number of virtual servers, tags are very handy tool which let you easily find resources (because not only instances you can tag) you need. Tags are simply key – value pairs and we can add up to 10 tags for any resource. For example we can name our server in a way that will be meaningful for us in the future. For the purpose of this series i will name my instance Test1.

Step 6 – Configure Security Group

In this step we are setting up firewall rules for inbound traffic. From the security point of view it’s crucial to open only this ports that are really needed to work. Because our instance will act as web server we need to open ports for HTTP and HTTPS protocols. In addition we also need to manage remotely our server so we need to open port 22 for SSH service. If we have static IP or we will connect to server from specific IP range (for example through VPN) it is good practice to limit access only for those IPs. My home IP address is dynamic so I leave this port open globally.

I named my group www-open-ssh, because it is quite self explanatory. You can name it anything you like.

Step 7 – Review

So now we are on review screen. We can one more time look through all the configuration details. If all settings are correct we can press “Launch” button and… Almost done! 🙂 Last thing we need to do is to generate key pair which we will use for authentication instead of password – this is in general more secure way to authenticate. We need to name this key pair somehow. It can be whatever you want. I will name it test1-keys. When you click Download Key Pair, the private key should be downloaded to your computer. This is the only time when you can get it. You won’t be able to re-download it again. The public key will be automatically added to your instance. Now we can press “Launch Instances”.

If all goes well you can go to Instance List on your EC2 Dashboard and there you find your instance running.
Congratulations! 🙂

Last thing i recommend is to get fingerprints of SSH keys. If you are sure that your computer and network are secure we can skip this step. On the other hand it isn’t much effort to do this, so we can do this just for sure. On instance list right click on your instance and choose Instance Settings -> Get System Log.

Popup contains boot messages should appear. If the window is empty give your machine another minute to boot up. On the very bottom we should find this section.

Let’s write down somewhere this fingerprints. They will be helpful on first connection through SSH.

Introduction

With this post I’m starting the series about deploying WordPress on Amazon AWS EC2. I’ll try to explain step by step what am I doing and why. If you know how to do something better or faster, please leave your comment on specific post. I’ll be happy to learn some new things or best practices. 🙂

Assumptions

Many people probably have set of tools which they like to use. Someone like this Linux distribution, someone else prefer that. Someone like Apache server and someone prefer Nginx. I won’t argue with that and I don’t think that one approach is better than another in every single situation. In many cases it’s just matter of preference. I’ll use following setup: