Posted on

Create a LEMP stack in AWS with EC2 (Linux, Nginx, MariaDB and PHP 7.2)

Hopefully, this quick run-through will help you get a LEMP server up and running quite quickly in AWS. If you have any questions, feel free to ask in the comments.

Important! Please, choose the required data center from the top right hand corner. Remember to do this for any configuration changes or new instances when logging into the AWS console.

Follow the navigation to start launching a new EC2 instance:
AWS > Compute > EC2 > Instances > Launch Instance

Select the Amazon Linux Candidate we want to use:
Amazon Linux 2 LTS Candidate 2 AMI (HVM), SSD Volume Type – ami-921423eb

And the following flavour with our desired specifications:
General Purpose: t2.xlarge

Click on the ‘next’ buttons in the bottom right hand corner until you get to ‘Configure Security Group’. Leave all other configuration options as default.

The SSH rule should be added already, but you will need to add the 443 and 80 port open from anywhere. Name this security group something relevant with a similar description, so it can be reused for other instances.

Finally, click ‘Review and launch’.

When prompted, create a new key pair and download this to your machine. This will be in the form of a .pem file which you should add to your .ssh directory. For now, this is the quickest way to configure a role to allow you to access the server:

cp ~/Downloads/aws.pem ~/.ssh/.
chmod 400 /path/aws.pem

Where aws.pem is the name of your key pair. The usage of CI means no one else should need access to the server, and less human intervention will prevent any configuration from changing. Cloud setups should be kept extremely automated.

If you wish for this to change, consider creating an IAM role, such as, ‘DevOps’, and create and add the necessary users, which will all have different key pairs, AWS logins and API keys. Use different user accounts per employee, to make it easy to revoke them where and when necessary.

Once your key pair is downloaded, you will be able to finally launch your instance. Head back to the ‘Instances’ page and wait for your instance to complete setup. The instance should be in a ‘Running’ state and the status check should show as ‘Initializing’.

When the status checks finalizes and shows ‘2/2 checks passed’, you will be able to use the public IVP4 address of your instance. Use this to login via SSH using the ec2-user user:

ssh -i ~/.ssh/aws.pem [email protected]

Where is your public IPV4 address of the instance.

Please note, if you are unable to ping or access this IP address, your security group may be misconfigured.

Once logged into the box, run the following commands to configure:

# Update Linux and install essential packages
sudo yum -y update
sudo yum install -y gcc make

# Install the latest epel repository
sudo yum install –y

# Install php72 using amazon-linux-extras
sudo amazon-linux-extras install php7.2 nginx1.12

# Install Nginx and PHP-FPM
sudo yum install -y nginx php-fpm

# Configure Nginx
sudo vi /etc/nginx/nginx.conf

Find the following line:

include /etc/nginx/conf.d/*.conf;

Add this line below it:

include /etc/nginx/sites-available/*.conf;

Come out of the file, and create the sites-available directory:

sudo mkdir /etc/nginx/{sites-available,sites-enabled}

Now, create a new virtual host entry:

sudo vi /etc/nginx/sites-available/my-site.conf

Paste in the following for a virtual host setup:

server {
  listen 80;
  listen [::]:80;
  return 301 https://$server_name$request_uri;

server {
  listen 443 ssl http2 default_server;
  listen [::]:443 ssl http2 default_server;
  root /var/www/my-site;

  ssl_certificate "/etc/pki/nginx/server.crt";
  ssl_certificate_key "/etc/pki/nginx/private/server.key";
  ssl_session_cache shared:SSL:1m;
  ssl_session_timeout 10m;
  ssl_ciphers HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers on;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;

  location ~ \.php$ {
    try_files $uri /index.php = 404;
    fastcgi_pass unix:/var/run/php-fpm/www.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
    include fastcgi_params;

For non-dev environments, the SSL certificate will need to be properly generated via a third party (such as CloudFlare or Let’s Encrypt). This will then need to be uploaded to the server(s) and the location of the key changed in the virtual host entry. After applying any changes, Nginx will need to be restarted for these changes to take effect.

Please be sure to change the server_name directive, and set up the relevant DNS (pointing to the load balancer or Elastic IP). After that, create the virtual host symlink:

sudo ln -s /etc/nginx/sites-available/my-site.conf /etc/nginx/sites-enabled/my-site.conf

Finally, we will need to create a server key for the SSL binding. For the key generation, use an empty passphrase, and leave the challenge password blank:

sudo mkdir -p /etc/pki/nginx/private
cd /etc/pki/nginx/
sudo ssh-keygen -f private/server.key
sudo openssl req -new -key private/server.key -out server.csr
sudo openssl x509 -req -days 365 -in server.csr -signkey private/server.key -out server.crt
sudo openssl rsa -in private/server.key -out private/server.key
# PHP-FPM Configuration
sudo vi /etc/php-fpm.d/www.conf

And change the matching keys to the following values:

listen = /var/run/php-fpm/www.sock

user = nginx
group = nginx

listen.owner = nginx = nginx
listen.mode = 0664
# Create directory for new virtual host
sudo mkdir /var/www/my-site

# Add the ec2-user to the nginx group and correct permissions
sudo usermod -a -G nginx ec2-user
sudo chown -R ec2-user:nginx /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} \;
find /var/www -type f -exec sudo chmod 0664 {} \;

# Add Nginx and PHP-FPM to the startup commands, and start the services
sudo systemctl enable nginx.service
sudo systemctl enable php-fpm.service

Feel free to comment out the default virtual host after you have confirmed everything is working as expected, which can be done in:

sudo vi /etc/nginx/nginx.conf

Once complete, Nginx and PHP-FPM should be running. You can install your website at /var/www/my-site to get started.

To install MariaDB, we’ll need to tell AWS to use the newer repositories:

# Create the MariaDB yum repository for v10.3
sudo vi /etc/yum.repos.d/MariaDB.repo

# And paste in the following:

# MariaDB 10.3 CentOS repository list
name = MariaDB
baseurl =

# Install Nginx, PHP-FPM and MariaDB sudo yum install -y nginx php-fpm MariaDB-server MariaDB-client

For other repositories, you can check their website directly or use their repository generator.

Then, we can go ahead and install MariaDB:

sudo yum install -y MariaDB-server MariaDB-client

We can then go ahead and add the root user and any other necessary users:


# Follow the on-screen instructions to add the root password, remove the test database, disallow remote access and reload privileges

# Log in to MariaDB (using your new root password) for the SQL commands (show below this command) to work:
mysql -uroot -p

# Add your new database(s)

# Add users and necessary privileges
CREATE USER 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';
GRANT ALL PRIVILEGES ON `my_db`.* TO 'dbuser'@'localhost';

# Don't forget to exit when you're done by typing 'exit' or using ctl > d

To enable mysql on startup, use:

sudo systemctl enable mysql

At a later stage, when the website is fully deployed, an image should be taken to allow us to recreate boxes at the click of a button, as well as being able to set up auto-scaling in the future. This will drastically reduce the time needed to re-create an instance, and could be used in an emergency situation if an instance is unresponsive.

Please note, it is not recommended to take an image when the instance is running, as Amazon is not able to guarantee the integrity of the file system on the created image. When creating images, please bear in mind the instance will be shut down. If taking images on a working production environment, the instance should be taken out of the load balancer before working on it.

If you have any problems or need to troubleshoot, check your Nginx configuration by using:

sudo systemctl status nginx.service

And using the Nginx error log to check for errors when accessing the web server:

sudo tail -f /var/log/nginx/error.log

Once a configuration file has changed, you will need to restart nginx with:

sudo systemctl restart nginx