Install EC2 Debian 11, PHP8.2, Mariadb, Apache2

This is a stable installation as at May 2025 using x86_64 Debian 11 Linux and hardware architecture on a t3a instance – e.g. t3a.nano or t3a.micro.

If you install on t3 by mistake, you can snapshot and re-attach it to a t3a instance.

I prefer NGINX, but Apache2 is a good starting place. On either platform, WordPress editing sometimes freezes. We do not know why as yet.

I will show an NGINX installation on Debian 12 and AWS Linux2023 separately to this tehnical note.

My example uses Sydney – ap-southeast-2 and subnet ap-southeast-2a. I use GP3 hard disk. Make sure Credit Specification is Standard.
Please subscribe to Debian 11 (x86_64) in the Market Place at $0 cost. (You can try ARM on a t4 instance if you wish.)
I use laurenceshaw.au in the examples. All my Linux commands are via the vi editor. My SSH key is a .pem file on an iMac logging into Linux as root.

Please be reasonably familiar with pre-requisites such as iMac root terminal login, Connecting to the EC2 instance, sudo su once logged in, and use of FileZilla with your .pem key (.ppk on Windows Putty)

Launch an Instance - Configurations

First Linux configurations

On an iMac terminal, previously set up your ability to use root login for the ssh command to work. (Internet search to see how, or view previous articles). These small shell scripts can be helpful when you log into a terminal session and change to root with “sudo su”.

vi ssh.sh

#!/bin/sh
:>/var/root/.ssh/known_hosts
exit
[save and exit]

chmod 777 ssh.sh

[use your own .pem key file name and location, and the ssh command from the EC2 Connect tab.]
vi domain.sh

#!/bin/sh
cd PEM
ssh -i "domain.pem" admin@ec2-xx-xx-xx-xx.ap-southeast-2.compute.amazonaws.com
exit
[save and exit]

chmod 777 domain.sh

These can assist for quick logins and clearing the ssh keys on your iMac. For example: ./domain.sh

Log into the EC2 instance, and set your environment before working on the instance.

Assumption: you have attached an IP4 address and are able to SSH login.
$ sudo su
# 

All commands will be under root. Where needed I will make comments... 
(Use 1GB swap space. Less will cause issues. Use your own timezone. DOMAIN is you domain name, or possibley something else descriptive)

export EXINIT='set noautoindent'
export VISUAL=vim
echo "vm.swappiness=10" >> /etc/sysctl.conf
echo "vm.vfs_cache_pressure=200" >> /etc/sysctl.conf
sysctl -w vm.swappiness=10
sysctl -w vm.vfs_cache_pressure=200
dd if=/dev/zero of=/swapfile bs=1024 count=1048576
mkswap /swapfile
chmod 0600 /swapfile
swapon /swapfile
echo "/swapfile swap swap defaults 0 0" >> /etc/fstab
a="Australia/Brisbane";export a;echo $a
ln -sf /usr/share/zoneinfo/$a /etc/localtime
date

vi /etc/vim/vimrc.local
let skip_defaults_vim = 1
if has('mouse')
  set mouse=r
endif
[save and exit]

cd ~
vi .bashrc
export EXINIT='set noautoindent'
export VISUAL=vim
export PS1="[\u@DOMAIN: \w]\\$ "
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
[save and exit]
cd /home/admin
vi .bashrc
export EXINIT='set noautoindent'
export VISUAL=vim
export PS1="[\u@DOMAIN: \w]\\$ "
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
[save and exit]

apt update
apt upgrade

SETUP A BACKDOOR EMERGENCY LOGIN - useful for EC2 serial console login if something has gone wrong.

We will add a backup/backdoor user. If you get the sss_cache error shown below, please use the fix shown.
Changes are based on building a new site before it goes live.
We will use "snoopy" (the dog) as the user name...
adduser snoopy

(Give snoopy a password then add snoopy to /etc/sudoers - Using the vi editor, go to the end of the file (SHIFT G), and append the entry. Then use :w! to save the entry as it is a read only file.)
(Again, all commands are from root user)

vi /etc/sudoers
snoopy ALL=(ALL) NOPASSWD:ALL
[Exit the file after saving with SHIFT ZZ]

(Add the user to groups admin and root: (for Linux 2023, it is wheel and root))

usermod -aG admin snoopy; usermod -aG root snoopy

(We will make a copy of a good verion of /home/admin/.ssh to /home:)

cd /home/admin
cp -pr .ssh ../SSH_BACKUP

This completes the creation of a backup user that you can use in an emergency on the EC2 Contact console.

IF YOU GET THIS ERROR:
-------------------------------
[sss_cache] [sysdb_domain_cache_connect] (0x0010): DB version too old [0.22], expected [0.23] for domain implicit_files!
Higher version of database is expected!
In order to upgrade the database, you must run SSSD.
Removing cache files in /var/lib/sss/db should fix the issue, but note that removing cache files will also remove all of your cached credentials.
Could not open available domains
--------------------------------
To fix this, do the following:

cd /var/lib/sss/db
rm *
sss_cache -E

Then add the backup/backdoor user.



We will next add the Linux packages. Keep in mind, after doing all the work, stop and restart the instance and if adding major components, it can help to do the commands:  sync;sync;reboot

Install Packages

I’m providing quite a number of packages to cover WordPress and general use of apps. I will show how to use letsencrypt, but in the immediacy will show use of a paid SSL certificate for laurenceshaw.au.

Preliminary work – your CAA records…

In your DNS settings, if using Comodo or Sectigo, add two CAA records. If these fail in the future, just contact the supplier to see what the records should be:

CAA 0 issue sectigo.com
CAA 0 issue digicert.com

If using Letsencrypt (certbot): 0 issue letsencrypt.org

If a paid certificate fails due to having letsencrypt in the DNS records, you could configure an authentication record instead, or temporarily remove the letsencrypt record. It should still be possible hoserver to install letsenscypt SSL without its CAA record.

Again, use root login to the EC2 instance:

PRELIMINARY WORK for a PAID SSL Certificate (and add CAA records to the DNS)

Let's say we have a paid SSL certficate that you have edited to include all the chaining (this is a separate topic)
Upload the .crt and .key files with FileZilla to /home/admin
cd /etc/ssl/certs
cp /home/admin/*crt .
cd ../private
cp /home/admin/*key .

This is now out of the way. (Letsencrypt will be covered, but for now we use this.)


PRELIMINARY APT installations with KEY WARNING FIXES - this is for Debian 11. Should be ok for Debian 12?

apt update

Sometimes we do or do not get an error:
Get:5 https://packages.sury.org/php bullseye InRelease [7551 B]                                           
Err:5 https://packages.sury.org/php bullseye InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B188E2B695BD4743
Reading package lists... Done
W: GPG error: https://packages.sury.org/php bullseye InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B188E2B695BD4743
E: The repository 'https://packages.sury.org/php bullseye InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.

To fix this:

apt autoclean
apt-key adv --fetch-keys 'https://packages.sury.org/php/apt.gpg'

YOu may see this message: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg) We will fix this in a moment. It does not stop updates from working though.

apt update
apt upgrade

If still not working, try these commands first and re-attempt the fix above:

apt -y install software-properties-common ca-certificates lsb-release apt-transport-https
sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
wget -qO - https://packages.sury.org/php/apt.gpg | sudo apt-key add - 
apt -y install curl gnupg2 ca-certificates lsb-release debian-archive-keyring

If there was not an error, still do the above 4 commands.


apt update
apt upgrade

If you see the message apt autoremove, it is okay to do it.

I know this is not good, but it seems not to happen on all installations.

Fixing the legacy warning... You will see at the top of the output a warning similar to this:

apt-key list

Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
/etc/apt/trusted.gpg
--------------------
pub   rsa3072 2019-03-18 [SC] [expires: 2026-02-04]
      1505 8500 A023 5D97 F5D1  0063 B188 E2B6 95BD 4743
uid           [ unknown] DEB.SURY.ORG Automatic Signing Key <deb@sury.org>
sub   rsa3072 2019-03-18 [E] [expires: 2026-02-04]


The fix is simple: (after you execute apt update the warning will not be there. If issues, use Google Advanced Search to assist on the exact error you get.)

cd /etc/apt
cp trusted.gpg trusted.gpg.d
apt update
apt upgrade


ATP PACKAGE INSTALLATIONS now that the warnings and errors are fixed.
A t3a.micro instance installs much faster than a t3a.nano instance. Check you did install with GP3 disk, and you used standard credit specifications - see the EC2 top right menu.
These kinds of steps are a learning curve, but should be veery familiar if by the time you start offering the service to others.

apt -y install gnupg

apt -y install php8.2

Re-run this command to make sure gpung2 is insalled:

apt -y install curl gnupg2 ca-certificates lsb-release debian-archive-keyring

apt -y install php8.2-cli php8.2-mbstring php8.2-xml php8.2-common php8.2-curl php8.2-imap php8.2-bz2
apt -y install mariadb

apt -y install php8.2-mysqli php8.2-fpm gcc libjpeg* zip php8.2-zip
apt -y install php8.2-gd

a2enmod proxy_fcgi setenvif
a2enmod ssl
a2enconf php8.2-fpm
a2ensite default-ssl
a2enmod rewrite
systemctl reload apache2

apt -y install libgd-tools ipset

For certbot/lets encrypt: (we do not install the certbot-apache plugin, and we only use pip for updating letsencrypt certificated)

apt -y install python3-venv
apt -y install php8.2-xmlrpc php8.2-soap php8.2-intl
python3 -m venv /opt/certbot/
/opt/certbot/bin/pip install --upgrade pip
/opt/certbot/bin/pip install certbot
ln -s /opt/certbot/bin/certbot /usr/bin/certbot
apt -y install certbot






Install and Configure Mariadb, various PHP, phpMyAdmin

NOTE: I am not installing memcached for apache2. I do however install it for Nginx. I never install ACPU - it has been too problematic for me.

apt install mariadb-server
mysql_secure_installation

"Enter current password for root" (enter for none): 
OK, successfully used password, moving on...
"Switch to unix_socket authentication [Y/n]"  n
"Change the root password?" [Y/n] Y
(nominate your database password)
Y for the remaining questions]

systemctl stop mariadb
systemctl start mariadb
systemctl enable mariadb

systemctl enable apache2
systemctl enable php8.2-fpm


VARIOUS CONFIGURATIONS

cd /
find . -name php.ini -print
./etc/php/8.2/fpm/php.ini
./etc/php/8.2/cli/php.ini
./etc/php/8.2/apache2/php.ini
cd /etc/php/8.2/fpm

Use your own timezone, and modify values to your own preference. If later uploading .sql files through phpMyAdmin, the max file sizees below will apply as a limit.
I prefer 512MB for memory_limit. Others may use 128 or 256. I prefer upload_max_filesise and post_max_size as 100MB.

cp -p php.ini php.ini.bak

vi php.ini

date.timezone = Australia/Brisbane
max_execution_time = 300
max_input_time = 600
max_input_vars = 2500
memory_limit = 512M
post_max_size = 50M
upload_max_filesize = 50M
[save and exit]


cd /
find . -name www.conf -print

./etc/php/8.2/fpm/pool.d/www.conf

cd /etc/php/8.2/fpm/pool.d
cp -p www.conf www.conf.bak

Some fo the following values will already be correct:

vi www.conf

user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
;listen.mode = 0660
listen.mode = 0660
; pm = dynamic
pm = ondemand
pm.max_children = 75
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.process_idle_timeout = 10s;
pm.max_requests = 500

Then at the bottom of the file: (use the same memory value you had in php.ini)

php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_flag[log_errors] = on
php_admin_value[disable_functions] = exec,passthru,system
php_admin_flag[allow_url_fopen] = off
php_admin_value[memory_limit] = 512M
[save and exit]

We add the emergency lines. You can place these lines anywhere near the commented lines for "emergency".
This helps prevent memory leaks, and ability to gracefully use systemctl reload php8.2-fpm on crontab once a night.

cd ..
cp -p php-fpm.conf php-fpm.conf.bak

vi php-fpm.conf

emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 60s
[save and exit]

crontab is already installed on Debian 11. (from memory, I think it is 'apt install cron' on Deb12. I use deb11 at the moment as. know it is stable)
Let's add "reload" for php8.2-fpm to crontab:

crontab -e

15 0 * * * /usr/bin/systemctl reload php8.2-fpm >/dev/null 2>&1
[save and exit]


cd /etc/php/8.2/mods-available
cp -p opcache.ini opcache.ini.bak

vi opcache.ini

zend_extension=opcache.so
opcache.jit=off
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=4000
[save and exit]

apt update
apt upgrade
sync;sync;reboot

Wait a bit and log back in as root. After all configs are done, please use the EC2 console to stop and start the instance for a "clean slate".


cd /var/
chmod 2775 www
cd www
chmod 2775 html
cd html
echo " < ?phpZphpinfo(); ? > "|sed 's/ //g'|sed 's/Z/ /g' > info.php

Create a simple index.html file (you can remove it after installing WordPress). Use your own domain name.
vi index.html

BONJOUR DOMAIN
[save and exit]

cd /var/www/html
chown www-data *
chgrp www-data *
chmod 664 *

We are not yet ready to test info.php or the domain name as we have to install SSL into apache2. We will do this shortly.
We can however next install phpMyAdmin to manage the database.

cd /usr/share

wget https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.gz
ls
tar xvf phpMyAdmin-latest-all-languages.tar.gz
rm phpMyAdmin-latest-all-languages.tar.gz
ls

Use the file name, e.g.:

mv phpMyAdmin-5.2.2-all-languages phpMyAdmin

cd phpMyAdmin

mkdir tmp
chmod 777 tmp
cp -p config.sample.inc.php config.inc.php
vi config.inc.php

Search for the blowfish line and insert an appropriate value in the single quotes. I use the following blowfish generator: (paste the value into your line)

https://phpsolved.com/phpmyadmin-blowfish-secret-generator/?g=[insert_php]echo%20$code;[/insert_php]

Paste the generated value into the blowfish value.
For exmample: $cfg['blowfish_secret'] = 'nzpC-qoCt}t/yTKOp5w0o,ULnX,xdKny';

Then after the SaveDir line, add TempDir...

$cfg['SaveDir'] = '';
$cfg['TempDir'] = '/tmp';
[save and exit]

cd /var/www/html
ln -s /usr/share/phpMyAdmin phpMyAdmin


Freezing Problems with mariadb:

It is sometimes nigh impossible to find where the system freezes when editing or displaying a page even after we have given “good” values in our configurations.

phpMyAdmin has a statistics page that graphically can show all is ok. And Amazon EC2 can show CPU, disk writes, RAM all good.

I don’t have an answer to this, but this may help:

cd /etc/mysql
cp -p my.cnf my.cnf.bak

vi my.cnf

[mysqld]
innodb_buffer_pool_size=512M
optimizer_search_depth=0
log_error=/var/log/mariadb-error.log
log_warnings=9

[save and exit]

At least we now have an error log. You could try omitting the pool size and optimizer lines.

These configurations were found by users on public forums relating to a Help Desk app where the system kept freezing, even though no errors, slow logs, or graphical overloads were shown.

We now wish to add a helpful shell scripts to restart services:

cd /home/admin

vi restart.sh

#!/bin/sh

systemctl restart apache2
systemctl restart mariadb
systemctl reload php8.2-fpm
swapoff -a
swapon -a
free -m
exit

[save and exit]

chmod 777 restart.sh
chown root restart.sh
chgrp admin restart.sh

This helps when testing.
If using crontab, you could use reload instead of restart. We use reload as our preference for php.
swapoff/on is also optional but I use it.
You can also use systemctl status -l SERVIVCE, e.g. /usr/bin/systemctl status -l apache2 to make sure no errors or where errors are being notified.
All log files are under /var/log - e.g. /var/log/apache2. Please check all of these out.

We will now show the optional but helpful use of the Amazon “aws” command to create backups and store in S3 buckets. Then we will address SSL.

phpMyAdmin basics

Using phpMyAdmin is another learning curve.

These configurations make you ready to install WordPress.
Assuming you made a softlink, e.g.:
cd /var/www/html
ln -s /usr/share/phpMyAdmin phpMyAmdin
Then log into phpMyAdmin as root user and password.
https://my_domain.com/phpMyAdmin

Fix the initial error message at the bottom of the screen where it says “find out why”. Just click on the link and follow the fix.

The screen shots below are fairly old, so use utf8mb4_general_ci or utf8_general_ci instead of Latin.

aws software - optional but helpful

Amazon uses the aws command to access S3 buckets. This is useful for storing backup files and databases.

In other notes, I have shown how to create access to S3 buckets from your Linux instance using an IAM role. You can then add that to the EC2 instance from the EC2 console top right menu in your region. (Actions > Security > Modify IAM Role)

To create the Role if not already done, go to IAM > Roles > Add Role
Select Trusted Entity Type: Aws Service, Use Case: S3, then Permissions Policies:

AdministratorAccess
AmazonS3FullAccess
AmazonSESFullAccess
CloudWatchFullAccessV2

The Trust Relationships tab will look like this:
{
“Version”: “2012-10-17”,
“Statement”: [
{
“Effect”: “Allow”,
“Principal”: {
“Service”: “ec2.amazonaws.com”
},
“Action”: “sts:AssumeRole”
}
]
}

When completed, AWS IAM will give you a public and private key. I keep these in a spreadsheet, as you must not lose these.

Then add it to the instance from the Actions pop-down menu as shown above.

To add this to the instance:

cd ~
mkdir .aws
cd .aws

You must have the empty, two blank lines as shown below. Use the Keys you were given when creating the IAM role.
vi config
[default]
aws_access_key_id = AKIA4.........
aws_secret_access_key = 3vvWqH.........

region = ap-southeast-2

[save and exit]

Press the Enter key for each response during the next configuration:
aws configure


Here are two shell scripts that show the use of the aws command. You can modify later when you have a WordPress site, assuming under /var/www/html, and a database with a user created in phpMyAdmin. These can be run via crontab. The shell scripts will use a bucket you previously created in your region. As a side-note, I use Oregon for all email buckets for Australia.

aws COMMAND - THIS IS OPTIONAL BUT VALUABLE - perhaps return to it later

cd /home/admin
vi info.log

[save and exit - just add one blank line]

chmod 777 info.log; chown root info.log; chgrp admin info.log

Use your own S3 bucket (e.g. create one in your region), website directories and names:

vi aws.sh

#!/bin/sh
d=`date | awk '{print $2,$3,$NF}'|tr " " "-"`
echo backups $d >> /home/admin/info.log

tar_html()
{
cd /var/www/
tar cvf domain.tar ./html
# if enough disk space, you can gzip the tar file to save on S3 Bucket space:
# gzip domain-$d.tar
# aws s3 mv domain-$d.tar.gz s3://domain/domain-$d.tar.gz

# if not using gzip:
aws s3 mv domain-$d.tar.gz s3://domain/domain-$d.tar
}

# call the functions - you could have multiple functions for multiple domains and backups, hence the use of functions is easier
tar_html
exit

[save and exit]

vi awsdb.sh

#!/bin/sh
d=`date | awk '{print $2,$3,$NF}'|tr " " "-"`
cd /home/admin
echo database backups $d >> /home/admin/info.log
# Your domain database - these can be any names you wish to use
db_domain()
{
cd /home/admin
mysqlcheck --user=DB_USER --password=DB_PASSWORD DB_NAME >> /home/admin/info.log
mysqldump --user=DB_USER --password=DB_PASSWORD DB_NAME >> /home/admin/DB_NAME-$d.sql
# You can gzip if you wish. This example will not do it.
aws s3 mv DB_NAME-$d.sql s3://domain/.DB_NAME-$d.sql
}

db_domain
exit

[save and exit]

You would have set DB_USER in phpMyAdmin, along with the DB_NAME and DB_PASSWORD.
For example if the user is "snoopy", the database name is "snoo" and you set the password to "H0und#d0g", mysqldump --user=snoopy --password=H0und#d0g snoo >> /home/admin/DB_NAME-$d.sql

It may seem labourious but it is highly useful. You can of course configure without the aws command and S3 buckets for now.

If you configure all this, you can test it. Make sure your IAM role was added in the EC2 console. Debian configurations on other platforms like Akami/Linode can install aws software as well, but a few trial and errors if you do that for the first time, using AWS documentation.

aws s3 ls s3://domain/

Notice how we use the trailing forward slash to list anything. You can also create subdirectories, such as domain/sub or domain/.sub.
For example, s3 ls s3://snoopy.me/.backups/

AWS doco may suggest use of a line like this: aws configure < /home/admin/aws.txt where aws.txt has the same lines we put in ~/.aws/config.







Paid SSL on apache2 for single or multiple domains - Part 1

Obtain your SSL certificate. One way to create the CSR is to open a free account with CleanTalk, and go through the process of creating a certificate, then download or copy the .CSR information, and the .KEY file. (Dashboard > Services > SSL Dashboard)

Here is an example screenshot. When you pay for a certificate e.g. from Comodo Store, (Sectigo for CAA records), you should have your admin@domain email working. Otherwise use the options for a DNS authentication record. I prefer to get emails working first. In the example below, use your ABN name or your registered business name (or trust name – trusts need trust deed documentation for a .com.au or .au top level domain registration.) Just use “IT” for the organisation Unit.

Click Generate, and download the file, then close the browser window or back-step to that you do not actually create it.

In the above example I downloaded laurenceshaw.au.zip. The zip file contains, laurenceshaw_au.csr and laurenceshaw_au.key.

The key file can be kept ad infinitum without renewing it. You transfer this file on Debian Apache2 to /etc/ssl/private.

We use the .csr file at Comodo Store for the lowest cost PositiveSSL(DV), $11.95 AUD at time of writing.

*** Make sure you uncheck any check box for added services they may add by default. ***

Make sure you have added the DNS CAA rcords:

0 issue sectigo.com

0 issue digicert.com

It is best not to have letsencrypt.org as a CAA record if using Paid SSL, or the process can fail and you have to phone their support. If using both free and paid SSL,  use the DNS authentication method that Comodo offers. Letsencrypt should be okay without a record if push comes to shove.

Go through the process by supplying the content to Comodo from the .csr file you made. Once you know how to do this, it is easy thereafter.

You will have to copy a key they send you in an admin@domain email if using the CAA records, then click and verify/paste the key.

The Comodo Store panel will show the status of the certificate. Once okay, you can download the zip file or use an admin@ email they send you to the domain you are registering.

Once you get the file, make sure the CAA records are put in place into the DNS, regardless.

Then you have to manually edit the .crt file (CRT) they sent you. Make a copy so you can edit the original.

Append to it the contents of a file that is names similar to this: SectigoRSADomainValidationSecureServerCA.crt

Then append again the contents of something like: USERTrustRSAAAACA.crt and save.

Do not use a Root certificate – e.g. a name like AAACertificateServices.

If you append content in the wrong order, later when testing at sslabs.com you will see a warning.

Then upload your modified file, e.g. laurenceshaw_au.crt and place in /etc/ssl/certs. I use Filezilla and simply “cp” the file.

Out of interest, Linux2023 would use /etc/pki/tls/certs and private.

When we configure Apache, we can later test the certificate. It will cover domain and www.domain. E.g. laurenceshaw.au and www.laurenceshaw.au

I do not go into more complex use of certificates, or more expensive ones. If you are actually making a lot of sales, you can look at that.

Here are the steps to configure apache2:

Add or modify stanzas as shown here. Lets add a standard domain under /var/www/html, perhaps placing it below whte /var/www stanza.

cd /etc/apache2

vi apache2.conf

<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride All
    Require all granted
 DirectoryIndex index.php index.html
</Directory>

[save and exit]

Add or modify the following, using your own domain name. Again, we are assuming a paid SSL certificate for the moment.
I am showing the full content below.

cd /etc/apache2/sites-available

vi 000-default.conf

<VirtualHost *:80>
ServerName laurenceshaw.au
ServerAlias www.laurenceshaw.au
   Redirect permanent / https://laurenceshaw.au/
   RewriteEngine on
   RewriteCond %{SERVER_NAME} =laurenceshaw.au
   RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
   ServerAdmin webmaster@localhost
   DocumentRoot /var/www/html
   ErrorLog ${APACHE_LOG_DIR}/error.log
   CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

[save and exit]

In the above example, the Rewrite lines are uncommented, as the SSL will be installed into /etc/ssl/...
If you install with Letsencrypt, you must comment the lines out as it is not possible to redirect to https:// and letsencrypt will fail to install.

Here is an example of a stanza you could append after the above configurations for a subdomain called tech.laurenceshaw.au, assuming we will use Letsencrypt. You could also use a different top level domain, e.g. mygreatestwebsite.com.au

<VirtualHost *:80>
  ServerName tech.laurenceshaw.au
#  Redirect permanent / https://tech.laurenceshaw.au/
#  RewriteEngine on
#  RewriteCond %{SERVER_NAME} =tech.laurenceshaw.au
#  RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/tech
  ErrorLog ${APACHE_LOG_DIR}/error.log
 </VirtualHost>
 

You would uncomment these lines after the certbot command installs the free SSL.

Debian 11 should have enabled the modules you need, including rewrite. (I noticed it did not in Debian12)

If we want extra security we should enable the headers module. We can then add some extra code in. /var/www/html/.htaccess later on.

a2enmod headers

The .htaccess code we could use is: (if you get strange behaviour, remove it.)
Do not add the line as some forums use: Header always set Referrer-Policy: "strict-origin" as this will stop a lot of things from working.


Header unset X-Powered-By
Header always set X-XSS-Protection: "1; mode=block"
Header always set X-Content-Type-Options: "nosniff"
Header always set X-Frame-Options: "SAMEORIGIN"
Header always set Content-Security-Policy: "object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self';"
Header always set Permissions-Policy: "autoplay=(), encrypted-media=(), fullscreen=(), geolocation=(), microphone=(), midi=()"
Header always set Clear-Site-Data: "*"
Header always set Strict-Transport-Security: "max-age=31536000; includeSubDomains; preload"


Out of interest, if using the Akamai/Linode service, you have to add the AAA record as well as the A record for domain names.
Letsencrypt would notice if it is missing on that system.

We now configure the default-ssl.conf file. I avoid failures by having all my configs in 000-default.conf and default-ssl.conf.

These files are by default listed in /etc/apache2/sites-enabled. If not, create a soft link.

For instance, you should see under sites-enabled:

ls
lrwxrwxrwx 1 root root 35 Apr 30 10:14 000-default.conf -> ../sites-available/000-default.conf
lrwxrwxrwx 1 root root 35 Apr 30 10:19 default-ssl.conf -> ../sites-available/default-ssl.conf

Let us say default-ssl.conf was missing (!) We can fix by this command:

If a default file is missing from sites-enabled - this is an example only.

cd /etc/apache2/sites-enabled

ln -s ../sites-available/ssl-default.conf ssl-default.conf

ls
lrwxrwxrwx 1 root root 35 Apr 30 10:14 000-default.conf -> ../sites-available/000-default.conf
lrwxrwxrwx 1 root root 35 Apr 30 10:19 default-ssl.conf -> ../sites-available/default-ssl.conf

You can search the internet for the other common a2... commands if needed. e.g. "How to enable a site on apache2" or enable a mod, or enable a conf file.

The default-ssl.conf file content, for a PAID SSL certificate (using my example domain of laurenceshaw.au from Comodo Store)

In this example, recall that the 000-default.conf file does not need to comment out the Rewrite rules, whereas Letsencrypt would need to.
We would not add the default-ssl.conf file configurations for a domain intended for Letsencrypt at this point. We would install the SSL, then update default-ssl.conf to be correct, and then remove the commented Rewrite lines from 000-default.conf – then restart apache2.

I will show the full content, so add what is missing, with your own domain name and certificate locations.

cd /etc/apache2/sites-available

cp -p default-ssl.conf default-ssl.conf.bak
The ssl module should be enabled already. Otherwise "a2enmod ssl"

vi default-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost _default_:443>

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        SSLEngine on

SSLCertificateFile    /etc/ssl/certs/laurenceshaw_au.crt
SSLCertificateKeyFile /etc/ssl/private/laurenceshaw_au.key
SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLProxyProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLProxyCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
SSLHonorCipherOrder on
SSLCompression off
SSLInsecureRenegotiation Off
SSLSessionTickets Off
SSLOpenSSLConfCmd ECDHParameters secp384r1
SSLOpenSSLConfCmd Curves secp384r1
# you will see a stanza for FilesMatch that we do not edit     

 <FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>

 </VirtualHost>

# YOU WOULD PUT MULTI-DOMAIN STANZAS IN HERE

</IfModule>

[save and exit]

Restart apache and test the website works. You can have a simple index.html file you can delete later, or the info.php file.
E.g. https://laurenceshaw.au/info.php
Test the index.html file you create so that you know the system should be fully working.
Then test phpMyAdmin, where previously you installed it, and had a softlink under /var/www/html
lrwxrwxrwx  1 root     www-data    21 Dec  3 16:27 phpMyAdmin -> /usr/share/phpMyAdmin

https://laurenceshaw.au/phpMyAdmin

You should not need a phpMyAdmin.conf file.

Now.... lets see what a multi-domain config looks like.
You would keep the Rewrite lines commented out in 000-default.conf, and not have any entry for the new domain in default-ssl.conf.
Once certbot adds the certificate, remove the comments from 000-defaultconf, then append something like this after the previous virtual host stanza:

<VirtualHost *:443>
 ServerName tech.laurenceshaw.au:443
 DocumentRoot /var/www/tech
 SSLEngine on
 SSLCertificateFile  /etc/letsencrypt/live/tech.laurenceshaw.au/fullchain.pem
 SSLCertificateKeyFile /etc/letsencrypt/live/tech.laurencehaw.au/privkey.pem
SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLProxyProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLProxyCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
SSLHonorCipherOrder on
SSLCompression off
SSLInsecureRenegotiation Off
SSLSessionTickets Off
SSLOpenSSLConfCmd ECDHParameters secp384r1
SSLOpenSSLConfCmd Curves secp384r1

</VirtualHost>
And restart apache2. Then test the web browser.

Test your SSL with https://www.ssllabs.com/ssltest/
It will give an A rating. If you put in the Headers for .htaccess you may get an A+ rating. You really only need A.

Free SSL - Letsencrypt (certbot) - apache2 for single or multiple domains - Part 2

LetsEncrypt can be tricky. To do a fresh installation, you usually have the CAA record (but not critical), as “0 issue letsencrypt.org”.
You must have your 000-default.conf file with no lines referencing a rewrite to https, as https does not yet exist.
You move default-ssl.conf to default-ss.conf.bak so that there is no SSL configuration involved.
You use –dry-run until you get a success message.
You then un-comment the rewrite rules, and edit the ssl conf file to have the domain name for port 443, and add the certificate paths. Restart apache2 and you are good to go by testing your https://domain.com site.


Here are example commands:

cd /etc/apache2
cd site-av*
pwd

vi 000-default.conf

(Uncomment any Rewrite redirections to https for the proposed domain. See Part 1 above for the 000-default.conf file contents)

[save and exit]

mv default-ssl.conf default-ssl.conf.bak
systemctl restart apache2

(Use your own email that you like to have for registering domains with letsencrypt, and use your domain, subdomain, or other domain as shown.
The example has me@gmail.com and laurenceshaw.au with /var/www/html as the website directory.)

/usr/bin/certbot certonly --non-interactive --agree-tos -m me@gmail.com  -d laurenceshaw.au --webroot -w /var/www/html --dry-run

 - The dry run was successful.

Now remove the ---dry-run and execute it.

Then edit the .conf files, as shown in Part 1 above. I'll give contents here in case it helps.

vi 000-default.conf

(remove comments from the domain's rewrite lines.)

<VirtualHost *:80>
   ServerName laurenceshaw.au
   ServerAlias www.laurenceshaw.au
   Redirect permanent / https://laurenceshaw.au/
   RewriteEngine on
   RewriteCond %{SERVER_NAME} =laurenceshaw.au
   RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

[save and exit]

If you were working on a multi-domain or subdomain, you'd have a stanza(s) below this that look like this after SSL is installed and you removed the comments rewrites:

<VirtualHost *:80>
  ServerName tech.laurenceshaw.au
  Redirect permanent / https://tech.laurenceshaw.au/
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =tech.laurenceshaw.au
  RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/tech
  ErrorLog ${APACHE_LOG_DIR}/error.log
 </VirtualHost>
 


Now we fix the default-ssl.conf file:

cp -p default-ssl.conf.bak default-ssl.conf

vi default-ssl.conf

<IfModule mod_ssl.c>
        <VirtualHost _default_:443>
                ServerAdmin webmaster@localhost

                DocumentRoot /var/www/html
                
                ErrorLog ${APACHE_LOG_DIR}/error.log
                CustomLog ${APACHE_LOG_DIR}/access.log combined
                SSLEngine on

 SSLCertificateFile    /etc/letsencrypt/live/laurenceshaw.au/fullchain.pem
 SSLCertificateKeyFile /etc/letsencrypt/live/laurenceshaw.au/privkey.pem

 SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
 SSLProxyProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2

 SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
 SSLProxyCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
 SSLHonorCipherOrder on
 SSLCompression off
 SSLInsecureRenegotiation Off
 SSLSessionTickets Off
 SSLOpenSSLConfCmd ECDHParameters secp384r1
 SSLOpenSSLConfCmd Curves secp384r1
                <FilesMatch "\.(cgi|shtml|phtml|php)$">
                                SSLOptions +StdEnvVars
                </FilesMatch>
                <Directory /usr/lib/cgi-bin>
                                SSLOptions +StdEnvVars
                </Directory>
        </VirtualHost>
</IfModule>

[save and exit]

systemctl restart apache2

(If errors, see systemctl status -l apache2)

Note that there are two long lines, SSLCipherSuite and SSLProxyCipherSuite that must be one line each, not accidentally split into multiple lines by your editor.

Now we can add an example of a multi-domain.

Append after the above </VirtualHost> stanza, and before </If Module> the following: (with your own domains that configiured SSL correctly)

vi default-ssl.conf

<VirtualHost *:443>
 ServerName tech.laurenceshaw.au:443
 DocumentRoot /var/www/tech
 SSLEngine on

 SSLCertificateFile      /etc/letsencrypt/live/tech.laurenceshaw.au/fullchain.pem
 SSLCertificateKeyFile   /etc/letsencrypt/live/tech.laurenceshaw.au/privkey.pem

 SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
 SSLProxyProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2

 SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
 SSLProxyCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
 SSLHonorCipherOrder on

 SSLCompression off
 SSLInsecureRenegotiation Off
 SSLSessionTickets Off
 SSLOpenSSLConfCmd ECDHParameters secp384r1
 SSLOpenSSLConfCmd Curves secp384r1

</VirtualHost>

[save and exit]

Restart apache2.

I don't like adding configuration files outside these default files. I've found in the past added files do not always work.

Free SSL - Letsencrypt (certbot) Auto-renewal script - Part 3

We now need a shell script to auto-renew Lets Encrypt

Replace with your own values as mentioned in Part 2 above.

cd /home/admin

vi certbot.sh

#!/bin/bash
d=`date`
c1=`head -1 /home/admin/certbot.dat`
c1=$(expr $c1 + 1)
if [ "$c1" = "65" ] ;
then
echo "0" > /home/admin/certbot.dat
echo "Certbot Renewal" $d >> /home/admin/info.log
/usr/bin/certbot -v certonly --non-interactive --agree-tos -m me@gmail.com -d laurenceshaw.au --webroot -w /var/www/html >/dev/null 2>&1
sudo /usr/bin/systemctl reload apache2 >/dev/null 2>&1
sudo /usr/bin/openssl x509 -noout -dates -in /etc/letsencrypt/live/laurenceshaw.au/cert.pem >> /home/admin/info.log
else
echo "Certbot day $c1 of 65" >> /home/admin/info.log
echo $c1 > /home/admin/certbot.dat
fi

sleep 10

d=`date`
c1=`head -1 /home/admin/certbot_tech.dat`
c1=$(expr $c1 + 1)
if [ "$c1" = "65" ] ;
then
echo "0" > /home/admin/certbot_tech.dat
echo "Certbot Renewal" $d >> /home/admin/info.log
sudo /usr/bin/certbot -v certonly --non-interactive --agree-tos -m me@gmail.com -d tech.laurenceshaw.au --webroot -w /var/www/tech >/dev/null 2>&1
sudo /usr/bin/systemctl reload apache2 >/dev/null 2>&1
sudo /usr/bin/openssl x509 -noout -dates -in /etc/letsencrypt/live/tech.laurenceshaw.au/cert.pem >> /home/admin/info.log
else
echo "Certbot day $c1 of 65" >> /home/admin/info.log
echo $c1 > /home/admin/certbot_tech.dat
fi

exit

[save and exit]

You could of course have these stanzas as shell script functions.
e.g.
domain()
{
insert code lines here....
}
dubdomain()
{
insert code lines here...
}

domain
subdomain

exit


This way you can manage lots of domains simply by commenting our those you don't want at any particular time.

Insert a blank line into info.log
Add a single line to certbot.dat and in this example also to certbot_tech.dat with the numeral 0 at the top as the only line.

chmod 777 info.log certbot.*
chown root certbot* info.log
chgrp admin certbot* info.log

crontab -e

15 1 * * * /home/admin/certbot.sh

[save and exit]

*** If your certbot.dat files are somehow corrupted with the wrong numerals, you can use the line (for your domain): ***
/usr/bin/openssl x509 -noout -dates -in /etc/letsencrypt/live/laurenceshaw.au/cert.pem

and work out how many days the certificate has been running, and put into that single top line of the .dat file.
Otherwise, if the renewal fails, you have to go through the whole process again of editing the 000-default.conf and default-ssl.conf files.

We use 65 days (approx) for renewals. Less than this usually fails. The shell script is not checking for failure or fixing the .dat files.)

We do not install the certbot apache plugin. We only use the above commands.

You could install postfix and sendmail scripting if you wish, to notify if the SSL certificate has expired. A fair bit of work to do that.

You can also monitor your website with Uptime Robot, but that does not check for SSL working.

Adding WordPress

You do need to learn how to use https://your_domain.com/phpMyAdmin.
See the section above on “phpMyAdmin basics”.
We can add a database now usually as utf8mb4_general_ci or utf8_general_ci.
Then we add a user for administrating it – username, localhost, password, and grant all permissions to that database.
If you do not use phpMyAdmin you need to see other articles or documents from Amazon’s installation of WordPress.
The default phpMyAdmin installation will show at the bottom of the screen a missing database that you simply click on to install.
Let’s assume you have this done.

Recall you would have used “ln -s /usr/share/phpMyAdmin phpMyAdmin” to link phpMyAdmin into your /var/www/html directory (or where you choose to have it)


Upload WordPress to your site, unzip and place the contents into /var/www/html or where you need for the domain.

e.g.

cd /var/www/html
unzip wordpress-6.8.1-en_AU.zip
cd wordpress
mv * ..

cd ..

./chdir.sh. ---> this is a script shown below.

 

We need a shell script to change permissions:

cd /var/www/html

vi chdir.sh

#!/bin/sh
chown -R www-data *
chgrp -R www-data *
find . -type d -exec chmod 2775 {} \;
find . -type f -exec chmod 0664 {} \;
if [ -f "./.htaccess" ] ; then
chown www-data .htaccess
chgrp www-data .htaccess
chmod 664 .htaccess
fi
chmod 777 *.sh
chown root chdir.sh
chgrp root chdir.sh
chmod 770 chdir.sh
exit

[save and exit]

chmod 777 chdir.sh

After placing WordPress files, in this example into /var/www/html:

./chdir.sh

I have /var/www/html as chmod 2775, chdir www-data and chgrp www-data,
and /var/www as chmod 2775

Make sure your installation directory no longer has any test index.html file. We want PHP to run by default.

Then you can run the WP install script with https://my_domain.com

If the installation tries to use FTP, your permissions are incorrect. Check /var/www/html is www-data group and owner, and 2775 permissions. www can be root, but check it is 2775.

I prefer using the same admin user and password as the database itself.

Then test your WordPress installation can login and works.



If you add the Wordfence plugin and have issues, remember it is installing hidden files in /var/www/html and files in /var/www/html/wp-content/ and /var/www/html/wp-content/plugins. There will be a stanza in wp-config.php which may be referencing an incorrect PHP version. I once had to add these lines:

<IfModule mod_php8.c>
        php_value auto_prepend_file '/var/www/html/wordfence-waf.php'
</IfModule>

I doubt you will, but you can see how configurations sometimes need problem solving and how code can change over time from the developers.

At the end of your wp-config.php file, you can add these lines for your memory, ability to upload any type of file to the media library, and use of the SMTP email plugin so that emails can be routed through Amazon. If using MS Exchange, as an example, you would use different settings.

define('WP_MEMORY_LIMIT', '512M');
define('DISALLOW_FILE_EDIT', true);
define( 'ALLOW_UNFILTERED_UPLOADS', true );
define('DISABLE_WP_CRON', true);
define( 'WPMS_ON', true );
define( 'WPMS_SMTP_PASS', 'YOUR AMAZON IAM SMTP PRIVATE KEY' );

Here is an example of the SMTP plugin using MS Exchange as the router. All this depends on DNS records being previously setup correctly.

WP Mail SMTP Plugin - example of MS Exchange

From Email: contact@laurenceshaw.au
Force From Email: ON
From Name: Laurence Shaw
Force From Name: ON
Return Path: ON
Mailer: Other SMTP
SMTP Host: smtp-mail.outlook.com
Encryption: TLS
SMTP Port: 587
Authentication: ON
SMTP Username: contact@laurenceshaw.au
SMTP Password: THIS GOES INTO THE wp-config.php FILE

Here is an example of Amazon Oregon as the router:

WP Mail SMTP Plugin - example of Amazon AWS SES router, Oregon

From Email: contact@laurenceshaw.au
Force From Email: ON
From Name: Laurence Shaw
Force From Name: ON
Return Path: ON
Mailer: Other SMTP
SMTP Host: email-smtp.us-west-2.amazonaws.com
Encryption: TLS
SMTP Port: 587
Authentication: ON
SMTP Username: AKIA................   (YOur own IAM SES email keys)
SMTP Password: THIS GOES INTO THE wp-config.php FILE

Start typing and press Enter to search