openec2 Article Description

Amazon Linux2023 Nginx for a WordPress Installation

This article assumes you know how to install the instance and other matters as shown in my other articles.

After installations, make sure systemctl status -l has no errors on the time stamp when you restart a service.
e.g. systemctl status -l mariadb
This is important do do, and to fix errors.

It helps to do a full system stop/restart or at least a reboot after the installation. This may clear up issues.

We want to get memcached.so configured first. This is needed for phpMyAdmin later on.

If not using memcached, it is not needed. I prefer memcached for slightly faster performance.

Install Linux 2023 as a bland installation.

Add your swap space.
Login is root, sudo su, and set -o vi.

[I use 768MB swap disk. I see no point in 1GB as the system will freeze up prior to that]

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=786432
mkswap /swapfile
chmod 0600 /swapfile
swapon /swapfile
echo "/swapfile swap swap defaults 0 0" >> /etc/fstab

Do the dnf update/upgrade procedure:

dnf check-release-update

[Choose current version. e.g. dnf list | grep php, then install php8.3 or whatever version]
dnf install php8.3

Then go further below in these notes, and install the php- packages - e.g. php-devel. Don't use the -y option so you can check it will install 8.3. See lines 69-76. Then attend to the install notes before and after those lines if installing memcached next.

Then run these scripts below to install php memcached if you wish to use it, and fix errors. If you cannot fix errors, it means more code has changed on Amazon, and for example, phpMyAdmin will not work, which voids the use of the instance. Default workaround is Debian 12 ARM. We have to have memcached.so installed as the php connector to memcached.

Find the php versions. e.g. 8.3. If you are on 8.4 or higher, edit the script below to use that instead of 8.3:

dnf list|grep php
At some point this script will fail. Run it and then do the commands after.
Reference: https://github.com/amazonlinux/amazon-linux-2023/issues/208


cd /home/ec2-user

dnf -y install php8.3-devel php-pear gcc && \
   pear update channels && \
   pecl update channels && \
   \
   # build + install igbinary for use by php-memcached

   
   pecl install igbinary && \
   echo "extension=igbinary.so" | sudo tee /etc/php.d/20-igbinary.ini && \
   \
   # build + install msgpack for use by php-memcached
   pecl install msgpack && \
   echo "extension=msgpack.so" | sudo tee /etc/php.d/20-msgpack.ini && \
   \
   # build + install php-memcached
   dnf install -q -y memcached-devel memcached \
       libmemcached-awesome-devel libmemcached-awesome \
       zlib-devel zlib cyrus-sasl cyrus-sasl-devel \
       libevent libevent-devel && \
   pecl install --configureoptions \
      'with-zlib-dir="no" \
       with-system-fastlz="no" \
       with-libmemcached-dir="no" \
       enable-memcached-igbinary="yes" \
       enable-memcached-msgpack="yes" \
       enable-memcached-json="yes" \
       enable-memcached-protocol="yes" \
       enable-memcached-sasl="yes" \
       enable-memcached-session="yes"' memcached &&  \
   echo "extension=memcached.so" | sudo tee /etc/php.d/25-memcached.ini && \
   \
   # clean up php dev tools and the dnf cache
   dnf remove -y gcc php8.3-devel php-pear libzip-devel \
      memcached-devel libmemcached-awesome-devel zlib-devel \
      cyrus-sasl-devel libevent-devel && \
   dnf autoremove -y && dnf clean all && rm -rf /var/cache/dnf


[Now run:]

pear update-channels
pecl update-channels

[Now run these commands to fix the errors:]

dnf install -q -y memcached-devel libmemcached-awesome-devel zlib-devel cyrus-sasl-devel libevent-devel
/usr/bin/yes 'no' | pecl install --configureoptions 'enable-memcached-igbinary="yes" enable-memcached-msgpack="yes" enable-memcached-json="yes" enable-memcached-protocol="yes" enable-memcached-sasl="yes" enable-memcached-session="yes"' memcached
echo 'extension=memcached.so' > /etc/php.d/41-memcached.ini


[Now check /etc/php.d as the 41-memcached.file. You can see where these scripts fail, and modify which lines to run.]

cd /
find . -name memcached.so -print
./usr/lib64/php8.3/modules/memcached.so

[Without this file, phpMyAdmin will not work.]



[Use your own Country/City. See /usr/share/zoneinfo]

a="Australia/Brisbane";export a;echo $a
ln -sf /usr/share/zoneinfo/$a /etc/localtime
date

[Change /etc/bashrc. Use your own domain name:]

vi /etc/bashrc

# [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
  [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@mydomain.com: \w]\\$ "

[save and exit]

vi /etc/selinux/config

# SELINUX=permissive
SELINUX=disabled

[save and exit]

[Create a backup/backdoor user if ec2-user is compromised for any reason: Use your own name instead of "snoopy". You may get an error which you can correct as shown below.]

adduser snoopy
[Give snoopy a password:]

Add snoopy to /etc/sudoers - note, when 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.

vi /etc/sudoers

snoopy ALL=(ALL) NOPASSWD:ALL

[Exit the file after saving with :w! by using SHIFT ZZ]
[Add the user to groups admin and root:  (for Linux 2023, it is wheel and root)]

sudo usermod -aG adm snoopy; sudo usermod -aG root snoopy

[We will make a copy of a good verion of /home/admin/.ssh to /home:]

cd /home/ec2-user
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, e.g. snoopy as shown above]

[We continue the installation:]

[dnf check-release-update was previously done when dealing with memcached.so]

[Some of these will already be installed... DOuble check php-common is installed - "dnf list|grep php|more"]


dnf install -y php-pear wget php-mysqli php-devel php-mbstring
dnf install -y php-cli php-pdo php-fpm php-json php-mysqlnd php-opcache
dnf install -y gd libzip-devel kernel-devel php-gd
dnf install -y cronie cronie-anacron
dnf -y install pcre-devel gcc zlib zlib-devel
dnf -y install mariadb105
dnf -y install mariadb105-server
dnf -y install libjpeg-turbo-utils

I do not do dnf remove *apache* as there are dependencies.

We do need to have memcached installed for nginx to cache with marked improvement. I have website without it and no issues. I use w3 Total Cache plugin to make use of memcached in WordPress.

I had an error when I first tried to install zip. We need it. If an error, just check no error message on a missing package, and if it appears missing but is present, reinstall with dnf reinstall, and check the channel-update is done.

pecl install zip
pecl channel-update pecl.php.net

[Check the extension exists:]
find . -name zip.so -print
./usr/lib64/php8.3/modules/zip.so

We configure php:

[Use your own Country/City. I use 512MB as memory. You may use 256, but I am hesitant these days with more load on PHP to do that.]

vi /etc/php.ini

;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;
extension=zip.so;

date.timezone = Australia/Brisbane
max_execution_time = 300
max_input_time = 600
max_input_vars = 2500
post_max_size = 100M
upload_max_filesize = 100M
max_file_uploads = 20
memory_limit = 512M

[If using memcached correct php.ini:]

# session.save_handler = files
  session.save_handler = memcached
  session.save_path = "127.0.0.1:11211"

[save and exit]

vi /etc/php.d/10-opcache.ini

opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=4000

[save and exit]

cd /etc/php-fpm.d

cp -p www.conf www.conf.o

vi /etc/php-fpm.d/www.conf

user = nginx
group = nginx 
; listen.acl_users = nginx,nginx ---> these must be or remain commented as shown here
; listen.acl_groups =
; 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
php_admin_value[disable_functions] = exec,passthru,system
php_admin_flag[allow_url_fopen] = off
php_admin_value[memory_limit] = 512M
php_value[opcache.file_cache]  = /var/lib/php/opcache

[Note: I have not uncommented opcache before, but it makes sense to do so.]

[If using memcached, fix as follows:]
; php_value[session.save_handler] = files
; php_value[session.save_path]    = /var/lib/php/session
php_value[session.save_handler] = memcached
php_value[session.save_path]    = 127.0.0.1:11211

[save and exit. Note the timeout line has a semicolon at the end]

[We do not add a memory or autosave value in WordPress wp-config.php when using Nginx.]
[We add the next three lines to php-fpm.conf so we can use systemctl reload php-fpm, rather than restart, and for memory leaks - according to Internet forums]

vi /etc/php-fpm.conf

emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 60s

[save and exit]

[We use crontab to safely reload php-fpm once a night, here shown at 5 past midnight]

crontab -e
5 0 * * * /usr/bin/systemctl reload php-fpm >/dev/null 2>&1

[save and exit]

[If using Let's Encrypt:]

dnf -y install python3 python3-devel augeas-libs
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

[Install Mariadb:]

systemctl start mariadb
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]

[We now start and enable our mariadb services. Enabling means they start at a reboot.]

[If any problems, stop and restart your EC2 instance or do "sync;sync;reboot"]

systemctl stop mariadb
systemctl start mariadb
systemctl enable mariadb

[There is a problem in the current Linux2023 as at writing, where systemctl status -l mariadb says: Database MariaDB is probably initialized in /var/lib/mysql already, nothing is done.
Just ignore this as ps -ef|grep mariadb shows the database is fine. I have not found how to correct this as yet.]

systemctl enable php-fpm
systemctl start php-fpm

[Install phpMyAdmin the same way as in the Debian 11 Nginx article, Part 6:]

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
mv phpMyAdmin-5.2.1-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. Do a Google search on blowfish phpmyadmin generator.
Avoid slashes and exlamation marks in the generator's output, so yu get used to avoiding these in general IT usage.
I use: https://phpsolved.com/phpmyadmin-blowfish-secret-generator/?g=[insert_php]echo%20$code;[/insert_php] from https://phpsolved.com.
Paste the generated value into the blowfish value.
Then after SaveDir as shown below, add TempDir...]
$cfg['SaveDir'] = '';
$cfg['TempDir'] = '/tmp';

[save and exit]

[Permissions need to be set for nginx:]
cd /usr/share
chgrp nginx phpMyAdmin
chmod 775 phpMyAdmin
ls -l | grep phpMyAdmin
drwxrwxr-x.  13 root nginx 16384 Oct  6 19:48 phpMyAdmin
cd phpMyAdmin
chown nginx index.php
chmod 664 index.php
ls -l
-rw-r--r--.  1 nginx root   1074 Feb  8  2023 index.php

[Make sure your domain name DNS records are correct and the A record uses the instance IP4 address. As we are not configuring IP6 on the instance, we do not use an AAAA record. If we did ahve IP6, you would need an AAAA record as well.]

[Here is an example of how you link to phpMyAdmin from the browser. Due to security, DO NOT log into phpMyAdmin until after we install Nginx and https:// is working. 

cd /var/www/html
pwd
ln -s /usr/share/phpMyAdmin phpMyAdmin
ls -l

[Note: you never want to change the ownerships and permissions of soft links. Be careful of this when changing permissions of WordPress files in the same directory.]

[To get phpmyadmin to work have nginx group as shown:]

cd /var/lib/php
ls -l
total 0
drwxrwx---. 2 root nginx 6 Feb 13 06:23 opcache
drwxr-xr-x. 2 root root   6 Feb 13 06:23 peclxml
drwxrwx---. 2 root nginx 6 Feb 13 06:23 session
drwxrwx---. 2 root nginx 6 Feb 13 06:23 wsdlcache

[fyi: later you can create databases in phpMyAdmin with utf8mb4_general_ci if you like]

[Check permissions and ownershios for the default /var/www/html directories we will use with Nginx. The same applies to multi-domains under, say, /var/www.]

cd /var
ls -l

[Set these permissions: drwxrwsr-x 12 root nginx 4096 Aug  2 00:00 www]
[e.g. chown root www;chgrp nginx www;chmod 2775 www]

cd /var/www
ls -l

[If html is not present, create it with "mkdir html"]
[Set these permissions: drwxrwsr-x  3 nginx nginx  4096 Jul 17 16:30 html]
[e.g. chown nginx html;chgrp nginx html;chmod 2775 html]

[Add the phpinfo.php file which we will use after Nginx is configured, to verify php configurations, including memcached if installed:]

echo " < ?phpZphpinfo(); ? > "|sed 's/ //g'|sed 's/Z/ /g' > phpinfo.php
chown nginx p*; chgrp nginx p*; chmod 664 p*
ls -l


[When we do install nginx, there is a process we go through to add SSL certificates. To test https://mydomain.com, you would use https://mydomain.com/phhpinfo.php, or add a dummy index.html file:]
cd /var/www/html

vi index.html

testing mydomain.com

[save and exit]

[Make sure your file(s) in /car/www/html are chown nginx *; chgrp nginx *; chmod 664 *]

If you wish to install ImageMagick for shell scripting purposes: (e.g. to convert from your photo album images equivalent square-shaped thumbnails)

(If needed, one can install php-imagick for Debian 11 by searching on how to do that, but I don’t see enough reason to install it or pursue that here on AL23.

dnf install ImageMagick

Note that I do not use php-imagick, which is available on Debian but not as a standard package on Linux2023. I use ImageMagick to do converions on photography images on my primary website galleries. The WP Plugin ewww may say there is an issue, so yu could follow up on that, perhaps with a test EC2 instance. I never use ewww for compression as my images are already the size I want from my photography Nikon Dx0 software. I dislike optimized compression as it impacts image quality too much.

Sections of the following references may be helpful. We need to install the current stable version of Nginx on Linux 2023.

We do not use dnf install nginx.

https://nginx.org/en/linux_packages.html#Amazon-Linux

https://www.cloudwithxavier.com/install-memcached-on-amazon-linux-2023-ami/

https://docs.aws.amazon.com/linux/al2023/ug/hosting-wordpress-aml-2023.html

Install Nginx:
This is the only way I could get the newer version of nginx.

dnf install yum-utils

[In the vi editing below, we must include the lines that have [....] in them.]

dnf install nginx
dnf remove nginx

SEE: https://nginx.org/en/linux_packages.html#Amazon-Linux

vi /etc/yum.repos.d/nginx.repo

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/amzn/2023/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
priority=9

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/amzn/2023/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
priority=9

[save and exit]

yum-config-manager --enable nginx-mainline
[I think the next line fails, but I used it anyway.]
yum reinstall nginx
[If it did install, remove and install again if the version is not 1.27 or higher. We do not want 1.24 or lower.]

dnf install nginx.  ---> it prompt for the Enter key a few times. 

[Just check these commands have been done somewhere along the way:]

[Just in case:]
dnf install libgd
dnf install lib-gd
dnf install gd

nginx -t

We now need to configure nginx before using it. See my notes on nginx to do this.
Also:
When we start nginx, we likely receive an error from the status command: [you have to make your shell terminal screen quite wide to see full error messages displayed]
systemctl status -l nginx
nginx.service: Can't open PID file /run/nginx
[If you get this, our reference for the fix is: https://serverfault.com/questions/1042526/open-run-nginx-pid-failed-13-permission-denied]
mkdir -p /etc/systemd/system/nginx.service.d
[Create these lines:]
vi /etc/systemd/system/nginx.service.d/override.conf
[Service]
ExecStartPost=/bin/sleep 0.1
[save and exit]
systemctl daemon-reload
systemctl restart nginx
systemctl enable nginx
systemctl status -l nginx ------ check the top lines for the /run/nginx.pid or /var/run/nginx.pid if you get an error in the status

You can create simple 404.html 50x.html and index.html files for your /var/www/html directory. (I can’t provide these here as it conflicts with my editing software and nginx)

To configure Nginx, please see Debian 11 – Part 7. I refer to this article as there a quite a few things to do.

Remember that when you include additional .conf files from my Scripts – Part 1 article, this can prevent wp-login.php or WordPress updates from executing, so just keep that in mind as yu can comment out an include file in your configs as a temporary measure.

When referring to the Debian Nginx article, we do not use php8.3 references but php-fpm, and fastcgi_pass unix:/run/php-fpm/www.sock;

And, we should approach memcached as a separate exercise, excluding it from our configurtions, until later when using the Linux 2023 – Nginx memcached article.

Keep in mind that a paid SSL certificate usually goes to these directories, and not /etc/ssl:

     ssl_certificate “/etc/pki/tls/certs/mydomain_com.crt”;

      ssl_certificate_key “/etc/pki/tls/private/mydomain_com.key”;

The Debain 11 article gives more information on how to obtain certificates – -which is quite a learning curve.