Installing WordPress with Nginx, MariaDB, and PHP7.4 (LEMP Stack) on Debian – Building a WordPress Blog Part 2

If you’ve read my previous post and followed along, you should have a working LEMP stack. You’re probably thinking to yourself, now what? Well, today I’ll be showing you what I did with mine, which is installing WordPress. WordPress is an extremely popular CMS (Content Management System) that many of your favorite websites are based off of. Hell, even this arguably kinda crappy blog uses WordPress. A CMS allows someone to easily build websites of various types without needing any sort of programming knowledge.

Prerequisites

If you’re going to follow along, the prerequisites are basically identical to my previous post:

  • An up to date Debian 11 install that has a LEMP stack installed, and you have full root access to. Regardless of your hardware/software, you’ll want at least 512MB of free RAM. You’ll also want to use something like SSH so you can copy and paste commands.
  • Some Linux command line experience.
  • I’m going to assume that you’ll want to put your WordPress instance on the internet for people to visit, so you’ll also need access to whatever firewalls your server is behind, and information like your public IP address. You’ll also want a domain name (Unless if you want to make your visitors remember an IP address for whatever reason).

Like I said in my previous post, I would recommend using a VPS (Virtual Private Server) as opposed to opening up a server at your home to the internet. If you’re looking for a VPS, there’s many good and cheap options, but I personally use Vultr (Referral plug because why not?). There’s a lot of security risks involved with exposing parts of your network to the internet, especially if your server isn’t properly patched, or if you misconfigure your firewalls. You also might run into roadblocks with stuff like CGNAT (Carrier Grade NAT) or your ISP blocking ports, which makes it difficult or impossible to port forward. Plus if you have crappy internet, it can make a pretty poor experience for your visitors.

Downloading WordPress

There’s a few different ways of downloading WordPress to your server, but I prefer using the command line since it’s more convenient in my opinion.

First, install wget and unzip:

sudo apt install wget unzip

Download the WordPress zip file:

wget https://wordpress.org/latest.zip

Unzip the file to /usr/share/nginx:

sudo unzip latest.zip -d /usr/share/nginx

And finally, change the owner of /usr/share/nginx/wordpress to the Nginx user (Don’t be like me and forget this step then wonder why doing anything gives me access denied errors):

sudo chown -R www-data:www-data /usr/share/nginx/wordpress

Don’t forget to remove the downloaded ZIP file so it doesn’t take up space on your server:

rm latest.zip

Connecting WordPress to MariaDB

You’ll need to create a dedicated database and database user for WordPress. Since I’m not familiar with MySQL commands, I’ll show you how to do it through phpMyAdmin.

Once you’ve logged in as a root user, click the New button in the left side bar:

Enter a database name, and then click Create:

Click the phpMyAdmin logo in the top left corner to return to the main screen, then select the User accounts tab:

Under new, click Add user account:

Enter a username and password, and click Go on the bottom right side of the page. Make sure to take note of this information since you’ll need this for creating wp-config.php:

After the user has been created, select the Database tab, and under Database-specific privileges, enter the name of the database that you’ve created (The name of mine is wordpress), then click Go:

Select the Check all checkbox next to Database-specific privileges, then click go:

After that, you should now have a MariaDB database and user for WordPress, and you can also modify WordPress’s databases directly by logging into the WordPress user (This has saved me a few times when I’ve changed the wrong setting and locked myself out).

Creating and Editing wp-config.php

Now that you’ve set up a MariaDB database and user for WordPress, it’s now time to make WordPress use them. Navigate to /usr/share/nginx/wordpress and rename wp-config-sample.php to wp-config.php.

Navigate to the following lines (Starting line 22), and replace the database name, username, and password with the one’s that you’ve just created:

/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );

/** Database username */
define( 'DB_USER', 'username_here' );

/** Database password */
define( 'DB_PASSWORD', 'password_here' );

There are many other options in this file, but these should be the only changes that you need to make.

Creating an Nginx Server Block

Save the below server block in /etc/nginx/conf.d as wordpress.conf. This also happens to be the same server block that I use. For testing purposes, use your servers IP address for server_name, but you’ll be changing it to your domain name later:

server {
  listen 80;
# You can safely remove the below line if your server doesn't support IPv6
  listen [::]:80;
  server_name 12.34.56.78;
  root /usr/share/nginx/wordpress/;
  index index.php index.html index.htm index.nginx-debian.html;

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

   location ~ ^/wp-json/ {
     rewrite ^/wp-json/(.*?)$ /?rest_route=/\ last;
   }

  location ~* /wp-sitemap.*\.xml {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  error_page 404 /404.html;
  error_page 500 502 503 504 /50x.html;

  client_max_body_size 999G;

  location = /50x.html {
    root /usr/share/nginx/html;
  }

  location ~ \.php$ {
    fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    include snippets/fastcgi-php.conf;

    # Add headers to serve security related headers
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header X-Frame-Options "SAMEORIGIN";
  }

  #enable gzip compression
  gzip on;
  gzip_vary on;
  gzip_min_length 1000;
  gzip_comp_level 5;
  gzip_types application/json text/css application/x-javascript application/javascript image/svg+xml;
  gzip_proxied any;

  # A long browser cache lifetime can speed up repeat visits to your page
  location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
       access_log        off;
       log_not_found     off;
       expires           30d;
  }

  # disable access to hidden files
  location ~ /\.ht {
      access_log off;
      log_not_found off;
      deny all;
  }

}

Once you’ve created the file, run the following command to test it:

sudo nginx -t

If there’s no errors, restart nginx so it can pick up the new server block:

sudo systemctl restart nginx

Change Max Upload Size

Since the max upload size by default is only 2MB, chances are you’ll want to increase it. Open /etc/php/7.4/fpm/php.ini in a text editor.

Scroll down to line 694, and change it to something larger. I personally have mine set to 999G so I don’t have to worry about any sort of limits, but if you’re going to allow users to upload content, you probably want to change it to something smaller:

post_max_size = 8M

Scroll down to line 846, and change it to something bigger. I also have this set to 999G, but like I said, you might want to keep it smaller if you’re allowing users to upload content:

upload_max_filesize = 2M

After you’re done making your changes, restart PHP:

sudo systemctl restart php7.4-fpm

Basic WordPress setup

I don’t plan on going into detail, but I’ll be showing the basics. Navigate to your servers IP address, and you should be redirected to the WordPress setup screen.

Getting an Nginx Welcome Screen

A problem that you might run into (At least one that I’ve run into a few times) is getting the Nginx welcome screen instead of being redirected to the WordPress install like in the screenshot. As a temporary workaround to get WordPress installed, you might be able to navigate to your_ip_address/wp-admin/install.php just to get WordPress installed, but you’ll still get the Nginx welcome screen if you just go to your servers IP address without a path:

First, try just simply rebooting your server. Rebooting my server has fixed this issue after I’ve determined that everything was setup correctly.

Next, check /etc/nginx/conf.d to see if there’s any server blocks that you don’t need, or one’s that are also using port 80. Remove any unneeded server blocks or change the ports that they’re using then run sudo systemctl restart nginx. You can also remove the welcome page from /usr/share/nginx/html to see what happens.

Lastly, check the logs for PHP and Nginx by running sudo systemctl status nginx and sudo systemctl status php7.4-fpm, or by checking their log files in /var/log. Usually they’ll tell you if something weird is going on.

After running through these steps, I would recommend rebooting your server again to ensure that everything has been restarted.

Once you’ve gotten to the WordPress install screen, select your language, and click Continue:

Enter a website name, username, password, and email address. I would also recommend checking the box to discourage search engines from indexing your website, then unchecking it once you’re ready to launch it. Click Install WordPress:

Once WordPress has been installed (Which should happen very quickly), click Log In to be redirected to the login page, then login using the login information that you entered during the install process:

Updating and Configuring WordPress

Before using WordPress, I would recommend installing updates. Under Dashboard in the left side bar, click Updates:

Depending on how long ago you download WordPress, there might be a few updates. But for me I only needed to update one plugin. Click the checkbox next to Select All, and then click update (Do this for themes as well if there’s updates available):

I would also recommend switching to security updates only for better stability, and also so your WordPress install doesn’t decide to randomly update to a new major version and cause a mess (cough Windows cough):

DNS and HTTPS

Just as a disclaimer, in this section my knowledge and experience is a little thin in some spots, so some stuff may not be explained all that well or correctly, but I’m open to feedback in the comments.

If you’ve made it this far, then congratulations! You’ve got yourself a mostly working WordPress install. However, it’s not all that secure because there’s no HTTPS, and you probably have a domain name that you want to use. Before doing this, make sure that your server is accessible to the internet by opening the necessary ports (80 and 443) on your firewalls, and also port forward if needed. I highly recommended doing some trial and error to ensure that your server is accessible while being secure, and I’ll be covering security in more detail in a future post. If you’re behind Cloudflare, you only need to open those ports to Cloudflare’s IP ranges once everything is set up.

First, select settings in the left side bar, and change WordPress Address and Site Address to https://your_domain__name.com like in the screenshot:

Just note that once you click Save Changes at the bottom of the screen, you will be locked out of your site because WordPress will only allow you to access your site from your domain name, and since you don’t have that set up yet, your site isn’t accessible. If you do need to change the URLs back for whatever reason, log into MariaDB with your WordPress user, open the WordPress database, open the wp_options table, and change siteurl and home to the previous values. You can also do this through phpMyAdmin.

DNS Records

The first thing that you’ll want to do is create a DNS record for your web server. This will vary depending on the domain registrar, so check their documentation before proceeding. You’ll most likely need an A DNS record for your server, a CNAME record so if someone types in www.your_domain.com, it will resolve to your_domain.com, and a AAAA record if your server supports IPv6. Here’s what my records look like in Cloudflare for example:

In case you couldn’t tell, the IP address is fake

If your server is proxied behind Cloudflare like mine is, you don’t need an AAAA record. This is because your domain will resolve to Cloudflare’s IP addresses instead, and Cloudflare will forward the requests to your server.

It may take a while for your DNS records to propagate, so don’t panic if your browser fails to resolve your domain and nslookup or dig don’t return anything. I recommend waiting a few hours and turning the TTL down, then turning it back up once your domain resolves.

HTTPS

Once your DNS records have propagated and your domain name resolves, it’s now time to set up HTTPS. If you try visiting your website now, you’ll probably get a different error. This is because even though WordPress is listening for HTTPS visitors and you typed https into your browser, your server doesn’t have a certificate installed, and Nginx isn’t listening on port 443.

First, open /etc/nginx/conf.d/wordpress.conf in a text editor, go to that same server_name line from earlier, and and change it to the following (Replacing example.com with your actual domain name):

server_name example.com www.example.com;

Next, test the configuration file:

sudo nginx -t

And finally, restart Nginx:

sudo systemctl restart nginx

To generate an HTTPS certificate, first you’ll install Certbot:

sudo apt install certbot python3-certbot-nginx

Next, generate a certificate by running the following command, replacing the example domains with yours, and the email address that you used to register the domains:

sudo certbot --agree-tos --nginx --redirect --hsts --staple-oscp --email [email protected] -d example.com,www.example.com

And finally, now your website should hopefully be accessible. If it is, then that means I wrote this section correctly (And you correctly followed the instructions). You might need to restart your server or Nginx before your website is accessible over HTTPS.

If you followed this post correctly (And I didn’t screw anything up), then congratulations! You should now have a fully working WordPress website that’s ready for you to start building. In a couple of upcoming posts, I’ll be going over my personal choices for WordPress plugins, and also how to take advantage of Cloudflare’s features and Fail2ban with WordPress. Feel free to leave a comment if you have any problems or suggestions, and I’ll try my best to help.

Part 3: My Top Picks for WordPress Plugins (Comments, Security, Email) – Building a WordPress Blog Part 3

References

Most of the content in this post is from my own knowledge or experience, but I did still reference some documentation and tutorials. These are the only ones that I can think of off of the top of my head.

WordPress’s Documentation

LinuxBabe’s Tutorial

Subscribe
Notify of

2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Dex
December 10, 2022 2:23 pm

When the imposter is sus