arrow_upward

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Host Your Own WP Blog (Debian 10, Nginx, PHP 8 & MariaDB)
#1
Host Your Own WordPress Blog
Using Debian 10, Nginx, PHP 8 & MariaDB


Hello Post4VPS Community & Staff

Welcome to my tutorial to teach you how to set up your own WordPress blog on a Debian 10 based server using only the command-line and its toolset. You will not need or use a hosting or VPS control panel. The command-line is your friend and key to your own success with Linux. So it is very important to collect command-line experience by doing projects such as those introduced to you in this tutorial. Another personal goal is to get you a bit away from using control panels to manage your server to reduce overhead and remove a big layer of possible security risks and other kinds of issues.

We will cover all necessary steps of the setup, starting with the installation of the Nginx web server, setting up the firewall rules, necessary directory permissions, everything in between, and finally performing the WordPress installation. What we will not cover are the following subjects: DNS and mail server setups. I recommend using a 3rd party DNS infrastructure provider such as Cloudflare or similar providers. For mail servicing, I would also recommend using a free 3rd party service with SMTP options to send emails from within your WordPress blog (e.g. Sendinblue or similar services). Additionally this guide will not contain the setup process of a HTTPS vHost with TLS certificates. Later on a tutorial may follow as an addon for this guide that will cover this topic in combination with Let's Encrypt TLS certificates.

For this tutorial, I'm using a small server with the following specifications:
  • Intel Pentium N4200 4x 2.4 GHz
  • 4 GB DDR4 2400 MHz RAM
  • 64 GB eMMC Flash Storage
  • Debian "Buster" 10 64 Bit

In short: I will be using a home server that is actually an old repurposed Acer Swift One Ultrabook. I will be hosting the setup locally however with a proper domain name. Regardless of this fact, everything shown in this guide will still work on dedicated servers and VPSs with public IP addresses. You can look at my setup for this guide as a computer & server testing laboratory. Made to produce educational content such as this tutorial.

Let's get started!



Before we really begin I'd like to mention some prerequisites and provide some information about upcoming procedures.

Clean OS
- It is highly recommended to use a clean OS installation for this project. A already in use OS installation where you might have certain software installed that might be similar to what we want to set up or something else is running on can produce conflicts and thus cause negative side effects. So it's best to reinstall your OS to a fresh installation of Debian 10 before starting with this tutorial.

Up to date OS
- Please make sure your OS installation is not only fresh but also up to date. This is also a highly recommended step that needs to be performed before going forward with the installation steps in this guide. Out-of-date software combined with what we want to do can cause unwanted and unnecessary issues.

Root access
- It is highly recommended to be logged in as root on your server to perform all upcoming installation setups and commands. You will save yourself a lot of time this way. Alternatively, you can use a user with sudo access but remember to apply the sudo keyword before all commands.

3rd party repos
- For the best experience we want to use the latest available version of the software that we need to achieve our goal. Sadly, the default software repositories of Linux distributions like CentOS, Debian, or Ubuntu don't provide the latest version of the software we need in their default repositories. To get past this problem we will be adding 3rd party software repositories that will allow us to get the latest version of the software we need.

Going a nit off road
- We're not going to stick with all software defaults of software packages. We will change configurations of the software we install and we will write our own configurations from scratch where and when necessary.

Make sure you have all of that ready and are properly prepared.



First, we will be adding 3rd party repositories for the latest Nginx Stable, PHP 8, and MariaDB versions.

Run the commands below to create new source lists for the three application sets.

Nginx Stable (directly from nginx.org)
apt-get update
apt-get install curl gnupg2 ca-certificates lsb-release -y
echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | tee /etc/apt/preferences.d/99nginx
curl -o /etc/apt/trusted.gpg.d/nginx_signing.asc https://nginx.org/keys/nginx_signing.key
apt-get update

PHP 8 (from deb.sury.org)
apt-get install wget apt-transport-https software-properties-common dirmngr -y
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/sury-php.list
wget -qO - https://packages.sury.org/php/apt.gpg | apt-key add -
apt-get update

MariaDB 10.5 (directly from MariaDB Foundation)
apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
add-apt-repository 'deb [arch=amd64] http://mirror.23media.de/mariadb/repo/10.5/debian buster main'
apt-get update
(In my case I'm using a German mirror. You can generate a source list for MariaDB 10.5 with a different mirror here.)

Finally, there are a few packages that can be updated and others that can be deleted (as they're no longer required). Run the command below to make sure everything is up to date:
apt-get upgrade -y
apt-get dist-upgrade -y
apt-get --purge autoremove -y

After adding these 3rd party repositories we can continue with the installation of all software packages that we need.



Nginx Stable

Let's start by installing, enabling, and starting the Nginx web server. Run the commands below:
apt-get install nginx -y
systemctl enable nginx
systemctl start nginx


PHP 8.0 + Extensions

Now it's time to install PHP 8.0 and the necessary extensions. One important being the PHP FPM extension. Which we will enable as a service and start after the installation. Execute the commands below on your server:
apt-get install php8.0 php8.0-bcmath php8.0-mysql php8.0-tidy php8.0-dba php8.0-readline php8.0-bz2 php8.0-xdebug php8.0-xml php8.0-enchant php8.0-opcache php8.0-intl php8.0-soap php8.0-xsl php8.0-cli php8.0-fpm php8.0-zip php8.0-sqlite3 php8.0-common php8.0-gd php8.0-phpdbg php8.0-mbstring php8.0-sybase php8.0-curl php8.0-gmp php8.0-pspell -y
systemctl enable php8.0-fpm
systemctl start php8.0-fpm


MariaDB 10.5

After PHP 8.0 has been installed we can install the MariaDB 10.5 MySQL database server. After that, we will enable and start it. Run the commands below in your terminal:
apt-get install mariadb-server -y
systemctl enable mariadb
systemctl start mariadb

Now we have everything necessary installed and can continue with the configuration of the applications, set up things like firewall rules and directory permissions.



Firewall rules for the web server

By default Debian 10 comes neither with firewalld nor with any other easier-to-use firewall or iptables frontend. Only the raw iptables firewall is available. However, to makes things much easier for the future we will install the iptables frontend ufw (uncomplicated firewall).

To install ufw run the commands below:
apt-get install ufw -y

If you have IPv6 addresses available you may want to enable IPv6 support.
nano /etc/default/ufw

Make sure you have the entry "IPV6=yes" inside the file and it is not commented.

Now we have to configure the default policies. The best security practice is to block everything that we didn't explicitly allow. So our default policy for incoming connections will be set to "deny". However, we will allow all outgoing connections as it can be very hard and painful to filter outgoing connections properly. Outgoing connections can happen basically any port to any port (1 to 65535). It depends a lot on what kind of server or service the outgoing connection is connecting to. So for the outgoing connections, we will set the default policy to "allow".

Run the commands below to set default policies:
ufw default deny incoming
ufw default allow outgoing

Don't worry. You will not be disconnected! After running the commands above ufw is actually still inactive.

Next, it is time to open the incoming ports that we need. We'll be simply starting with the SSH port (I use port 22 still as SSH is only accessible over LAN - remember to adjust your SSH port in the command below), port 80 for HTTP, and port 443 for HTTPS. Run the commands below:
ufw allow 22
ufw allow 80
ufw allow 443

Now we will enable ufw and from here on the rules will be active. If you set up the wrong port for SSH you will be locked out after running the command below! For this kind of case make sure you have some kind of emergency access. I highly recommend being careful when configuring the allowed incoming connections to avoid locking yourself out.

Enable ufw:
ufw enable

If asked whether you wish to continue press the Y button and the ENTER button. Ufw is now enabled.

Please read https://www.digitalocean.com/community/t...d-commands for more information about ufw and the most necessary basics and commands.


What you can do now to confirm that the firewall is working properly is to access the IP or domain of your server. You should see an Nginx page showing up like in the screenshot below. And obviously, if your SSH connection is still working the firewall rules for it are correct Wink.

[Image: fFWcFHE.png]

By the way: during the whole tutorial I will be using hiddenrefuge.eu.org as my domain in all configurations, etc. Keep in mind to replace this domain with your own domain where you see it. This means especially the part where we will configure our Nginx vHost, the WordPress blog, etc.



Nginx default vHost configuration

We will not touch the default nginx.conf file in /etc/nginx/ as it is fine as it is by default. The way the file is configured by default in the Nginx.org packages is enough to run pretty much any website for the beginning.

What we will modify is the default vHost "default.conf" to disconnect all connections that attempt to connect to the IP address or domain name that has no vHost on the server.

Rename the original default.conf file to a backup:
mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak

Open a new and empty default.conf:
nano /etc/nginx/conf.d/default.conf

Paste the following into the file:
server {
        listen 80 default_server;
        return 444;
}

Use the CTRL + O button to save the changes and after that use CTRL + X to exit nano.

Restart Nginx to apply the changes:
systemctl restart nginx

If you now access the IP address or domain of your server you will see a browser error message like this one:
[Image: 2015-02-09-12-13-38-59e3c7.png]
(In the case of Firefox, as it is the web browser I currently use.)

If you see such a page or a similar in another browser you now know that the default.conf vHost is working as intended. All connections to the IP address directly or a domain that has no vHost on the webserver are canceled by the webserver to prevent host spoofing.



Nginx vHost configuration for your own domain

Now that we have configured the default vHost we can continue with setting up the real vHost for our own domain of the WordPress blog we want to host.

Create an empty vHost file for your site:
nano /etc/nginx/conf.d/hiddenrefuge.eu.org.conf
(Remember to adjust the domain in the vHost file name.)

Paste the following code into the file:
server {
        listen 80;
        server_name hiddenrefuge.eu.org www.hiddenrefuge.eu.org;

        root /var/www/hiddenrefuge.eu.org;

        index index.html index.htm index.php home.html home.htm home.php;

        location / {
                try_files $uri $uri/ /index.php?$args;
        }

        location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.0-fpm.sock;
        include         fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
  }
}
(Again remember to adjust the domain name to the one you use where needed.)

Use the CTRL + O button to save the changes and after that use CTRL + X to exit nano.

In this guide, I will use /var/www/hiddenrefuge.eu.org as the directory for my WordPress blog. So now it is necessary to create that folder and give it the correct permissions.

Create the folder tree:
mkdir -p /var/www/hiddenrefuge.eu.org
(Adjust your domain!)

Set the correct ownership of the folder:
chown -R nginx:nginx /var/www
(The Nginx web server is running as the user and group "nginx".)

Restart Nginx to apply the new vHost configuration:
systemctl restart nginx

Now you have a vHost for your domain that is pointed to the IP address of your server. If you now open the domain you pointed to your server you should see a 403 Forbidden error. Why 403? Because we don't have an index file, yet. By default, Nginx disables the listing directories and so it returns a 403 Forbidden error. However, this means that the vHost is working. If it wouldn't be working you still would get the error from the default vHost configuration or another error/issue.

[Image: O6G3R7V.png]


Fixing PHP to prevent malicious requests to PHP via PHP-FPM

Quote:When pairing NGINX with PHP-FPM, it’s possible to return to NGINX a .php URI that does not actually exist within the site’s directory structure. The PHP processor will process the URI, and execute the .php file because its job is to process anything handed to it by NGINX. This presents a security problem.

It’s important to limit what NGINX passes to PHP-FPM so malicious scripts can’t be injected into return streams to the server. Instead, the request is stopped, possibly then resulting in a 404.

Run the following command:
sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php/8.0/fpm/php.ini

Restart PHP-FPM:
systemctl restart php8.0-fpm

That security risk should be fixed now.



Fix PHP-FPM pool listen user and group

The Nginx web server is running as the user Nginx and the group Nginx. Meanwhile, the default PHP-FPM pool www is using the user and group www-data. This is a conflict that will prevent from PHP 8.0 working with Nginx. This needs to be fixed.

Open the default PHP-FPM pool www config file to edit it:
nano /etc/php/8.0/fpm/pool.d/www.conf

Find the following lines:
user = www-data
group = www-data
listen.owner = www-data
listen.group = www-data

Replace them with:
user = nginx
group = nginx
listen.owner = nginx
listen.group = nginx

Use the CTRL + O button to save the changes and after that use CTRL + X to exit nano.

Restart PHP-FPM to apply the changes:
systemctl restart php8.0-fpm

Now the PHP-FPM process will be running under the same user as Nginx and Nginx can properly access the listen socket of PHP-FPM to process PHP files from the webserver to PHP and vice-versa.


Verification of PHP 8.0 working with Nginx

The next step before going forward with MariaDB is to confirm that PHP 8.0 is actually working properly with Nginx.

Create an empty info.php file in the directory of your website:
nano /var/www/hiddenrefuge.eu.org/info.php

Paste the following PHP code into the file:
<?php
phpinfo();
?>

Use the CTRL + O button to save the changes and after that use CTRL + X to exit nano.

Open the file in your browser and you should see the PHP 8.0 info page like in the screenshot below.

[Image: 8r7nINK.png]

If you see this page and not an error page you now know that PHP 8.0 is working properly together with the Nginx webserver.

You can remove the info.php file as it is no longer needed.


Setting up MariaDB

How far are we? Great news! We have so far installed and configured the Nginx web server successfully. We've fixed up PHP 8.0 and made it work together with Nginx (with a small and easy verification).

Next goal: MariaDB 10.5 MySQL database server.

The first step is to perform a secure configuration of the MariaDB MySQL database server by setting a root password, etc.

Run the command below to start the secure configuration:
mysql_secure_installation

By default, there is no root password set. So simply press the ENTER key to continue.

Next, you will be asked if you want to switch to unix_socket authentication. Press the N key and the ENTER key. While this might be more secure not every application you might want to host will support Unix socket authentication.

Now you will be asked to change the root password. Press the Y key and the ENTER key. Type in the new password twice.

After that, press the Y key and the ENTER key when asked to disable anonymous user access.

Next, you will be asked to disable root login. Press the Y key and the ENTER key. This will allow root login only via localhost in the CLI.

After that, you will be asked if you wish to remove the test database. Press the Y key and the ENTER key.

Finally, when asked to reload the privileges tables press the Y key and the ENTER key.

The secure setup of MariaDB is finished after this set of steps.

Here is how the whole output of the configuration screen should look like:
Quote:root@hiddenrefuge:~# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!

To log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorization.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] n
... skipping.

You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n] Y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] Y
... Success!

Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess the root password from the network.

Disallow root login remotely? [Y/n] Y
... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access. This is also intended only for testing and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] Y
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] Y
... Success!

Cleaning up...

All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!


Creating a MySQL user and database for the WordPress blog

Time to create a new MySQL user and database for the WordPress blog that we will host. We will not use the MySQL root account and we cannot. It is bad security practice to use the MySQL root account for web applications or other database use cases. In the new MySQL / MariaDB version it is impossible to use root any other way than via the localhost CLI MySQL tool.

Start the CLI MySQL tool:
mysql -u root -p

Type in the password you have set before during the MariaDB secure setup.

You will be in the MariaDB CLI interace that looks like this:
[Image: Vo3S9Oc.png]

Create a new database for the Wordpress blog:
CREATE DATABASE hiddenblog;
(I will be using the database name hiddenblog. Remember to adjust yours!)

Now, create a new user:
CREATE USER 'hiddenuser'@'localhost' IDENTIFIED BY 'mypassword123';
(I will be using the username hiddenuser. Remember to adjust yours! Also don't forget to set the password.)

After that, it is time to give the user full permission for the database:
GRANT ALL ON hiddenblog.* TO 'hiddenuser'@'localhost';

Finally, reload the privileges:
FLUSH PRIVILEGES;

Exit the MySQL CLI tool.
exit

So now we have an empty database and a user assigned to it that we can use in the WordPress installation.



WordPress blog installation

Finally! We can start with the installation of the WordPress blog Smile .

Change into the directory of your site:
cd /var/www/hiddenrefuge.eu.org/

Download the latest WordPress version:
wget https://wordpress.org/latest.tar.gz

Extract the downloaded archive:
tar -xvf latest.tar.gz

Move the WordPress files into your main directory:
mv /var/www/hiddenrefuge.eu.org/wordpress/* /var/www/hiddenrefuge.eu.org

Remove the downloaded archive and the empty wordpress folder:
rm -rf /var/www/hiddenrefuge.eu.org/wordpress
rm -rf /var/www/hiddenrefuge.eu.org/latest.tar.gz

Set ownership for the files and folders correctly:
chown -R nginx:nginx /var/www/

Now, open your domain in the web browser and you should see the WordPress installer.

At the first screen select the language you want to use. In my case English. After that press on the blue "Continue" button.

After that, you will see a info screen showing what is coming up next in terms of configuration. Here you will need the database name, username and password that we created before. First click on the "Let's go!" button.

On the next screen type in the database name, username and password. You can keep the database host and table prefix as is. After you have filled out the necessary fields click on the "Submit" button.

Now, you will see a screen saying that everything looks sparky (good) and you can click on the "Run the installation" button to perform the installation.

Shortly after, you will be at the first configuration screen where you can set the title of your blog, a username and password for the main account and e-mail. Fill in everything as you wish. At the end press the "Install Wordpress" button.

A few seconds later you will be the last screen of the installation. It should say Success!. From here on your blog is installed. You can log into he Admin CP and continue the configuration and add content.

[Image: 5126of4.png]

[Image: bo4iR4N.png]

FYI: WordPress permalinks are already working as the vHost that we created for our site contains the necessary pieces of code to make them work.

That's it. You now have a Nginx web server running with PHP 8.0 and the MariaDB MySQL database server. All of that is hosting your very own WordPress blog. You've not used a single control panel during the whole process.

This might seem like a lot of work? 75% of the content from this thread can be compiled into a single bash shell script that will perform a lot of the steps automatically without any user input. After that you would only have to setup your own vHost, create a database with a user and install your WordPress blog. Again using no control panel.


Revision: 2021-05-19
[Image: zHHqO5Q.png]


Messages In This Thread


person_pin_circle Users browsing this thread: 1 Guest(s)
Sponsors: VirMach - Host4Fun - CubeData - Evolution-Host - HostDare - Hyper Expert - Shadow Hosting - Bladenode - Hostlease - RackNerd - ReadyDedis - Limitless Hosting