
In this tutorial, we are going to show you how to set up a high-performance LEMP stack on Ubuntu 26.04. LEMP is a shortcut for Linux, NGINX, MariaDB (or MySQL), and PHP. This stack has powered millions of fast, modern websites and web applications. The version we are going to install in this tutorial is the latest and greatest combination available in 2026: NGINX as the web server, PHP 8.4 with the FPM process manager, MariaDB 11.8 LTS as the database engine, and Redis as an in-memory cache layer for sessions and object caching.
NGINX is well known for its event-driven architecture, low memory footprint, and ability to handle thousands of concurrent connections without breaking a sweat – which makes it the perfect web server for high-traffic dynamic websites. Pair it with PHP 8.4’s JIT compiler, MariaDB 11.8’s improved query optimizer, and Redis to offload sessions and queries from the database, and you get a stack that can comfortably serve WordPress, Laravel, Magento, Nextcloud, or any other PHP-based application at scale
Installing a high-performance LEMP stack on Ubuntu 26.04 is straightforward and should take 15 to 20 minutes. Let’s get started!
Table of Contents
Prerequisites
– An Ubuntu 26.04 server (codenamed Resolute Raccoon)
– User privileges: root, or a non-root user with sudo privileges
Step 1. Update the System
Before we start with any installation, we will update the system packages to their latest versions:
# apt update -y && sudo apt upgrade -y
Once finished, it is a good idea to reboot if a new kernel was installed:
# reboot
Step 2. Install NGINX
The first component of our LEMP stack is the NGINX web server. NGINX is available in the default Ubuntu 26.04 repositories, so installation is just a single command:
apt install nginx -y
Once installed, start the NGINX service and enable it to start automatically at boot:
systemctl start nginx && sudo systemctl enable nginx
To confirm that NGINX is up and running, execute the following command:
systemctl status nginx
You should see output similar to this:
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-05-11 10:14:22 UTC; 5s ago
Docs: man:nginx(8)
Main PID: 2418 (nginx)
Tasks: 4 (limit: 4613)
Memory: 3.1M (peak: 3.7M)
CPU: 38ms
CGroup: /system.slice/nginx.service
├─2418 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
├─2419 "nginx: worker process"
├─2420 "nginx: worker process"
└─2421 "nginx: worker process"
Now open your browser and navigate to `http://your_server_ip`. You should see the default NGINX welcome page, which confirms that the web server is working as expected.
Step 3. Install MariaDB 11.8
The next component is the database server. Ubuntu 26.04 ships MariaDB 11.8 LTS directly in the default repositories, so there is no need to add an external repository for this release. You can also confirm this by checking the available mariadb-server packages with:
apt-cache search mariadb-server
Now, to install MariaDB, use the command:
apt install mariadb-server mariadb-client -y
Once installed, start and enable the service:
systemctl start mariadb && sudo systemctl enable mariadb
Verify that the database service is running:
# systemctl status mariadb
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; preset: enabled)
Active: active (running) since Tue 2026-05-12 04:37:05 UTC; 6h ago
You can now connect to the MariaDB shell to confirm everything is working:
sudo mariadb
Step 4. Install PHP 8.4 with PHP-FPM
At the moment of writing the tutorial, the PPA Ondrej is not supported for Ubuntu 26.04. So for this tutorial, we will show you how to install PHP 8.4 from source.
You can download the source files from GitHub or directly download and extract the files with the command:
wget https://www.php.net/distributions/php-8.4.21.tar.gz
tar -xzvf php-8.4.21.tar.gz
cd php-8.4.21
Now, to install, you will need to configure PHP with the PHP extensions:
./configure --prefix=/usr/local/php8.4 \
--with-config-file-path=/usr/local/php8.4/etc \
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
--with-fpm-systemd \
--with-mysqli \
--with-pdo-mysql \
--with-openssl \
--with-zlib \
--with-curl \
--with-gd \
--with-mbstring \
--with-opcache \
--enable-opcache \
--enable-intl \
--enable-zip
Once completed, go ahead and compile the PHP with the following command:
make -j$(nproc)
You should allow some time for the compilation process to finish. When the compilation is done, we can install PHP 8.3 with the command below:
make install
After the installation, we need to make a symbolic link:
ln -s /usr/local/php8.4/bin/php /usr/bin/php
Once the installation is complete, check the PHP version:
php -v
You should get an output similar to this:
PHP 8.4.21 (cli) (built: May 11 2026 18:23:32) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.4.21, Copyright (c) Zend Technologies
You can now configure the PHP-FPM service. First, create the php-fpm.service file in /etc/systemd/system/ and enter the following:
[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target
[Service]
Type=simple
PIDFile=/run/php-fpm/php-fpm.pid
ExecStart=/usr/local/php8.4/sbin/php-fpm --nodaemonize --fpm-config /usr/local/php8.4/etc/php-fpm.d/www.conf.default
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
Now reload the php-fpm daemon and start the service
systemctl daemon-reload
systemctl start php-fpm
To check if the service is started and running, check with:
# systemctl status php-fpm
● php-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/etc/systemd/system/php-fpm.service; disabled; preset: enabled)
Active: active (running) since Tue 2026-05-12 20:25:17 UTC; 4s ago
Step 5. Install and Configure Redis
Redis is an in-memory key-value store that drastically reduces database load by caching sessions, objects, and frequently used queries. Ubuntu 26.04 ships Redis 8 in the default repositories, which is a perfectly good choice for production use.
Install Redis and the CLI tools with:
apt install redis-server redis-tools -y
Now open the Redis configuration file to tune it for production:
nano /etc/redis/redis.conf
Find and update the following directives
supervised systemd
maxmemory 512mb
maxmemory-policy allkeys-lru
The `supervised systemd` directive lets systemd properly manage the Redis process. The `maxmemory` directive caps Redis memory usage – adjust this to your hardware. The `allkeys-lru` policy tells Redis to evict the least recently used keys when the memory cap is reached, which is the best policy for using Redis as a cache.
For security, make sure Redis is bound only to localhost (this is the default), and set a password by uncommenting and editing the `requirepass` directive:
bind 127.0.0.1 ::1
requirepass YourStrongRedisPasswordHere
Save the file and exit. Then restart Redis and enable it on boot:
systemctl restart redis-server && sudo systemctl enable redis-server
Verify Redis is responding:
redis-cli -a YourStrongRedisPasswordHere ping
You should get:
PONG
That confirms Redis is installed and responding.
Step 6. Tune PHP-FPM for High Performance
The default PHP-FPM pool configuration is conservative and not ideal for high-traffic websites. Open the `www` pool config:
nano /usr/local/php8.4/etc/php-fpm.d/www.conf.default
Find the following directives and adjust them based on your server resources. The values below are a sensible baseline for a server with 4 GB of RAM:
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500
A rough rule of thumb: `pm.max_children` should be set so that `max_children × average PHP process memory` is less than your available RAM. On a 4 GB server, assuming each PHP process uses around 40 MB, 50 workers is a safe ceiling.
Next, let’s tune OPcache, the bytecode cache that ships with PHP and is one of the biggest single performance wins you can enable. Open the OPcache config file and set the following settings:
zend_extension=opcache
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.jit_buffer_size=128M
opcache.jit=tracing
The last two lines enable the PHP 8.4 JIT (Just-In-Time) compiler in tracing mode, which can deliver significant performance gains for CPU-bound workloads.
Save the file and restart PHP-FPM to apply the changes:
systemctl restart php-fpm
Step 7. Configure NGINX with PHP-FPM
Now we will create an NGINX server block that passes PHP requests to PHP-FPM. We’ll also tune the worker processes for performance.
First, edit the main NGINX configuration file:
nano /etc/nginx/nginx.conf
Adjust the top-level performance directives:
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
multi_accept on;
use epoll;
}
…
Save and close the file. Next, create a new server block for your website. Replace `your_domain.com` with your actual domain:
nano /etc/nginx/sites-available/your_domain.com
Paste the following configuration:
server {
listen 80;
server_name example.com;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
# Static asset caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?|svg)$ {
expires 30d;
access_log off;
add_header Cache-Control "public, no-transform";
}
}
Save the file and exit. Now create the document root and enable the site:
mkdir -p /var/www/html/
chown -R www-data:www-data /var/www/html
sudo ln -s /etc/nginx/sites-available/your_domain.com /etc/nginx/sites-enabled/ your_domain.com
Test the NGINX configuration for syntax errors:
nginx -t
If everything is fine, you will see:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Reload NGINX to apply the new configuration:
systemctl reload nginx
Step 8. Use Redis as the PHP Session Handler
By default, PHP stores session data on disk, which is slow and does not scale well. By moving sessions into Redis, you cut disk I/O and gain support for sticky sessions across multiple servers.
Open the PHP-FPM `php.ini`:
nano /etc/php/8.4/fpm/php.ini
Find these two directives and change them to point at Redis:
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?auth=YourStrongRedisPasswordHere"
Save the file, then restart PHP-FPM:
systemctl restart php8.4-fpm
From this point on, all PHP sessions will be stored in Redis, freeing up disk I/O and giving you blazing-fast session reads and writes.
Step 9. Optional Performance Tweaks
Install Certbot and grab a free Let’s Encrypt certificate:
apt install certbot python3-certbot-nginx -y
certbot --nginx -d your_domain.com -d www.your_domain.com
After Certbot finishes, edit your server block and replace `listen 80;` with `listen 443 ssl http2;` to enable HTTP/2, which dramatically improves load times for asset-heavy pages.
Step 10. Add FastCGI caching in NGINX
For mostly-static sites (blogs, brochure sites, WordPress with Redis object caching), enable FastCGI caching at the NGINX layer to skip PHP entirely for cached pages.
You can adjust the nginx file /etc/nginx/sites-available/your_domain.com to:
set $skip_cache 0;
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
if ($http_cookie ~* "PHPSESSID|wordpress_logged_in|woocommerce_items_in_cart") {
set $skip_cache 1;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_cache PHP;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_valid 200 301 302 30m;
fastcgi_cache_valid 404 1m;
add_header X-FastCGI-Cache $upstream_cache_status;
}
Reload NGINX and watch your TTFB drop into the single-digit milliseconds for cached responses.
Step 11. Tune MariaDB for your workload
You can use MySQL Tuner to check and tune MySQL according to your server resources.
wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
chmod +x mysqltuner.pl
perl mysqltuner.pl
Running this script will check and suggest the edits you can apply to your MySQL configuration file.
Or if you have a dedicated database server, you can adjust the buffer pool to roughly 50–70% of total RAM by editing the /etc/mysql/mariadb.conf.d/50-server.cnf file.
innodb_buffer_pool_size = 2G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
max_connections = 200
query_cache_type = 0
query_cache_size = 0
Restart MariaDB to apply:
systemctl restart mariadb
That’s it! You now have a fully working, production-ready, high-performance LEMP stack on Ubuntu 26.04 with NGINX, PHP 8.4 (with JIT and OPcache), MariaDB 11.8 LTS, and Redis 8 acting as both a session store and a general-purpose cache. This stack is more than capable of handling thousands of concurrent users on a modest VPS, and it gives you a solid foundation for installing WordPress, Laravel, Magento, Nextcloud, or any other modern PHP application.
Of course, you don’t have to set up a high-performance LEMP stack on Ubuntu 26.04 if you use one of our [Managed Linux VPS Hosting](https://www.rosehosting.com/linux-vps-hosting/) services, in which case you can simply ask our expert Linux admins to set up, optimize, and secure the entire stack for you – completely free of charge. They are available 24/7 and will take care of your request immediately.