Install WordPress on Ubuntu 22.04 with Nginx, MariaDB, PHP8.1 (LEMP)

This tutorial is going to show you how to install WordPress on Ubuntu 22.04 with Nginx, MariaDB, and PHP8.1 (LEMP Stack). WordPress is the most popular CMS (Content Management System) in the world. It is estimated that more than a third of websites today are powered by WordPress. PHP8.1 is made into the Ubuntu 22.04 repository and the latest version of WordPress runs perfectly with it.

Prerequisites

1. To follow this tutorial, you need an Ubuntu 22.04 OS running on a remote server. If you are looking for a virtual private server (VPS), I recommend Kamatera VPS, which features:

  • 30 days free trial.
  • Starts at $4/month (1GB RAM)
  • High-performance KVM-based VPS
  • 9 data centers around the world, including the United States, Canada, UK, Germany, The Netherlands, Hong Kong, and Isreal.

Follow the tutorial linked below to create your Linux VPS server at Kamatera.

2. You also need a domain name, so visitors can type a domain name in the web browser address bar to access your website. I registered my domain name at NameCheap because the price is low and they give whois privacy protection free for life.

3. This tutorial assumes that you have already set up a LEMP stack on Ubuntu 22.04. If not, please check out the following tutorial.

After finishing LEMP installation, come back here and read on.

Step 1: Download WordPress

SSH into your Ubuntu 22.04 server and update existing software.

sudo apt update && sudo apt upgrade -y

Next, go to wordpress.org download page and download the zip archive. You can acquire the direct download link by right-clicking the download button and select copy link location.

install-wordpress-on-ubuntu-20.04

Then at the command line prompt, type in wget followed by the direct download link to download WordPress to your Ubuntu 22.04 server.

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

Next, extract the zip archive using the command below.

sudo apt install unzip

sudo mkdir -p /usr/share/nginx

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

The archive will be extracted to /usr/share/nginx/ directory. A new directory named wordpress will be created (/usr/share/nginx/wordpress). Now we can rename it like below, so it’s easy for us to identify each directory. Replace example.com with your real domain name.

sudo mv /usr/share/nginx/wordpress /usr/share/nginx/example.com

Step 2: Create a Database and User for WordPress Site

Log into MariaDB console as root with the following command.

sudo mariadb -u root

or

sudo mysql -u root

Once you are logged in, create a database for WordPress using the following command. I named it wordpress, but you can use whatever name you like such as your site name. (Don’t leave out the semicolon.)

create database wordpress;

Then enter the command below to create a database user for WordPress.  Replace wpuser and your-password with your preferred username and password.

create user wpuser@localhost identified by 'your-password';

Grants all privileges of WordPress database to the user.

grant all privileges on wordpress.* to wpuser@localhost;

Flush the privileges table for the changes to take effect and then get out of MariaDB console.

flush privileges;

exit;

Step 3: Configure WordPress

Go to your WordPress directory.

cd /usr/share/nginx/example.com/

Copy the sample configuration file and rename it to wp-config.php.

sudo cp wp-config-sample.php wp-config.php

Now edit the new config file with a command-line text editor like Nano.

sudo nano wp-config.php

Find the following lines and replace the red texts with the database name, username and password you created in the previous step.

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

/** MySQL database username */
define('DB_USER', 'username_here');

/** MySQL database password */
define('DB_PASSWORD', 'password_here');

Then scroll down to find the following line.

$table_prefix = 'wp_';

By default, every WordPress database table name begins with wp_ as the prefix. It’s highly recommended to change it to something else to improve security. Use random characters like below.

$table_prefix = '9OzB3g_';

Save and close the file. To save the file in Nano text editor, press Ctrl+O, then press Enter to confirm. Next, press Ctrl+X to exit.

Because this file contains a password, we run the following command to make sure only the file owner can read this file.

sudo chmod 640 wp-config.php

We also need to set the Nginx user (www-data) as the owner of the WordPress site directory by using the following command.

sudo chown www-data:www-data /usr/share/nginx/example.com/ -R

Step 4: Create an Nginx Server Block for WordPress

We will create the server block file in /etc/nginx/conf.d/ directory. The file name must end with .conf.

sudo nano /etc/nginx/conf.d/example.com.conf

Put the following texts into the file. Replace the red texts with your own domain name. Don’t forget to create A records for your domain name in your DNS manager.

server {
  listen 80;
  listen [::]:80;
  server_name www.example.com example.com;
  root /usr/share/nginx/example.com/;
  index index.php index.html index.htm index.nginx-debian.html;

  error_log /var/log/nginx/wordpress.error;
  access_log /var/log/nginx/wordpress.access;

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

   location ~ ^/wp-json/ {
     rewrite ^/wp-json/(.*?)$ /?rest_route=/$1 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 20M;

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

  location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    include snippets/fastcgi-php.conf;
    fastcgi_buffers 1024 4k;
    fastcgi_buffer_size 128k;
  }

  #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           360d;
  }

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

Save and close the file. Then test Nginx configurations.

sudo nginx -t

If the test is successful, reload Nginx.

sudo systemctl reload nginx

Enter your domain name in the browser address bar.

example.com

or

example.com/wp-admin/install.php

You shall see the WordPress installation wizard. Select a language.

install-wordpress-ubuntu-17.10-lemp

If the installation wizard isn’t displayed, you probably need to install some PHP extensions.

sudo apt install php-imagick php8.1-fpm php8.1-mbstring php8.1-bcmath php8.1-xml php8.1-mysql php8.1-common php8.1-gd php8.1-cli php8.1-curl php8.1-zip

Then reload PHP-FPM and Nginx. The wizard should now be displayed.

sudo systemctl reload php8.1-fpm nginx

Before entering your sensitive information in the setup wizard, it’s recommended to enable HTTPS to prevent traffic hijacking.

Step 5: Enabling HTTPS

To encrypt the HTTP traffic, we can enable HTTPS by installing a free TLS certificate issued from Let’s Encrypt. Run the following command to install Let’s Encrypt client (certbot) on Ubuntu 22.04 server.

sudo apt install certbot python3-certbot-nginx

And run this command to obtain and install TLS certificate.

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

Wher

  • --nginx: Use the Nginx plugin.
  • --agree-tos: Agree to terms of service.
  • --redirect: Force HTTPS by 301 redirect.
  • --hsts: Add the Strict-Transport-Security header to every HTTP response. Forcing the browser to always use TLS for the domain. Defends against SSL/TLS Stripping.
  • --staple-ocsp: Enables OCSP Stapling. A valid OCSP response is stapled to the certificate that the server offers during TLS.
  • --email: Email used for registration and recovery contact.
  • -d flag is followed by a list of domain names, separated by comma. You can add up to 100 domain names.

The certificate should now be obtained and automatically installed.

wordpress apache https

Now if you reload the WordPress setup wizard, you can see that HTTP is automatically redirected to HTTPS connection.

Step 6: Finish the Installation with the Setup Wizard

Create an admin account and click the Install WordPress button.

wordpress ubuntu 20.04 PHP7.4

And now your new WordPress site is installed.

install wordpress ubuntu 20.04 LAMP

How to Redirect www to non-www (Or Vice Versa)

We have already enabled redirecting HTTP to HTTPS, what’s left to do is redirect www to non-www, or vice versa. It’s very easy. Simply go to WordPress Dashboard > Settings > General and set your preferred version (www or non-www) in WordPress Address and Site Address. Be sure to include the https:// prefix.

letsencrypt apache redirect

How to Send Emails in WordPress

Your WordPress site needs to send emails like account registration emails, password-resetting emails, comment notification emails, etc. Instead of using expensive third-party solutions like Gsuite to create professional email addresses for your website, you can follow this iRedMail tutorial to set up your own mail server with your own domain name, so you can have unlimited mailboxes and send unlimited emails without breaking the bank.

Note that it’s a good practice to install the mail server and WordPress on two different virtual private servers because you don’t want the mail server to slow down your WordPress site speed, and the mail server will leak the IP address of your WordPress site if they are on the same virtual private server, which means hackers can bypass any CDN (Content Delivery Network) you are using and launch DDoS attack directly at your origin server.

Once your mail server is up and running, you can install an SMTP plugin in WordPress, so it can connect to your mail server and send emails. Go to your WordPress dashboard -> Plugins, click Add New to install a new plugin.

wordpress add new plugin

Then type in WP Mail SMTP in the search box. Install and activate the WP Mail SMTP by WPForms plugin.

wp mail smtp

Reload the WordPress dashboard web page, you will see WP Mail SMTP on the left menu bar. Click on it and select Settings.

wp mail smtp settings

Then scroll down to the Mailer section. By default, the PHP mailer is selected. We need to change it to Other SMTP.

wordpress send emails

Scroll down and you will need to enter the SMTP settings.

  • Enter the hostname of your mail server.
  • Select TLS as Encryption.
  • Use port 587.
  • Enable Authentication.
  • Enter an email address of your domain and the password.

wordpress set up your own email server

After saving the settings, you can test email sending by logging out the WordPress dashboard, and click lost your password link to send a password-resetting email.

wordpress lost your password

Increase Upload File Size Limit

By default, files such as images, PDF files uploaded to the WordPress media library can not be larger than 2MB. To increase the upload size limit, edit the PHP configuration file.

sudo nano /etc/php/8.1/fpm/php.ini

Find the following line (line 850). In the Nano text editor, you can press Ctrl+/, then enter 850, to jump to line 850.

upload_max_filesize = 2M

Change the value like below:

upload_max_filesize = 20M

Then find the following line (line 694).

post_max_size = 8M

Change the maximum size of POST data that PHP will accept.

post_max_size = 20M

Save and close the file. Alternatively, you can run the following two commands to change the value without manually opening the file.

sudo sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/g' /etc/php/7.4/fpm/php.ini

sudo sed -i 's/post_max_size = 8M/post_max_size = 20M/g' /etc/php/7.4/fpm/php.ini

Then restart PHP-FPM.

sudo systemctl restart php8.1-fpm

Nginx also sets a limit of upload file size. The default maximum upload file size limit set by Nginx is 1MB. To allow uploading large files to your WordPress site, edit the Nginx configuration file.

sudo nano /etc/nginx/conf.d/example.com.conf

We have already set the maximum file size in this file, as indicated by

client_max_body_size 2M;

You can change it if you prefer, like 20M.

client_max_body_size 20M;

Save and close the file. Then reload Nginx for the changes to take effect.

sudo systemctl reload nginx

Next Steps

I hope this tutorial helped you install WordPress on Ubuntu 22.04 with Nginx, MariaDB and PHP8.1 (LEMP stack). As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks.

Backup is important in case of hacking, data center disasters, etc. You should have a backup strategy for your WordPress site.

Linux Server Performance Tuning and Monitoring

WordPress Command Line Utility

Take care 🙂

Rate this tutorial
[Total: 11 Average: 4.8]

19 Responses to “Install WordPress on Ubuntu 22.04 with Nginx, MariaDB, PHP8.1 (LEMP)

  • Deborah
    2 years ago

    I installed LEMP with your tutorial, got an error saying port 80 was in conflict, so I deleted the 80 ports on the server file and it ran ok.

    Although I installed the additional php you recommended, I am still getting ERR_CONNECTION_REFUSED.

    UFW is enabled for NGINX and all ipv6 ports.

    So I am stuck with getting the site/wp-config up…

    Any suggestion? Can you help with getting Nginx logs? I ran [$ ps aux | grep httpd] and next lsof but nothing came up.

    Thanks for the well written tutorials.

  • deborah
    2 years ago

    ok so to clarify…
    After installing LEMP just the way you did, all is good.
    After installing wp, I pulled logs from nginx:

    tail -f /var/log/nginx/error.log

    2022/07/28 20:23:08 [warn] 6146#6146: conflicting server name "_" on [::]:80, ignored
    2022/07/28 20:23:08 [notice] 6146#6146: signal process started
    2022/07/28 20:36:50 [warn] 6239#6239: conflicting server name "_" on 0.0.0.0:80, ignored
    2022/07/28 20:36:50 [warn] 6239#6239: conflicting server name "mydomain.app" on 0.0.0.0:80, i                       gnored
    

    Even after excluding 80 from nginx for wp file, it is still not going.

    I am definitely going to donate for the help!

    • Xiao Guoan (Admin)
      2 years ago

      You should delete the default Nginx virtual host file.

      sudo rm /etc/nginx/sites-enabled/default
      • Deborah
        2 years ago

        Xiao my dear, thanks, I terminated the instance, started over. No success, I opened a call for help on your community and Stack Overflow mentioning your post: https://stackoverflow.com/questions/73160559/wordpress-install-error-failed-to-open-stream

        I’m getting this error:

        #0 /usr/share/nginx/myserver.app/wp-blog-header.php(13): require_once()
        #1 /usr/share/nginx/myserver.app/index.php(17): require('...')
        #2 {main}
          thrown in /usr/share/nginx/myserver.app/wp-load.php on line 50" while reading response header from upstream, client: 209.85.238.***, server: www.myserver.app, request: "GET /robots.txt HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "myserver.app"
        2022/07/29 00:24:00 [error] 28753#28753: *13 FastCGI sent in stderr: "PHP message: PHP Warning:  require_once(/usr/share/nginx/myserver.app/wp-config.php): Failed to open stream: Permission denied in /usr/share/nginx/myserver.app/wp-load.php on line 50PHP message: PHP Fatal error:  Uncaught Error: Failed opening required '/usr/share/nginx/myserver.app/wp-config.php' (include_path='.:/usr/share/php') in /usr/share/nginx/myserver.app/wp-load.php:50
        Stack trace:
        #0 /usr/share/nginx/myserver.app/wp-blog-header.php(13): require_once()
        #1 /usr/share/nginx/myserver.app/index.php(17): require('...')
        #2 {main}
          thrown in /usr/share/nginx/myserver.app/wp-load.php on line 50" while reading response header from upstream, client: 209.85.238.***, server: www.myserver.app, request: "GET /robots.txt HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "myserver.app"
        

        I deleted the default file, enabled ufw granted permissions… will start over one more time…

    • Xiao Guoan (Admin)
      2 years ago

      You need to grant permission to the www-data web server user.

      sudo chown www-data:www-data /usr/share/nginx/myserver.app/ -R
  • deborah
    2 years ago

    and I get the same permission error.

    • Xiao Guoan (Admin)
      2 years ago

      Maybe you need to change the permissions on the wp-config.php file.

      sudo chmod 770 /usr/share/nginx/myserver.app/wp-config.php

      Then reload PHP8.1-FPM and Nginx.

      sudo systemctl reload php8.1-fpm nginx
      • deborah
        2 years ago

        nope.
        do you think It is worth re-install wp using sudo su?

    • Xiao Guoan (Admin)
      2 years ago

      No. Installing WordPress as root will mess up the permission even more.

      Check which user PHP-FPM is running as.

      sudo ps aux | grep 'php-fpm: pool www'
      

      Check which user Nginx is running as.

      sudo ps aux | grep 'nginx: worker process'
      • deborah
        2 years ago

        thank you for being here..
        I am not this instructed in coding, sorry… don’t know what info you want.

    • Xiao Guoan (Admin)
      2 years ago

      This is really strange. PHP-FPM and Nginx both run as the www-data user, and the files under /usr/share/nginx/myserver.app/ are owned by www-data.

      Maybe you should just set the wp-config.php file mode to 776.

      sudo chmod 776 /usr/share/nginx/myserver.app/wp-config.php
  • Another perfect instruction as always!

  • Thank you for an awsume guide. Worked beautifully.

    The only issue I had was editing and saving WordPress widgets and found that it was an issue with the nginx config.

    “There was an error. The response is not a valid JSON response.”

    I removed the following line and it worked.

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

  • Zena Faretra
    2 years ago

    We just felt compelled to say something and let you know how much I appreciated reading your blog. Your content are amazing and have given me fresh perspectives. I will be bookmarking your site to my own list and look forward to reading your future posts. Thank you for putting in the time and keep up the amazing work!

  • Thanks for this.
    I followed up the whole process you did even using the same domain name example.com.

    Now I enter a domain name example.com or example.com/wp-admin/install.php
    it shows me this rather than showing wordpress:
    ” Example Domain
    This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.

    More information… ”

    I tried those php extensions you mentioned.

    Could you help why is that?

  • I followed all of your directions on both installing LEMP and WordPress. Very easy to follow, thank you. I am having a problem when I enter domain.ca I get 404 Forbidden page. When I enter domain.ca/wp-admin I edit wordpress site. What may be preventing just the domain name from receiving the wordpress home page?

  • sudo sed -i ‘s/upload_max_filesize = 2M/upload_max_filesize = 20M/g’ /etc/php/7.4/fpm/php.ini

    sudo sed -i ‘s/post_max_size = 8M/post_max_size = 20M/g’ /etc/php/7.4/fpm/php.ini

    More precisely
    sudo sed -i ‘s/upload_max_filesize = 2M/upload_max_filesize = 20M/g’ /etc/php/8.1/fpm/php.ini

    sudo sed -i ‘s/post_max_size = 8M/post_max_size = 20M/g’ /etc/php/8.1/fpm/php.ini
    not like that?

    Also, the next part is unnecessary, it already appears above
    Nginx also sets a limit of upload file size. The default maximum upload file size limit set by Nginx is 1MB. To allow uploading large files to your WordPress site, edit the Nginx configuration file.

    sudo nano /etc/nginx/conf.d/example.com.conf
    We have already set the maximum file size in this file, as indicated by

    client_max_body_size 2M;
    You can change it if you prefer, like 20M.

    client_max_body_size 20M;
    Save and close the file. Then reload Nginx for the changes to take effect.

    sudo systemctl reload nginx

    And thank you so much for all the great guides

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here