Install WordPress with Ubuntu 20.04, Apache2, MariaDB and PHP 8.1-FPM

If you’re planning to host WordPress at Cloud Server, this guide is going to be helpful for you.

WordPress Apache2 Install

LAMP stands for Linux, Apache, MariaDB and PHP softwares which combined together known as LAMP stack.

Pros & Cons of choosing Apache web server over NGINX

  • Pros: It supports .htaccess file that is commonly used by many Page Caching & Optimization. This is a great choice for non-coder.
  • Cons: It is slightly less performant than NGINX but that can be managed using APO. For a high traffic site, LEMP stack is the best choice.

Follow these 3 steps and watch the video. Need help? Contact me. 😊

  1. Setting up Cloudflare DNS
  2. Getting Ubuntu Server
  3. Deploying LAMP Stack

Now before you get started, here’s a quick tip. Use Search and Replace Extension to bulk change example.com to your own domain in this web page.

Time-saving tip for Google Chrome users.
search replace

Part A: Keep Cloudflare Nameservers active

We will be using Cloudflare DNS for getting Let’s Encrypt Wildcard SSL certificate. Complete this step first to enjoy zero-downtime migration.

Check Current Nameservers

Part B: Get a Ubuntu Server 20.04 LTS Server ready

Ubuntu
Ubuntu logo

1. Sign up Vultr to grab $100 Free credits (Valid for 30 days)

As someone who have tried so many Cloud server company, my experience says you can’t go wrong with Vultr. These guys are genuine and caring when it comes to support and services.

vultr

⚡ Performance

  • 3rd Generation AMD EPYC™
  • NVME / SSD
  • Up to 4 GHz CPU
  • Up to 5Gbps Network Speed
  • Datacenter in America, Europe, Asia, Austraillia
  • IPV6 ready

💡 Features

  • Beginner-Friendly Dashboard
  • One-click to Snapshot
  • Automtatic Backup (Paid)
  • Free Cloud Firewall
  • DDoS protection (Paid)
  • 100% KVM Virtualization

⚙ Support

  • PayPal/Card
  • 24/7 Ticket Support
  • Documentation

2. Deloy a New Server

Simply click on the plus button to get started

Deploy New Server

3. Choose Server type

Select Cloud Compute for shared CPU in affordable pricing.

Cloud Compute

Next, you need to choose CPU & Storage Technology, you can opt for “AMD High Performance”.

cpu and storage technology

4. Choose a Server Location

Vultr offers server in the four continents. For the lowest latency and best performance, you should always choose a region that is closest for your audience. For example, if 99% traffic comes from India, you can choose Mumbai. If temporarily unavailable, then you may choose Singapore.

America

  • Miami, United States
  • Atlanta, United States
  • Chicago, United States
  • Dallas, United States
  • Honolulu, United States
  • Los Angeles, United States
  • Mexico City, Mexico
  • New York (NJ), United States
  • Seattle, United States
  • Silicon Valley, United States
  • Toronto, Canada, São Paulo

Europe

  • Stockholm, Sweden
  • London, United Kingdom
  • Amsterdam, Netherlands
  • Frankfurt, Germany
  • Madrid, Spain
  • Paris, France
  • Warsaw, Poland

Australlia

  • Sydney, Australlia
  • Melbourne, Australia

Asia

  • Tokyo, Japan
  • Mumbai, India
  • Seoul, South Korea
  • Singapore, Singapore
vultr regions

5. Select the Server Image > Operating System > Ubuntu 22.04 LTS x64

Long-term support (LTS) is a product lifecycle management policy in which a stable release of computer software is maintained for a longer period of time than the standard edition.

ubuntu releases 2
ubuntu os

6. Choose a Server Size

server size

$6/mo plan would be a great starting point for a new blog. You can upgrade anytime as per requirement.

Tip: If you are migrating, check Total installation size in Site health info.

Checking WordPress Installation Size in WordPress Site Health

7. Enable IPV6, Backup

enable ipv6 and automatic backup vultr

8. Add a SSH key

This is a recommended, optional step for the enhanced security.

Add SSH key
  • Click on Add New button to add a new SSH key to submit your 🔒Public key.
  • Generate Keys using below method as per your OS.
win os
  • Download PuTTy application.
  • Search for PuTTygen in the Start menu
  • Click on Generate button and hover mouse pointer
  • Copy Public key and provide to Vultr
  • Enter key passphrase
  • Save 🔑Private Key at the safest location.
  • This can be used for login to SSH or SFTP.
linux 2
  • Run: ssh-keygen -t rsa. For a more secure 4096-bit key, run: ssh-keygen -t rsa -b 4096
  • Press enter when asked where you want to save the key (this will use the default location).
  • Enter a passphrase for your key.
  • Run cat ~/.ssh/id_rsa.pub – this will give you the key in the proper format to paste into the control panel.
  • Make sure you backup the ~/.ssh/id_rsa file. This cannot be recovered if it is lost.

Select your SSH key

Following these steps will attach your public key to your new Instance. Then, you will be able to login to SSH using Plain Text password and SSH key both.

select SSH public key

9. Link Web Firewall rule to Server Instance

Firewall
  1. Click on Manage and create a new Firewall Group.
  2. Allow TCP port 22 for SSH. 80 for HTTP and 443 HTTPS for IPV4 and IPV6 rules both.
  3. Once done, link the Firewall group to your Instance.
firewall status
Accept TCP connection from 22, 80, 443 only
Link Firewall Group
Link firewall rule to new instance

10. Enter Hostname and label click Deploy Now

deploy vultr instance

Now, you will see installing in the progress

Instance Installing

15. Go to New Instance page

Copy IP address, username and password. Your default port is 22.

login credentials

16. Disable Password Login

For security reasons, it’s recommended to disable password authentication and allow only key based authentication.

  1. Edit the configuration file nano /etc/ssh/sshd_config
  2. Find (CTRL + W) and search PasswordAuthentication
  3. Change value from yes to no
  4. To save type, CTRL + O
  5. Restart the SSH service using command sudo service ssh restart
disable password auth
Disable Password Authentication

From the next time, you can use SSH via key only as shown in the video.

For Linux or Mac, use Terminal with command like this

ssh root@192.168.1.1 -p 22 -i id_rsa

Step 18. Disable UFW

When you deploy a new instance at VULTR it comes with UFW (Uncomplicated Firewall) enabled that keeps all ports blocked except the SSH port 22. This can return ERR_CONNECTION_REFUSED Error in the browser. To fix this, I would suggest keeping UFW disabled.

ufw disable

Now, I’ll speed up the original process for deploying WordPress on the LEMP stack.

Part C. Deploy WordPress on LAMP Stack

1. Update repositories

Type below command and press enter key

sudo -s
apt update && apt upgrade -y && apt dist-upgrade && apt autoclean && apt autoremove -y && reboot

or

wget -qO update https://dl.gulshankumar.net/update && chmod +x update

Next time, always use below shortcut command to update.

./update

2. Install MariaDB with security

Login again and enter following command

sudo apt install mariadb-server -y && sudo mysql_secure_installation

Answer below questions

  • Enter current password for root (enter for none): Press Enter key
  • Set root password? [Y/n]: Press Enter key.
  • New password: Type your password, you can use Dashlane to generate. Right to click paste.
  • Re-enter new password: Re-type your password.

After successful password set, you will see

Password updated successfully!
Reloading privilege tables..
... Success!

Also, you need answer following questions.

Remove anonymous users? [Y/n]: Press Y and enter
Disallow root login remotely? [Y/n]: Press Y and enter
Remove test database and access to it? [Y/n]: Press Y and enter
Reload privilege tables now? [Y/n]: Press Y and enter

3. Create a new Database for WordPress

Login to MySQL, press enter key when it asks for password.

mysql -u root -p

Create a new Database, and Grant Privileges to use its user with password. This is where WordPress store all post, pages, themes, plugin, etc information.

create database wordpress;
grant all on wordpress.* to gulshan@localhost identified by '5pY8CKJxDRJEGQNkX7';
flush privileges;
exit;

Where your …
database is wordpress
username is gulshan
password is 5pY8CKJxDRJEGQNkX7

Tip: Consider using unique login credential

4. Install PHP 8.1, Apache2 and set Permission

sudo add-apt-repository ppa:ondrej/php -y && apt update && apt install php8.1-fpm php8.1-common php8.1-mysql php8.1-xml php8.1-xmlrpc php8.1-curl php8.1-gd php8.1-imagick php8.1-cli php8.1-dev php8.1-imap php8.1-mbstring php8.1-soap php8.1-zip php8.1-bcmath -y && sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php/8.1/fpm/php.ini && service php8.1-fpm restart && apt install apache2 -y && chown -R www-data:www-data /var/www/ && chmod -R 755 /var/www/

Tweak PHP Configuration

Most fancy theme and plugin requires high-end PHP configuration to run. Therefore, we should make this changes.

sed -i 's/memory_limit = 128M/memory_limit = 512M/g' /etc/php/8.1/fpm/php.ini
sed -i 's/post_max_size = 8M/post_max_size = 128M/g' /etc/php/8.1/fpm/php.ini
sed -i 's/max_file_uploads = 20/max_file_uploads = 30/g' /etc/php/8.1/fpm/php.ini
sed -i 's/max_execution_time = 30/max_execution_time = 900/g' /etc/php/8.1/fpm/php.ini
sed -i 's/max_input_time = 60/max_input_time = 3000/g' /etc/php/8.1/fpm/php.ini
sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 128M/g' /etc/php/8.1/fpm/php.ini
service php8.1-fpm restart

5. Install Wildcard Let’s Encrypt SSL Certificate

Create a cloudflare.ini file inside /root/.secrets/ directory.

mkdir -p /root/.secrets/ && cd /root/.secrets/ && nano cloudflare.ini

Add below code and save using CTRL+O and exit using CTRL+X

dns_cloudflare_email = "your-cloudflare-email@example.com"
dns_cloudflare_api_key = "XXXXXXXXXXXXXXXXX"

Find your Cloudflare e-mail and Global API key at “My Profile” > API Tokens > Global API Key

chmod 0400 /root/.secrets/cloudflare.ini

Install Certbot and DNS Authenticator according to OS and HTTP web server

apt install snapd -y
snap install --beta --classic certbot
snap set certbot trust-plugin-with-root=ok
snap install --beta certbot-dns-cloudflare
snap connect certbot:plugin certbot-dns-cloudflare

Get Wildcard SSL Certificate

certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.secrets/cloudflare.ini -d example.com,*.example.com --preferred-challenges dns-01

Set Automatic Renewal using Cron Job

  • Type crontab -e
  • Type 1 for nano editor
  • Enter below command and save
0 0 * * *  /etc/init.d/apache2 reload >/dev/null 2>&1

Test renewal

certbot renew --dry-run

Activate these useful modules

a2enmod proxy_fcgi ssl http2 expires headers rewrite remoteip
systemctl restart apache2

6. Create App Directory for each WordPress site you want to install

mkdir -p /var/www/example.com/public

This will be your Document Root path in your Apache Configuration file. The reason of creating example.com inside www is to keep each site organized way. Second, I created public directory as well with aim to keep all WordPress core files there but wp-config.php one level up (/var/www/example.com/).

7. Create Apache2 Configuration

This is important where you need configure your domain, how Apache2 should handle your HTTP requests.

Delete default server blocks configuration files of Apache2

rm /etc/apache2/sites-available/000-default.conf
rm /etc/apache2/sites-available/default-ssl.conf
rm /etc/apache2/sites-enabled/000-default.conf
source /etc/apache2/envvars

Now, Create a new server block configuration files. You need to do this step everytime you want to add a new WordPress at same server.

Please replace example.com with own domain and do not forget to end the configuration file name with .conf extension. Otherwise it won’t work.

cd /etc/apache2/sites-available/
nano example.com.conf
  1. Replace example.com with own domain
  2. Enter below code and Press ctrl+o to save and ctrl+x to exit.
##############################################################
#                                                               
# NOTES: Kindly make search and replace of example.com to own domain.  
#                                                                
##############################################################


# We are going to Force HTTPS non-www
# If you want HTTPS www please keep https://www.example.com/ in the last line.
# Or you may face redirect loop issue.

<VirtualHost *:80>
   ServerSignature Off
   ServerName example.com
   ServerAlias www.example.com
   Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
   ServerSignature Off
   ServerName example.com
   ServerAlias www.example.com
   Protocols h2 h2c http/1.1
   DirectoryIndex index.php index.html
    
   # Recommended for Cloudflare users
   # RemoteIPHeader X-Forwarded-For
   
   # Document Root Path (Pay attention to this path to avoid 404)
   DocumentRoot /var/www/example.com/public
   
   # Logs Path is /var/log/apache2/example.com-access.log
   ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
   CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
   
   # Let's Encrypt SSL
   SSLEngine On
   SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
   SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
   
   # Allow use of .htaccess file to override configuration
   <Directory /var/www/example.com/public>
     Options FollowSymLinks
     AllowOverride All
     Require all granted
   </Directory>
   
   # Block PHP execution inside Uploads Directory
   <Directory /var/www/example.com/public/wp-content/uploads>
    <Files *.php>
      deny from all
    </Files>
   </Directory>
   
   # Protect wp-config.php
   <files wp-config.php>
      order allow,deny
      deny from all
   </files>

  # HTTP Auth for additional security
  # If you want HTTP Auth for WordPress Login page then consider uncommenting this block of code.
  # If you do so you must generate .htpasswd file as well.
  # <Files wp-login.php>
  #  AuthName "Admins Only"
  #    AuthUserFile /var/www/.htpasswd
  #   AuthType basic
  #    require user gulshan
  #   <RequireAny>
  #      Require ip 127.0.0.1
  #       Require valid-user
  #   </RequireAny>
  # </Files>
   
   # Block XML-RPC to prevent DDoS Attack. 
   <Files xmlrpc.php>
      Order Deny,Allow
      Deny from all
   </Files>
   
   # Handle PHP execution
   <FilesMatch ".php$">
      SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost/"
   </FilesMatch>
</VirtualHost>

To save, press CTRL+O and Enter key. Then, exit nano editor using command CTRL+X.

To activate server block, enter the command

Before running below command, please replace example.com to own domain.

a2ensite example.com.conf

Test configuration (optional)

apache2 -t

Restart and update

service apache2 restart && service php8.1-fpm restart && service mysql restart && apt-get update && apt upgrade -y

8. Install WordPress files

Download WordPress files in /var/www/html directory and set permission.

cd /var/www/example.com/public/ && wget https://wordpress.org/latest.tar.gz && tar -xvzf latest.tar.gz && mv -v wordpress/* /var/www/example.com/public/ && rm -rf latest.tar.gz wordpress && chown -R www-data:www-data /var/www/example.com/public/ && sudo chmod -R 755 /var/www/example.com/public/

To update permission in future, use below command. This will set www-data for everything inside /var/www/ directory

chown -R www-data:www-data /var/www/example.com/public/ && sudo chmod -R 755 /var/www/example.com/public/

9. Override hosts file [Hardcoding]

If you’re hosting WordPress locally, want to bypass proxy or want to perform zero downtime migration, this step is useful. I generally prefer in case of Static WordPress Dev area. 😉

  • There are two ways to point DNS. If you are migrating site to Vultr and want to test first locally then edit your hosts file and point there.

For Windows

  • Go to properties of ‪‪C:\Windows\System32\drivers\etc\hosts
  • Change “Security” permission to full control for your current Username
  • Now you can freely edit the hosts file under your System user and save it.
# For same machine you can have localhost address else public IP
127.0.0.1 example.com
127.0.0.1 www.example.com

An example, this is how it should look

For Mac or Linux

cd && nano /etc/hosts
  • If everything is perfect and you want to make your site live, Login to Cloudflare DNS and update new IP
A ---------- @ -----------> Server IPV4 address
AAAA ------- @ -----------> Server IPV6 address
CNAME ------www -----------------> example.com

where @ denotes naked domain example.com

9. Visit your domain name to setup WordPress

If you want to keep non-www version domain for your WordPress then visit non-www version else www.

https://example.com
  • Provide Database login credential to begin WordPress Setup
  • Run Installation
  • Fill up Basic details of your new Site and Install WordPress.
  • Login to WordPress

Other neccessary things

  • Increase the Swap Memory to deal with sudden load
swapoff -a
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
sudo cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
  • Make sure to use a single Page Caching plugin to keep server load in control. As this is a LAMP stack, I would recommend you WP Fastest Cache.
  • Always keep backup.
  • Use SMTP plugin Services for sending outgoing email of WordPress otherwise you will not be able to receive password reset link, contact form 7 messages.

Finally, the WordPress installation has been completed.

I greatly appreciate your valuable time in reading this article. See you in the next tutorial!

Want more? 
Imagine getting Tutorials everyday! THAT's FREAKING AWESOME. Subscribe now. 

Leave a Comment