Root-Server Tutorial


Installing WordPress on a LEMP Stack

Learn how to install WordPress on a Linux, Nginx, MariaDB, and PHP stack.


Sebastian Huskynarr Selinger

Last updated:



Welcome to this tutorial on optimizing and installing WordPress on a LEMP stack. LEMP stands for Linux, Nginx, MariaDB, and PHP, and it's a powerful combination that can help you run WordPress faster and more efficiently.

In this tutorial, we'll cover the steps required to set up a LEMP stack on your server, install and configure WordPress, and optimize its performance using various tools and techniques. Whether you're a beginner or an experienced user, you'll find valuable information that can help you improve the speed, security, and stability of your WordPress instance.

So, let's get started and learn how to install and optimize WordPress on a LEMP stack!


To install and optimize WordPress on a LEMP stack, you'll need to make sure your system meets the following requirements:

  • Debian-based operating system

By meeting these requirements, you'll be able to successfully install and optimize WordPress on a LEMP stack.

Step 1 - Ordering the VPS

At the time of the creation of this tutorial (April 2023), the recommended product to use is the RS 1000 G9.5 a1 12M. Alternatively, a VPS product can be used. Existing customers can add the product easily and quickly.

Step 2 - Basic configuration of the server

After you have undergone the provisioning of the server and successfully logged in for the first time with the username root and the password sent to you by email, the first step is to update the basic configuration of the server.

  1. Change the root password by means of passwd.
  2. Import the current security updates with apt-get update && apt-get upgrade -y.
  3. It is recommended to set up an SSH key at this point and to disallow password login for the root user. These procedures are not part of this tutorial and as the latter functionality requires root capability, the setup of an unprivileged user is omitted at this point.

Step 3 - Installation of LEMP

Install Nginx:

  • Update the package index: sudo apt update
  • Install Nginx: sudo apt install nginx
  • Start Nginx: sudo systemctl start nginx
  • Enable Nginx to start at boot: sudo systemctl enable nginx

Install MariaDB:

  • Install MariaDB: sudo apt install mariadb-server
  • Start MariaDB: sudo systemctl start mariadb
  • Secure your MariaDB installation: sudo mariadb_secure_installation
  • Follow the prompts to set up a root password and secure your installation.

Install PHP:

  • Install PHP and necessary modules: sudo apt install php-fpm php-mariadb
  • Configure PHP-FPM to work with Nginx:
    • Open the PHP-FPM pool configuration file: sudo nano /etc/php/8.2/fpm/pool.d/www.conf
    • Uncomment the following lines:

      listen.owner = www-data = www-data
      listen.mode = 0660
    • Save and close the file.
  • Restart PHP-FPM: sudo systemctl restart php8.2-fpm

Note that the specific commands and version numbers may vary depending on your Linux distribution and version. Also, be sure to follow best practices for securing your server and applications.

Step 4 - Installing WordPress

Download WordPress:

  • Download WordPress from the official download page: wget
  • Extract the downloaded file to the '/var/www/html' directory: sudo tar -zxvf ~/Downloads/latest.tar.gz -C /var/www/html
  • Create a MariaDB database and user for WordPress:
    • Log in to the MariaDB shell: sudo mariadb
    • Create a new database: CREATE DATABASE wordpress;
    • Create a new user and grant privileges to the new database:

      CREATE USER 'wordpressuser'@'localhost' IDENTIFIED WITH mariadb_native_password BY 'password';

    GRANT ALL ON wordpress.* TO 'wordpressuser'@'localhost'; FLUSH PRIVILEGES;
  • Configure WordPress:
    • Rename the wp-config-sample.php file to wp-config.php: sudo mv /var/www/html/wp-config-sample.php /var/www/html/wp-config.php
    • Open the wp-config.php file in your favorite text editor: sudo nano /var/www/html/wp-config.php
    • Modify the following lines to include your database name, username, and password:

      define( 'DB_NAME', 'wordpress' );

define( 'DB_USER', 'wordpressuser' ); define( 'DB_PASSWORD', 'password' );

  • Save and close the file.
  • Set permissions:
    • Set the owner and group of the WordPress files to www-data: sudo chown -R www-data:www-data /var/www/html
    • Set the appropriate permissions for the WordPress files and directories: sudo find /var/www/html/ -type f -exec chmod 644 {} \; and sudo find /var/www/html/ -type d -exec chmod 755 {} \;
  • Complete the WordPress installation:
  • Open your web browser and navigate to your server's IP address (you should be able to find your server's IP address in the SCP under Network): http://server_ip_address
  • Follow the WordPress installation wizard to complete the installation.
  • Once the installation is complete, you can log in to the WordPress admin dashboard by going to 'http://server_ip_address/wp-admin/' and entering your login credentials.
  • That's it! You now have WordPress installed and configured on your LEMP stack.

Step 5 - Optimize LEMP

Optimize Nginx

Configure Nginx to use caching, which can significantly reduce the number of requests to PHP and the database. And use the gzip module to compress responses before sending them to clients.

Use the fastcgi_cache module to cache PHP responses.

  • Open your Nginx configuration file, which is usually located at /etc/nginx/nginx.conf or /etc/nginx/conf.d/default.conf.
  • Add the following code inside your server block in the Nginx configuration file:

    fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;

fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_valid 200 60m; fastcgi_cache_bypass $http_pragma; fastcgi_cache_revalidate $http_cache_control; fastcgi_cache_min_uses 1; fastcgi_cache_use_stale error timeout invalid_header http_500;

  • Replace /var/cache/nginx with the path where you want to store your cache files.
  • Save and close the file.

Use cache-control:

  • Add the following code inside your location block in the Nginx configuration file:

    expires 1d;

add_header Cache-Control "public, max-age=86400, immutable";

  • expires sets the expiration time for the cache in seconds. In this example, it is set to one day.
  • Cache-Control sets additional cache-control headers. In this example, it is set to cache the response for one day and make it immutable.
  • Save and close the file.
  • Run the command sudo service nginx reload to reload Nginx with the new configuration.

Activate gzip compression

  • Open your Nginx configuration file, which is usually located at /etc/nginx/nginx.conf or /etc/nginx/conf.d/default.conf.
  • Locate the gzip settings and add the following lines:

    gzip on;

gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1;

  • Save and close the file.
  • Use the 'expires' and 'cache-control' headers to set caching policies for static assets.

Optimize PHP

Activate opcache:

  • Open your PHP configuration file, which is usually located at /etc/php.ini.
  • Locate the [opcache] settings and add or modify the following lines:


'opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=10000 opcache.validate_timestamps=0 zend_extension points to the opcache extension file. opcache.enable enables opcache. opcache.enable_cli enables opcache for command line interface (CLI) scripts. opcache.memory_consumption sets the amount of memory that opcache can use. opcache.interned_strings_buffer sets the amount of memory that opcache can use for string internment. opcache.max_accelerated_files sets the maximum number of PHP files that can be cached by opcache. opcache.validate_timestamps disables the timestamp validation for cached files.'

  • Save and close the file.

Activate memcache:

  • Install the php-memcached extension by running the command sudo apt-get install php-memcached.
  • Restart PHP-FPM by running the command sudo systemctl restart php7.4-fpm.service.

You have now activated opcache and memcache in your LEMP stack.

Optimize MariaDB

Tune the MariaDB configuration file:

  • Open the MariaDB configuration file, which is usually located at /etc/mysql/mariadb.conf.d/50-server.cnf.
  • Locate the [mysqld] section and add or modify the following lines:

' > slow_query_log=1 slow_query_log_file=/var/log/mysql/mariadb-slow.log long_query_time=2


sort_buffer_size=4M read_buffer_size=1M read_rnd_buffer_size=2M join_buffer_size=8M innodb_buffer_pool_size=512M


query_cache_limit=4M query_cache_size=64M innodb_flush_method=O_DIRECT innodb_file_per_table=1

  • slow_query_log enables slow query logging.
  • slow_query_log_file specifies the filename and location for slow query logs.
  • long_query_time sets the threshold for slow queries in seconds.
  • key_buffer_size sets the size of the key buffer for MyISAM tables.
  • sort_buffer_size sets the size of the sort buffer for sorting queries.
  • read_buffer_size and read_rnd_buffer_size set the size of the read buffer and random read buffer for MyISAM tables.
  • join_buffer_size sets the size of the join buffer for joins between tables.
  • innodb_buffer_pool_size sets the size of the buffer pool for InnoDB tables.
  • query_cache_type enables the query cache.
  • query_cache_limit sets the maximum size of individual query results that can be cached.
  • query_cache_size sets the maximum size of the query cache.
  • innodb_flush_method sets the flush method for InnoDB logs.
  • innodb_file_per_table enables the creation of a separate file for each InnoDB table.'
  • Save and close the file.

Optimize tables: Use the mysqlcheck command to optimize all tables in all databases:

  • sudo mysqlcheck --optimize --all-databases
  • Restart the MariaDB service to apply the changes:

sudo systemctl restart mariadb.service

Use a Content Delivery Network (CDN):

Use a CDN to serve static assets, such as images, videos, and JavaScript files, from a network of servers located around the world. This can reduce the load on your server and improve the overall performance of your website.

Minimize HTTP requests:

Combine and minify CSS and JavaScript files to reduce the number of HTTP requests. Use sprites to combine small images into a single image to reduce the number of HTTP requests. Use lazy loading to load images and videos only when they are needed.

Optimize the database:

Regularly optimize the database to reduce the size of tables and improve performance. Use a caching plugin such as WP Super Cache or W3 Total Cache to cache database queries. By following these tips, you can improve the performance of your LEMP stack and provide a faster and more responsive experience for your users.

Step 6 - Deactivation of the cron job on each web page call

  • Open your Crontab file:
    • Run the command crontab -e to open your user's Crontab file.
    • Add the Cron job:
    • Add the following line to the file to run the WordPress scheduled tasks every 5 minutes: */5 * * * * sudo -u www-data php /var/www/html/wp-cron.php > /dev/null 2>&1
  • This line will switch the user to www-data (which is the user that owns the WordPress files), and execute the wp-cron.php file every 5 minutes.
  • Save and close the file.
  • Verify the Cron job:
    • Run the command crontab -l to verify that the Cron job has been added to your Crontab file.
    • You should see the line you added in the previous step.

That's it! The WordPress scheduled tasks will now be executed every 5 minutes using the system's Crontab instead of relying on web requests.



Copyright (c) 2021 netcup

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


Contributor's Certificate of Origin

By making a contribution to this project, I certify that:

  1. The contribution was created in whole or in part by me and I have the right to submit it under the licence indicated in the file; or

  2. The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate licence and I have the right under that licence to submit that work with modifications, whether created in whole or in part by me, under the same licence (unless I am permitted to submit under a different licence), as indicated in the file; or

  3. The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.

  4. I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the licence(s) involved.

Published 30/04/2023 by Sebastian Huskynarr Selinger

Submit your tutorial

Get 60€ netcup vouchers for every published tutorial.