Install Magento 2.3.2 on AWS Ubuntu 18.04 full SSL with Nginx Redis Varnish and Cloudfront

Description of the requests flow:

user -> nginx:80 -> nginx:443 -> varnish:6081 -> nginx:8080

Installation preparation:

Inbound:
SSH Port 22 My IP
HTTP Port 80 0.0.0.0
HTTPS Port 443 0.0.0.0
sudo apt update && sudo apt upgrade
sudo apt install unzip certbot
sudo apt-get -y install nginx
sudo apt install mariadb-server
sudo mysql_secure_installation
CREATE DATABASE magentodb;GRANT ALL PRIVILEGES ON magentodb.* TO ‘magentouser’@’localhost’ IDENTIFIED BY ‘putyourpasswordhere’;FLUSH PRIVILEGES;exit;
sudo useradd -m -U -r -d /opt/magento magento
sudo usermod -a -G magento www-data
sudo chmod 750 /opt/magento
sudo apt install php7.2-common php7.2-cli php7.2-fpm php7.2-opcache php7.2-gd php7.2-mysql php7.2-curl php7.2-intl php7.2-xsl php7.2-mbstring php7.2-zip php7.2-bcmath php7.2-soap
sudo sed -i “s/memory_limit = .*/memory_limit = 2048M/” /etc/php/7.2/fpm/php.inisudo sed -i “s/upload_max_filesize = .*/upload_max_filesize = 256M/” /etc/php/7.2/fpm/php.inisudo sed -i “s/zlib.output_compression = .*/zlib.output_compression = on/” /etc/php/7.2/fpm/php.inisudo sed -i “s/max_execution_time = .*/max_execution_time = 18000/” /etc/php/7.2/fpm/php.inisudo sed -i “s/;date.timezone.*/date.timezone = UTC/” /etc/php/7.2/fpm/php.inisudo sed -i “s/;opcache.save_comments.*/opcache.save_comments = 1/” /etc/php/7.2/fpm/php.ini
sudo nano /etc/php/7.2/fpm/pool.d/magento.conf
[magento]
user = magento
group = www-data
listen.owner = magento
listen.group = www-data
listen = /var/run/php/php7.2-fpm-magento.sock
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s
pm.max_requests = 500
chdir = /
sudo systemctl restart php7.2-fpm
curl -sS https://getcomposer.org/installer | sudo php — — install-dir=/usr/local/bin — filename=composer

Installation — SSL certificate:

sudo systemctl stop nginx
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
sudo su
mkdir -p /var/lib/letsencrypt/.well-known
chgrp www-data /var/lib/letsencrypt
chmod g+s /var/lib/letsencrypt
sudo nano /etc/nginx/snippets/letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
allow all;
root /var/lib/letsencrypt/;
default_type “text/plain”;
try_files $uri =404;
}
sudo nano /etc/nginx/sites-available/mywebsite.com
upstream fastcgi_backend {
server unix:/run/php/php7.2-fpm.sock;
}
server {
server_name mywebsite.com;
listen 80;
include snippets/letsencrypt.conf;
}
sudo ln -s /etc/nginx/sites-available/mywebsite.com /etc/nginx/sites-enabled/mywebsite.com
sudo rm -f /etc/nginx/sites-enabled/default
sudo rm -f /etc/nginx/sites-available/default
sudo service nginx start
sudo certbot certonly — agree-tos — email myemail@gmail.com — webroot -w /var/lib/letsencrypt/ -d mywebsite.com
sudo nano /etc/cron.d/certbot
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e ‘sleep int(rand(3600))’ && certbot -q renew — renew-hook “systemctl reload nginx”

Installation — Magento:

sudo su — magentocomposer create-project — repository-url=https://repo.magento.com/ magento/project-community-edition /opt/magento/public_htmlcd ~/public_html
php bin/magento setup:install — base-url=https://www.mywebsite.com/ \
— base-url-secure=https://www.mywebsite.com/ \
— admin-firstname=”FirstName” \
— admin-lastname=”LastName” \
— admin-email=”myemail@gmail.com” \
— admin-user=12345 \
— admin-password=”123456” \
— db-host=localhost \
— db-name=magentodb \
— db-user=magentouser \
— db-password=putyourpasswordhere\
— currency=USD \
— timezone=America/Chicago \
— use-rewrites=1
php ~/public_html/bin/magento cron:install
sudo nano /etc/nginx/sites-available/mywebsite.comupstream fastcgi_backend {
server unix:/var/run/php/php7.2-fpm-magento.sock;
}
server {
listen 80;
server_name mywebsite.com;
include snippets/letsencrypt.conf;
return 301 https://mywebsite.com$request_uri;
}
server {
listen 443 ssl http2;
server_name mywebsite.com;
ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/mywebsite.com/chain.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ‘ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS’; ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;
keepalive_timeout 300s;
add_header Strict-Transport-Security “max-age=15768000; includeSubdomains; preload”;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
include snippets/letsencrypt.conf; set $MAGE_ROOT /opt/magento/public_html;
set $MAGE_MODE developer; # or production
access_log /var/log/nginx/mywebsite.com-access.log;
error_log /var/log/nginx/mywebsite.com-error.log;
include /opt/magento/public_html/nginx.conf.sample;
}
nginx -t
sudo service nginx reload
sudo service nginx restart

Installing and configuring a secure Redis for session caching

Sudo apt-get install redis-server
sudo update-rc.d redis-server defaults
sudo nano /etc/redis/redis.conf
...
bind 127.0.0.1 ::1
...
...
# requirepass foobared
requirepass replacewithyourpassword
openssl rand 60 | openssl base64 -A
sudo systemctl restart redis.service
bin/magento setup:config:set — session-save=redis — session-save-redis-host=127.0.0.1 — session-save-redis-log-level=3 — session-save-redis-db=2 — session-save-redis-password replacewithyourpassword

Installing and configuring Varnish for full page caching

sudo apt-get install varnish
import std;
sudo nano -f /etc/varnish/default.vcl
server {
listen 443 ssl http2;
server_name mywebsite.com;
ssl_certificate /etc/letsencrypt/live/magento-test.summerraingroup.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/magento-test.summerraingroup.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/magento-test.summerraingroup.com/chain.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ‘ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS’; ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;
keepalive_timeout 300s;
location / {
proxy_pass http://127.0.0.1:6081;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Ssl-Offloaded “1”;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
#proxy_hide_header X-Varnish;
#proxy_hide_header Via;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
server_name mywebsite.com;
listen 8080;
add_header Strict-Transport-Security “max-age=15768000; includeSubdomains; preload”; add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
include snippets/letsencrypt.conf; set $MAGE_ROOT /opt/magento/public_html;
set $MAGE_MODE production; # or production
access_log /var/log/nginx/mywebsite.com-access.log;
error_log /var/log/nginx/mywebsite.com-error.log;
include /opt/magento/public_html/nginx.conf.sample;
}
Inside   /etc/default/varnish edit as following:DAEMON_OPTS=”-a :6081 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-p http_resp_hdr_len=65536 \
-p http_resp_size=98304 \
-s malloc,256m”
nginx -tsudo service restart varnishsudo service restart nginxservice httpd restart# go to magento folder and flush the cache
bin/magento cache:flush

Configuring Cloudfront CDN to serve media and static files

sudo nano /etc/nginx/magento2-cors.conf# content below:
add_header 'Access-Control-Allow-Origin' '*' 'always';

if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' 'always';
add_header 'Access-Control-Allow-Headers' 'x-requested-with' 'always';
add_header 'Access-Control-Max-Age' 86400 'always';
add_header 'Content-Length' 0 'always';
return 204;
}
location /static/ {
# Uncomment the following line in production mode
# expires max;
# Remove signature of the static files that is used to overcome the browser cache
location ~ ^/static/version {
rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
}
location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|json)$ {
add_header Cache-Control “public”;
add_header X-Frame-Options “SAMEORIGIN”;
include /etc/nginx/magento2-cors.conf;
expires +1y;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}

location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control “no-store”;
add_header X-Frame-Options “SAMEORIGIN”;
include /etc/nginx/magento2-cors.conf;
expires off;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}

if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}

add_header X-Frame-Options “SAMEORIGIN”;
include /etc/nginx/magento2-cors.conf;
}
location /media/ {
try_files $uri $uri/ /get.php$is_args$args;
location ~ ^/media/theme_customization/.*\.xml {
deny all;
}
location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
add_header Cache-Control “public”;
add_header X-Frame-Options “SAMEORIGIN”;
include /etc/nginx/magento2-cors.conf;
expires +1y;
try_files $uri $uri/ /get.php$is_args$args;
}
location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control “no-store”;
add_header X-Frame-Options “SAMEORIGIN”;
include /etc/nginx/magento2-cors.conf;
expires off;
try_files $uri $uri/ /get.php$is_args$args;
}
add_header X-Frame-Options “SAMEORIGIN”;
include /etc/nginx/magento2-cors.conf;
}
cd /opt/magento/public_html
bin/magento cache:flush
nginx -t
sudo service varnish restart
sudo service nginx restart

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store