How to Install LEMP with RDS on Ubuntu with Let’s Encrypt SSL – AWS. In this guide you will learn how to install Nginx, PHP 7.4 and configure MySQL in Amazon RDS.
You will also install some common PHP extensions and adjust the PHP configurations. Finally you will install Let’s Encrypt SSL and configure HTTPS.
This setup is tested on an EC2 Instance with Ubuntu 18.04 OS.
Prerequisites
- A running EC2 Instance. Learn how to create an AWS EC2 instance.
- Assigned a Elastic IP to your EC2 Instance.
- Setup Amazon RDS and connect it with EC2 Instance.
- Setup and configure Route 53 and point your domain to AWS.
- Successful SSH connection to your EC2 Instance.
SSH to your EC2 Instance and perform the steps listed below.
Step 1: Initial Server Setup
Let’s start by updating the local package index with the following command to the latest available version.
sudo apt update
sudo apt upgrade
Once the update is done you can start installing the required packages.
Step 2: Install Nginx
Nginx is available by default in the Ubuntu repository, so you can install it directly using the apt
command.
sudo apt install nginx
This will install nginx
and all required dependencies.
Step 3: Setup Firewall
Now you can set up Uncomplicated Firewall (UFW) with Nginx to allow public access on default web ports for HTTP
and HTTPS
sudo ufw app list
You will see all listed applications.
Output
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
- Nginx Full: This profile opens both port
80
(normal, unencrypted web traffic) and port443
(TLS/SSL encrypted traffic) - Nginx HTTP: This profile opens port
80
(normal, unencrypted web traffic) - Nginx HTTPS: This profile opens only port
443
(TLS/SSL encrypted traffic) - OpenSSH: This profile opens port
22
for SSH access.
If you are not going to use SSL you need to enable only the Nginx profile.
Now we will enable Nginx Full.
sudo ufw allow 'Nginx Full'
With this command you can view the status of UFW.
sudo ufw status
You will see the output as follows.
Output
Status: active
To Action From
-- ------ ----
Nginx Full ALLOW Anywhere
OpenSSH ALLOW Anywhere
Nginx Full (v6) ALLOW Anywhere (v6)
OpenSSH (v6) ALLOW Anywhere (v6)
Step: 4 Check Nginx Installation
Once Nginx is installed it will be started automatically and already be up and running.
Every process in Nginx is managed with the systemctl
command. Check the status of Nginx with the following command.
sudo systemctl status nginx
Output nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2020-01-12 15:43:24 IST; 22h ago Docs: man:nginx(8) Main PID: 22736 (nginx) Tasks: 2 (limit: 669) CGroup: /system.slice/nginx.service ├─22736 nginx: master process /usr/sbin/nginx -g daemon on; master_process on; └─22737 nginx: worker process
Now we have Nginx installed and configured Firewall.
Step 5: Install PHP 7.4 FPM
Here we will install PHP 7.4 FPM the current latest version available. Add the ondrej/php
which has PHP 7.4 package and other required PHP extensions.
sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
Once you have added the PPA you can install PHP 7.4 FPM.
Execute the following command to install PHP 7.4 FPM.
sudo apt install php7.4-fpm
After the installation has completed, you can confirm the installation using the following command
php-fpm7.4 -v
Step 6: Install PHP 7.4 Extensions
Installing PHP extensions are simple with the following syntax.
sudo apt install php7.4-extension_name
Now, install some commonly used php-extensions
with the following command.
sudo apt install php7.4-common php7.4-mysql php7.4-xml php7.4-xmlrpc php7.4-curl php7.4-gd php7.4-imagick php7.4-cli php7.4-dev php7.4-imap php7.4-mbstring php7.4-opcache php7.4-soap php7.4-zip php7.4-intl -y
Step 7: Configure PHP 7.4 FPM
Now we configure PHP for Web Applications by changing some values in php.ini
file.
For PHP 7.4 FPM the php.ini
location will be in following directory.
sudo nano /etc/php/7.4/fpm/php.ini
Hit F6
for search inside the editor and update the following values for better performance.
upload_max_filesize = 32M
post_max_size = 48M
memory_limit = 256M
max_execution_time = 600
max_input_vars = 3000
max_input_time = 1000
Once you have modified your PHP settings, hit CTRL+X
and Y
to save the configuration and restart PHP-FPM for the changes to take effect.
sudo php-fpm7.4 -t sudo service php7.4-fpm restart
Step 8: Setup Amazon RDS and connect with EC2
Now you can create an RDS database server with MySQL engine and configure security groups to allow connections from EC2 Instance.
Follow the RDS setup guide to configure it with MySQL.
Step 9: Configure Nginx
Next, open the Nginx configuration file, which can be found at /etc/nginx/nginx.conf
sudo nano /etc/nginx/nginx.conf
The worker_processes directive is the amount of CPU cores your instance. In my case, this is 1
.
Uncomment the multi_accept directive and set it to on
.
Lower the keepalive_timeout directive to 15
.
For security reasons, you should uncomment the server_tokens directive and ensure it is set to off
.
Add the new client_max_body_size directive below the server_tokens and set the value to 64m.
Uncomment the gzip_proxied directive and set it to any
, uncomment the gzip_comp_level directive and set it to the value of 2
and finally uncomment the gzip_types directive.
In order for Nginx to correctly serve PHP you also need to ensure the fastcgi_param SCRIPT_FILENAME
directive is set, otherwise, you will receive a blank white screen when accessing any PHP scripts. So open fastcgi_params file by issuing
sudo nano /etc/nginx/fastcgi_params
Add the following at the end of the file
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
That’s all, this is the basic Nginx configuration, hit CTRL+X
followed by Y
to save the changes. Ensure that the configuration file contains no errors and restart Nginx for the changes to take effect by issuing the following command
sudo nginx -t
If you get a successful message, then proceed with the following command
sudo service nginx restart
If everything worked out fine, you should still be able to see the Nginx welcome page when visiting your domain in the browser. However, unless visiting a known host the server should return a 444 response. So, we remove the default server blocks from Nginx.
sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default
Now you need to add a catch-all block to the Nginx configuration. Open the nginx.conf
file
sudo nano /etc/nginx/nginx.conf
Find the line with include /etc/nginx/sites-enabled/*;
Below this line add the following
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
Hit CTRL+X
followed by Y
to save the changes and then test the Nginx configuration and restart Nginx.
sudo nginx -t
sudo service nginx restart
Now when you visit the domain name you should receive an error.
Step 10: Configure Nginx Server Blocks for Domain
Create directories to house your website.
sudo mkdir -p /var/www/html/domainname/public
sudo mkdir -p /var/www/html/domainname/logs
Setup correct permissions.
sudo chmod -R 755 /var/www/html/domainname sudo chown -R www-data:www-data /var/www/html/domainname
Create a new Nginx configuration for your website in the sites-available
directory.
sudo nano /etc/nginx/sites-available/domainname.com
Copy and paste the following configuration, ensure that you change the domain name with your domain name.
server { listen 80; listen [::]:80; server_name domainname.com www.domainname.com; error_log /var/www/html/domainname/logs/error.log; root /var/www/html/domainname/public/; index index.html index.php; location / { try_files $uri $uri/ /index.php?$args; } location = /favicon.ico { log_not_found off; access_log off; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_read_timeout 3600; fastcgi_index index.php; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; include fastcgi_params; } }
Hit Ctrl+X
followed by Y
and Enter
to save the file and exit.
To enable this newly created website configuration, make a symbolic link of the file that you just created into sites-enabled
sudo ln -s /etc/nginx/sites-available/domainname.com /etc/nginx/sites-enabled/domainname.com
Step 11: Install Let’sEncrypt SSL with Nginx
HTTPS is a protocol for secure communication between a server (instance) and a client (web browser). Due to the introduction of Let’s Encrypt, which provides free SSL certificates, HTTPS are adopted by everyone and also provides trust to your audiences.
sudo add-apt-repository ppa:certbot/certbot sudo apt update sudo apt install python-certbot-nginx
Now we have installed Cert bot by Let’s Encrypt for Ubuntu 18.04, run this command to receive your certificates.
sudo certbot --nginx certonly
Enter your email
and agree to the terms and conditions, then you will receive the list of domains you need to generate SSL certificate.
To select all domains simply hit Enter
This will automatically generate the new certificate for your domain.
Open your Nginx configuration and modify it to allow HTTPS connections and install the SSL certificate.
sudo nano /etc/nginx/sites-available/domainname.com
The following configuration will redirect all http
traffic to https
with www
. If you need to redirect without www
you can modify easily.
server {
listen [::]:80;
listen 80;
server_name domain.com www.domainname.com;
return 301 https://www.domainname.com$request_uri;
}
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name domainname.com;
ssl_certificate /etc/letsencrypt/live/domainname.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domainname.com/privkey.pem;
error_log /var/www/html/domainname/logs/error.log;
root /var/www/html/domainname/public/;
index index.html index.php;
return 301 https://www.domainname.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.domainname.com;
ssl_certificate /etc/letsencrypt/live/domainname.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domainname.com/privkey.pem;
error_log /var/www/html/domainname/logs/error.log;
root /var/www/html/domainname/public/;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_read_timeout 3600;
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
The http2
value is all that is needed to enable the HTTP/2 protocol.
Hit CTRL+X
followed by Y
to save the changes.
Check your configuration and restart Nginx for the changes to take effect.
sudo nginx -t
sudo service nginx restart
Step 12: Renewing SSL Certificate
Certificates provided by Let’s Encrypt are valid for 90 days only, so you need to renew them often. So, let’s test the renewal feature using the following command.
Certificates provided by Let’s Encrypt are valid for 90 days only, so you need to renew them often. Now you set up a cronjob to check for the certificate which is due to expire in next 30 days and renew it automatically.
sudo crontab -e
Add this line at the end of the file
0 0,12 * * * certbot renew >/dev/null 2>&1
Hit CTRL+X
followed by Y
to save the changes.
This cronjob will attempt to check for renewing the certificate twice daily.
Step: 13: Test the Setup
Once you have done the able steps you can create a new test PHP file in your web directory.
sudo nano /var/www/html/domainname/public/info.php
Paste the below code inside the file.
<?php phpinfo();
Save the file.
Now go ahead and check your domain name with the info.php
in the url (domainname.com/info.php
).
You will see that your domain got redirected to HTTPS and see the PHP information details.
Become a Certified AWS Professional with this easy to learn course now.
Conclusion
Now you have learned how to install LAMP stack with RDS database setup on Amazon EC2 Instance with Ubuntu 18.04. You have also learned how to install SSL and test the setup.
Thanks for your time. If you face any problem or any feedback, please leave a comment below.
I have use this so many time. It is a great article. Having said that, if you use this for multiple diffrerent sites you will get nginx -t results
root@ip-172-26-6-108:/etc/nginx/sites-available# nginx -t
nginx: [warn] conflicting server name “example.com” on [::]:80, ignored
nginx: [warn] conflicting server name “example.com” on 0.0.0.0:80, ignored
nginx: [warn] conflicting server name “example.com” on 0.0.0.0:443, ignored
nginx: [warn] conflicting server name “example.com” on [::]:443, ignored
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
adding dates to these articles would be nice. i didn’t install this b/c there are no dates and honestly I probably won’t see this site again as a result ha but great work!
Thank you very much for the feedback.