How To Install LEMP Stack on Rocky Linux 10
The LEMP stack represents one of the most powerful and efficient web development environments available today. This acronym stands for Linux, Nginx (pronounced “Engine-X”), MySQL/MariaDB, and PHP – a combination that delivers exceptional performance for modern web applications. Unlike traditional LAMP stacks that utilize Apache, LEMP leverages Nginx’s event-driven architecture to handle thousands of concurrent connections with minimal resource consumption.
Rocky Linux 10 emerges as the ideal foundation for your LEMP deployment. This enterprise-grade operating system provides the stability and security features essential for production environments. As a community-driven replacement for Red Hat Enterprise Linux, Rocky Linux offers long-term support, extensive compatibility, and robust performance characteristics that make it perfect for web server deployments.
Why choose LEMP over other web server configurations? The answer lies in its architecture. Nginx excels at serving static content and handling high-traffic scenarios where traditional web servers might struggle. When combined with PHP-FPM (FastCGI Process Manager) and MariaDB’s enhanced performance features, the result is a lightweight yet powerful platform capable of supporting everything from simple websites to complex web applications.
This comprehensive guide will walk you through every aspect of LEMP stack installation on Rocky Linux 10. You’ll learn not only how to install each component but also how to configure them for optimal security and performance. We’ll cover essential topics including firewall configuration, SSL implementation, database security hardening, and performance tuning techniques that will prepare your server for production use.
Whether you’re a system administrator preparing enterprise infrastructure or a developer setting up a development environment, this tutorial provides the knowledge and practical steps needed to build a robust, secure, and high-performing web server platform.
Prerequisites and System Requirements
Before beginning the LEMP stack installation process, ensure your system meets the necessary hardware and software requirements. A successful deployment depends on proper preparation and understanding of the underlying infrastructure needs.
Hardware Requirements
Your Rocky Linux 10 server requires adequate resources to handle web traffic effectively. Minimum specifications include 2GB of RAM, though 4GB or more is recommended for production environments. The additional memory ensures smooth operation when handling multiple concurrent connections and database operations simultaneously.
Storage requirements vary based on your intended use, but allocate at least 10GB of free disk space for the base installation and initial configuration. Consider SSD storage for improved I/O performance, particularly beneficial for database operations and serving static content.
Network connectivity is essential for package downloads, security updates, and serving web content. Ensure stable internet access during installation and ongoing maintenance operations.
Software Prerequisites
Start with a fresh Rocky Linux 10 installation to avoid conflicts with existing packages or configurations. This clean slate approach minimizes potential issues and ensures compatibility with all LEMP stack components.
Administrative privileges are mandatory for system-level installations and configurations. Verify you have either root access or sudo privileges before proceeding with any installation steps.
Basic command-line familiarity will significantly enhance your experience with this guide. While detailed instructions are provided, understanding fundamental Linux concepts like file permissions, service management, and text editing will prove invaluable.
Initial System Preparation
Begin by updating your system packages to ensure you have the latest security patches and software versions:
sudo dnf update -y
This command refreshes package repositories and applies available updates. The -y
flag automatically confirms installation prompts, streamlining the update process.
Verify your firewall status and prepare for web traffic configuration:
sudo systemctl status firewalld
SELinux configuration requires attention in Rocky Linux environments. Check the current enforcement mode:
getenforce
Understanding these baseline configurations will prevent common deployment issues and ensure smooth LEMP stack integration.
Installing Nginx Web Server
Nginx’s event-driven architecture makes it an exceptional choice for modern web applications. Unlike traditional process-based web servers, Nginx utilizes a master process with multiple worker processes, enabling efficient handling of thousands of simultaneous connections while maintaining low memory usage.
Understanding Nginx Architecture
The master process manages worker processes and handles administrative tasks like configuration reloading and worker process management. Worker processes handle actual client connections, with each worker capable of managing thousands of concurrent connections efficiently. This design provides excellent scalability and resource utilization compared to traditional web server models.
Step-by-Step Nginx Installation
Update your package repositories to ensure access to the latest Nginx version:
sudo dnf update -y
Install Nginx using the DNF package manager:
sudo dnf install nginx -y
The installation process automatically resolves dependencies and configures basic system integration. Nginx packages include the main server binary, essential modules, and default configuration files needed for operation.
Verify the installation by checking the Nginx version:
nginx -v
Service Configuration and Management
Enable Nginx to start automatically at boot time:
sudo systemctl enable nginx
Start the Nginx service:
sudo systemctl start nginx
Verify the service is running correctly:
sudo systemctl status nginx
The status command displays detailed information about service state, recent log entries, and any potential issues requiring attention.
Firewall Configuration
Configure firewall rules to allow web traffic through standard HTTP and HTTPS ports:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
These commands permanently add HTTP (port 80) and HTTPS (port 443) services to the firewall configuration and reload the rules to make them active immediately.
Verify firewall rules are active:
sudo firewall-cmd --list-services
Initial Testing and Verification
Test Nginx functionality by accessing your server’s IP address through a web browser. You should see the default Rocky Linux Nginx welcome page, confirming successful installation and basic functionality.
For command-line testing, use curl:
curl http://localhost
This command retrieves the default page content and verifies Nginx is responding to HTTP requests properly.
Monitor Nginx logs for any issues:
sudo tail -f /var/log/nginx/error.log
Log monitoring helps identify configuration problems or potential security issues during initial setup and ongoing operations.
Installing MariaDB Database Server
MariaDB serves as an excellent MySQL replacement, offering enhanced performance features, improved security, and full compatibility with existing MySQL applications. Rocky Linux 10 includes MariaDB in its default repositories, simplifying installation and ensuring optimal integration with the operating system.
MariaDB vs MySQL Considerations
MariaDB was created by MySQL’s original developers and maintains complete compatibility with MySQL protocols and data formats. It offers several advantages including improved performance in many scenarios, enhanced security features, and more transparent development processes. For Rocky Linux deployments, MariaDB provides better integration and long-term support guarantees.
Installation Process
Install MariaDB server and client packages:
sudo dnf install mariadb-server mariadb -y
This command installs both the database server and client tools necessary for database administration and application connectivity.
Enable MariaDB to start automatically at system boot:
sudo systemctl enable mariadb
Start the MariaDB service:
sudo systemctl start mariadb
Verify the service is running properly:
sudo systemctl status mariadb
Initial Security Configuration
Run the security installation script to configure basic security settings:
sudo mysql_secure_installation
This interactive script guides you through several security enhancements:
- Set root password: Choose a strong password for the database root user
- Remove anonymous users: Delete default anonymous user accounts
- Disable remote root login: Prevent root access from remote hosts
- Remove test database: Delete the default test database
- Reload privilege tables: Apply security changes immediately
Follow the prompts carefully, answering “Y” to most security questions unless you have specific requirements for less restrictive settings.
Database Service Management
Verify MariaDB is accepting connections:
sudo mysql -u root -p
This command opens an interactive MariaDB session where you can execute SQL commands and verify database functionality.
Create a test database to confirm proper operation:
CREATE DATABASE test_lemp;
SHOW DATABASES;
EXIT;
These SQL commands create a new database, display all available databases, and exit the MySQL client.
Basic Database Operations
Configure a database user for web applications:
CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON *.* TO 'webuser'@'localhost';
FLUSH PRIVILEGES;
Replace ‘secure_password’ with a strong password for production environments. This user account will handle database connections from your web applications.
Monitor MariaDB performance and connections:
sudo mysql -u root -p -e "SHOW PROCESSLIST;"
This command displays current database connections and active queries, helpful for performance monitoring and troubleshooting.
Installing PHP Processing Engine
PHP serves as the dynamic content engine for your LEMP stack, processing server-side scripts and generating dynamic web pages. Rocky Linux 10 provides multiple PHP versions through modular packages, allowing you to choose the most appropriate version for your applications.
PHP Version Selection
Check available PHP versions:
sudo dnf module list php
Rocky Linux 10 typically includes PHP 8.0 and PHP 8.1 streams. For optimal performance and security, choose the latest stable version unless specific application compatibility requirements dictate otherwise.
Reset any existing PHP module configurations:
sudo dnf module reset php -y
Enable the desired PHP version (PHP 8.1 recommended):
sudo dnf module enable php:8.3 -y
Core PHP Installation
Install PHP and essential modules:
sudo dnf install php php-fpm php-mysqlnd php-json php-xml php-mbstring php-curl php-zip php-gd -y
These modules provide:
- php-fpm: FastCGI Process Manager for Nginx integration
- php-mysqlnd: MariaDB/MySQL connectivity
- php-json: JSON parsing and generation
- php-xml: XML processing capabilities
- php-mbstring: Multi-byte string handling
- php-curl: HTTP client functionality
- php-zip: Archive file handling
- php-gd: Image processing capabilities
PHP-FPM Configuration
PHP-FPM offers significant advantages over traditional mod_php implementations, including better resource isolation, improved security, and enhanced performance for high-traffic scenarios.
Configure PHP-FPM to start automatically:
sudo systemctl enable php-fpm
Start the PHP-FPM service:
sudo systemctl start php-fpm
Verify PHP-FPM is running:
sudo systemctl status php-fpm
Edit the PHP-FPM pool configuration for optimization:
sudo nano /etc/php-fpm.d/www.conf
Key configuration parameters to review:
user = nginx
group = nginx
listen = /run/php-fpm/www.sock
listen.owner = nginx
listen.group = nginx
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
These settings configure PHP-FPM to run under the nginx user account and optimize process management for typical web server workloads.
Integration with Nginx
PHP-FPM communicates with Nginx through Unix sockets or TCP connections. Unix sockets generally provide better performance for local connections.
Restart PHP-FPM after configuration changes:
sudo systemctl restart php-fpm
Verification and Testing
Verify PHP installation and version:
php -v
Create a test PHP file to verify functionality:
sudo nano /usr/share/nginx/html/info.php
Add the following content:
<?php
phpinfo();
?>
This file will display comprehensive PHP configuration information when accessed through a web browser, confirming proper installation and module availability.
LEMP Stack Integration and Configuration
Integrating all LEMP stack components requires careful configuration to ensure secure and efficient communication between Nginx, PHP-FPM, and MariaDB. Proper integration enables dynamic content processing while maintaining optimal performance and security standards.
Nginx Configuration for PHP Processing
Create a new server block configuration for your website:
sudo nano /etc/nginx/conf.d/default.conf
Add the following configuration:
server {
listen 80;
server_name your_domain.com www.your_domain.com;
root /usr/share/nginx/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
This configuration enables PHP processing through FastCGI and implements basic security measures like blocking access to .htaccess files.
Virtual Host Setup
For multiple websites, create separate configuration files for each domain:
sudo nano /etc/nginx/conf.d/example.com.conf
Implement domain-specific configurations including SSL certificates, custom error pages, and application-specific routing rules.
Test Nginx configuration syntax:
sudo nginx -t
This command validates configuration files and reports any syntax errors before applying changes.
Reload Nginx configuration:
sudo systemctl reload nginx
Database Connection Configuration
Create a PHP test script to verify database connectivity:
sudo nano /usr/share/nginx/html/db_test.php
Add database connection test code:
<?php
$servername = "localhost";
$username = "webuser";
$password = "secure_password";
try {
$pdo = new PDO("mysql:host=$servername", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Database connection successful!";
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
File Permissions and Security
Set appropriate permissions for web content directories:
sudo chown -R nginx:nginx /usr/share/nginx/html
sudo chmod -R 755 /usr/share/nginx/html
Configure SELinux contexts for web content:
sudo setsebool -P httpd_can_network_connect 1
sudo setsebool -P httpd_execmem 1
These SELinux booleans allow web servers to establish network connections and execute memory operations necessary for dynamic content processing.
Sample Application Deployment
Create a comprehensive test application to verify complete stack functionality:
sudo nano /usr/share/nginx/html/lemp_test.php
Include code that tests all stack components:
<?php
echo "<h1>LEMP Stack Test</h1>";
echo "<p>PHP Version: " . phpversion() . "</p>";
// Database connection test
try {
$pdo = new PDO("mysql:host=localhost", "webuser", "secure_password");
echo "<p>Database: Connected successfully</p>";
// Create test table
$pdo->exec("CREATE DATABASE IF NOT EXISTS lemp_test");
$pdo->exec("USE lemp_test");
$pdo->exec("CREATE TABLE IF NOT EXISTS test_table (id INT AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255))");
$pdo->exec("INSERT INTO test_table (message) VALUES ('LEMP Stack is working!')");
// Retrieve and display data
$stmt = $pdo->query("SELECT message FROM test_table ORDER BY id DESC LIMIT 1");
$result = $stmt->fetch();
echo "<p>Database Test: " . $result['message'] . "</p>";
} catch(PDOException $e) {
echo "<p>Database Error: " . $e->getMessage() . "</p>";
}
echo "<p>Server: Nginx</p>";
echo "<p>Test completed at: " . date('Y-m-d H:i:s') . "</p>";
?>
This comprehensive test verifies that all LEMP components are functioning together correctly.
Security Hardening and Best Practices
Implementing robust security measures protects your LEMP stack from common threats and ensures compliance with security best practices. A layered security approach addresses vulnerabilities at each component level while maintaining optimal performance.
Nginx Security Configuration
Hide server version information to reduce attack surface:
sudo nano /etc/nginx/nginx.conf
Add or modify the following directive in the http block:
server_tokens off;
Implement security headers:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
Configure rate limiting to prevent abuse:
http {
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
server {
location /login {
limit_req zone=login burst=5 nodelay;
}
}
}
MariaDB Security Enhancements
Create dedicated database users with minimal privileges:
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_database.* TO 'app_user'@'localhost';
FLUSH PRIVILEGES;
Configure MariaDB to listen only on localhost:
sudo nano /etc/my.cnf.d/mariadb-server.cnf
Add or modify:
[mysqld]
bind-address = 127.0.0.1
Implement regular backup procedures:
sudo mkdir -p /backup/mysql
sudo mysqldump --all-databases --single-transaction --routines --triggers > /backup/mysql/backup_$(date +%Y%m%d_%H%M%S).sql
PHP Security Settings
Configure secure PHP settings:
sudo nano /etc/php.ini
Modify critical security parameters:
expose_php = Off
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
allow_url_fopen = Off
allow_url_include = Off
session.cookie_httponly = 1
session.cookie_secure = 1
max_execution_time = 30
max_input_time = 60
memory_limit = 128M
post_max_size = 8M
upload_max_filesize = 2M
System-Level Security
Configure automatic security updates:
sudo dnf install dnf-automatic -y
sudo systemctl enable --now dnf-automatic.timer
Implement fail2ban for intrusion prevention:
sudo dnf install epel-release -y
sudo dnf install fail2ban -y
sudo systemctl enable --now fail2ban
Configure fail2ban for web services:
sudo nano /etc/fail2ban/jail.local
Add configuration:
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
[nginx-limit-req]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 10
SSL/TLS Implementation
Install Let’s Encrypt certificates for production deployments:
sudo dnf install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your_domain.com -d www.your_domain.com
Configure automatic certificate renewal:
sudo systemctl enable --now certbot-renew.timer
Implement strong SSL configuration:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
Performance Optimization
Optimizing LEMP stack performance involves tuning each component for your specific workload and traffic patterns. Proper optimization can significantly improve response times, increase concurrent user capacity, and reduce server resource consumption.
Nginx Performance Tuning
Configure worker processes based on CPU cores:
sudo nano /etc/nginx/nginx.conf
Optimize worker settings:
worker_processes auto;
worker_connections 1024;
worker_rlimit_nofile 2048;
events {
use epoll;
multi_accept on;
}
Enable gzip compression:
http {
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
}
Configure caching for static content:
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
MariaDB Performance Enhancement
Optimize MariaDB configuration:
sudo nano /etc/my.cnf.d/mariadb-server.cnf
Add performance tuning parameters:
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
query_cache_type = 1
query_cache_size = 64M
tmp_table_size = 64M
max_heap_table_size = 64M
Monitor query performance:
SHOW PROCESSLIST;
SHOW ENGINE INNODB STATUS;
PHP Performance Optimization
Enable OPcache for significant performance improvements:
sudo nano /etc/php.d/10-opcache.ini
Configure OPcache settings:
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=2
opcache.fast_shutdown=1
Optimize PHP-FPM pool settings:
pm = dynamic
pm.max_children = 20
pm.start_servers = 8
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500
System Resource Management
Monitor system performance:
top
htop
iotop
Configure system limits:
sudo nano /etc/security/limits.conf
Add resource limits:
nginx soft nofile 65536
nginx hard nofile 65536
Optimize kernel parameters:
sudo nano /etc/sysctl.conf
Add network optimizations:
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
Troubleshooting Common Issues
Understanding common LEMP stack issues and their solutions enables quick resolution of problems that may arise during installation, configuration, or operation. This section covers the most frequent challenges and provides practical troubleshooting approaches.
Installation Problems
Package dependency conflicts often occur when mixing repositories or using outdated package sources. Resolve by cleaning package cache and updating repositories:
sudo dnf clean all
sudo dnf update -y
Repository access issues may prevent package installation. Verify network connectivity and repository configuration:
sudo dnf repolist
ping google.com
Service startup failures typically result from configuration errors or resource constraints. Check service status and logs:
sudo systemctl status nginx
sudo journalctl -u nginx -f
Configuration Errors
Nginx configuration syntax errors prevent service startup. Always test configuration before reloading:
sudo nginx -t
Common syntax issues include missing semicolons, incorrect directive placement, or invalid parameter values.
PHP-FPM connection problems often stem from socket permission issues or incorrect Nginx FastCGI configuration. Verify socket permissions:
ls -la /run/php-fpm/www.sock
Database connectivity issues may result from incorrect credentials, network restrictions, or service problems. Test connections manually:
mysql -u webuser -p -h localhost
Performance Issues
High memory usage can overwhelm servers with insufficient resources. Monitor process memory consumption:
ps aux --sort=-%mem | head
free -h
Slow response times may indicate configuration problems or resource bottlenecks. Enable slow query logging and analyze performance:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
Resource bottleneck identification requires systematic monitoring of CPU, memory, disk I/O, and network utilization:
iostat -x 1
nethogs
Security Concerns
Permission-related errors can prevent proper file access or execution. Verify ownership and permissions:
ls -la /usr/share/nginx/html/
sudo chown -R nginx:nginx /usr/share/nginx/html/
Firewall connectivity problems may block legitimate traffic. Review firewall rules and logs:
sudo firewall-cmd --list-all
sudo tail -f /var/log/firewalld
SELinux denial troubleshooting requires understanding security contexts and policies:
sudo sealert -a /var/log/audit/audit.log
sudo getsebool -a | grep httpd
Maintenance and Monitoring
Regular maintenance ensures optimal LEMP stack performance, security, and reliability. Implementing systematic monitoring and maintenance procedures prevents issues before they impact production systems.
Regular Maintenance Tasks
System updates should be applied regularly to maintain security and stability:
sudo dnf update -y
sudo systemctl restart nginx php-fpm mariadb
Log rotation and cleanup prevents disk space exhaustion:
sudo nano /etc/logrotate.d/nginx
Configure log rotation:
/var/log/nginx/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 644 nginx adm
postrotate
systemctl reload nginx
endscript
}
Performance monitoring identifies trends and potential issues:
sudo dnf install htop iotop nethogs -y
Backup Strategies
Database backup automation ensures data protection:
sudo nano /usr/local/bin/backup_databases.sh
Create backup script:
#!/bin/bash
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
mysqldump --all-databases --single-transaction > $BACKUP_DIR/all_databases_$DATE.sql
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
Make executable and schedule:
sudo chmod +x /usr/local/bin/backup_databases.sh
sudo crontab -e
Add cron job:
0 2 * * * /usr/local/bin/backup_databases.sh
Configuration file backups preserve system settings:
sudo tar -czf /backup/configs_$(date +%Y%m%d).tar.gz /etc/nginx /etc/php-fpm.d /etc/my.cnf.d
Monitoring and Alerting
System resource monitoring tracks server health:
sudo dnf install zabbix-agent2 -y
Service availability checks ensure continuous operation:
sudo nano /usr/local/bin/check_services.sh
Create monitoring script:
#!/bin/bash
services=("nginx" "php-fpm" "mariadb")
for service in "${services[@]}"; do
if ! systemctl is-active --quiet $service; then
echo "$service is down" | mail -s "Service Alert" admin@yourdomain.com
systemctl restart $service
fi
done
Performance metrics tracking provides operational insights:
curl -o /tmp/server_status http://localhost/nginx_status
curl -o /tmp/php_status http://localhost/php-fpm-status
Update Management
Security patch application maintains system security:
sudo dnf update --security -y
Version upgrade procedures require careful planning and testing:
sudo dnf module list php
sudo dnf module reset php
sudo dnf module enable php:8.2
sudo dnf update php*
Compatibility testing ensures application functionality after updates:
php -v
nginx -t
systemctl status mariadb
Congratulations! You have successfully installed LEMP. Thanks for using this tutorial for installing the LEMP Stack on your Rocky Linux 10 system. For additional help or useful information, we recommend you check the official LEMP website.