π Introduction
The L(EMP) stack is a powerful combination of open-source software used to serve dynamic web applications and websites. The acronym stands for Linux (operating system), Nginx (web server, pronounced "Engine-X"), MariaDB (database management system), and PHP (server-side scripting language).
L(EMP) Stack Architecture
π‘ Stack Components Overview
- Nginx: High-performance web server that handles HTTP requests and serves static content
- MariaDB: Relational database management system (MySQL fork) for data storage
- PHP 8.3: Server-side scripting language for generating dynamic page content
π¦ Understanding Repositories and Package Management
Repository Types
Ubuntu uses two main types of repositories for software distribution:
β Official Repositories
- Tested by Ubuntu developers
- Guaranteed malware-free
- Full compatibility assured
- Slightly older versions
- Prioritize stability over features
- Recommended for production servers
β οΈ Unofficial Repositories (PPAs)
- Newer package versions
- Maintained by developers/communities
- Regular security updates
- Support multiple PHP versions
- Use with caution
- OndΕej PPA is trusted and safe
APT Package Manager Commands
The Advanced Package Tool (APT) is Ubuntu's package management system. Here are the essential commands:
| Command | Purpose | Example |
|---|---|---|
apt update |
Update package list | sudo apt update |
apt upgrade |
Upgrade installed packages | sudo apt upgrade |
apt install |
Install new package(s) | sudo apt install nginx |
apt remove |
Remove package (keep config) | sudo apt remove nginx |
apt purge |
Remove package + config files | sudo apt purge nginx |
apt-cache search |
Search for packages | apt-cache search nginx |
apt-cache show |
Show package information | apt-cache show nginx |
π‘ Remove vs Purge
Remove: Uninstalls the package but preserves configuration files for future reinstallation.
Purge: Completely removes the package including all configuration files.
Searching for Packages
Search for a package:
apt-cache search nginx
View package details:
apt-cache show nginx
π Installing Nginx Web Server
Nginx is a high-performance web server known for its stability, rich feature set, simple configuration, and low resource consumption. We'll install Nginx along with several useful modules.
Step 1: Update System
sudo apt update
sudo apt upgrade
sshd_config), always choose "Keep the local version currently
installed" unless you're certain about the changes.
Step 2: Add OndΕej Nginx Repository
Note: The repository name has changed from nginx/mainline to just
nginx.
sudo add-apt-repository ppa:ondrej/nginx
Step 3: Install Nginx and Modules
sudo apt install nginx \
libnginx-mod-http-cache-purge \
libnginx-mod-http-headers-more-filter \
libnginx-mod-http-brotli-filter \
libnginx-mod-http-brotli-static
Nginx Modules Explained
| Module | Purpose |
|---|---|
nginx |
Core web server package |
http-cache-purge |
Selective FastCGI cache purging |
headers-more-filter |
Advanced header manipulation |
http-brotli-filter |
Brotli compression for dynamic content |
http-brotli-static |
Pre-compressed static file serving |
Step 4: Check Nginx Status
sudo systemctl status nginx
sudo systemctl status nginx --no-pager -l
β οΈ Troubleshooting IPv6 Binding Error
If you disabled IPv6 for security and Nginx fails to start with an "address family not supported" error, you need to disable IPv6 listening in Nginx configuration:
sudo nano /etc/nginx/sites-available/default
Find the line:
listen [::]:80 default_server;
Comment it out by adding # at the beginning:
# listen [::]:80 default_server;
Save and restart Nginx:
sudo systemctl start nginx
Step 5: Verify Nginx is Running
# Check if enabled for auto-start
sudo systemctl is-enabled nginx
# Check status
sudo systemctl status nginx --no-pager -l
β You should see "active (running)" status and "enabled" for auto-start.
Step 6: Test Nginx in Browser
Open your browser and navigate to:
http://your_server_ip_address/
Or test using curl:
# View HTTP headers
curl -I http://your_server_ip_address/
# View page content
curl -i http://your_server_ip_address/
The default welcome page is located at: /var/www/html/index.nginx-debian.html
Step 7: Check Nginx Version
nginx -v
ποΈ Installing MariaDB Database Server
MariaDB is a community-developed, commercially supported fork of MySQL. Ubuntu 24.04 ships with MariaDB 10.11, which is a Long-Term Support (LTS) release maintained until February 2028.
Step 1: Install MariaDB
sudo apt update
sudo apt install mariadb-server
π‘ No need to run apt update if you just ran it for Nginx installation (within the
same session).
Step 2: Check MariaDB Status
sudo systemctl status mariadb
sudo systemctl status mariadb --no-pager -l
Step 3: Verify Auto-Start Configuration
sudo systemctl is-enabled mariadb
β MariaDB should show "active (running)" and "enabled" status.
MariaDB Communication Flow
π± Client Request
β
π Nginx (Web Server)
β
π PHP-FPM (Processes PHP)
β
ποΈ MariaDB (Fetches Data)
β
π Dynamic HTML Response
π Security Note
After installation, you should run the MariaDB security script to improve security (covered in later sections):
sudo mysql_secure_installation
π Installing PHP 8.3
PHP 8.3 is the latest stable version with significant performance improvements. We'll install it from the OndΕej repository along with essential extensions.
Why Use OndΕej's PHP Repository?
- β Easy version upgrades
- β Multiple PHP versions on same server
- β Regular security updates
- β Comprehensive extension support
- β Maintained by trusted Debian developer
Step 1: Add OndΕej PHP Repository
sudo add-apt-repository ppa:ondrej/php
Step 2: Install PHP 8.3 with Extensions
π‘ Brace Expansion Method
Instead of typing each package separately, use brace expansion for efficiency:
sudo apt install php8.3-{fpm,gd,mbstring,mysql,xml,xmlrpc,opcache,cli,zip,soap,intl,bcmath,curl,imagick,ssh2}
PHP Extensions Explained
| Extension | Purpose |
|---|---|
fpm |
FastCGI Process Manager - Processes PHP requests from Nginx via FastCGI protocol over Unix sockets |
gd |
Graphics Draw - Image manipulation library for creating and editing images |
mbstring |
Multibyte String - Handles non-ASCII strings and character encoding conversions |
mysql |
MySQL/MariaDB Driver - Enables PHP to communicate with MySQL/MariaDB databases |
xml |
XML Parser - Reads and processes XML data from strings |
xmlrpc |
XML-RPC - Allows remote updates to WordPress and other applications |
opcache |
Opcode Cache - Dramatically improves PHP performance by caching precompiled scripts |
cli |
Command Line Interface - Executes PHP commands from the terminal |
zip |
ZIP Archive - Creates, reads, and extracts ZIP files |
soap |
SOAP Protocol - Enables web service creation and consumption |
intl |
Internationalization - Provides localization support for dates, numbers, and currencies |
bcmath |
Binary Calculator - Arbitrary precision mathematics for financial calculations |
curl |
Client URL Library - Makes HTTP requests to external APIs and services |
imagick |
ImageMagick - Advanced image processing using the ImageMagick library |
ssh2 |
SSH2 Protocol - Secure remote server access via SSH |
Step 3: Verify PHP-FPM Status
sudo systemctl status php8.3-fpm
sudo systemctl status php8.3-fpm --no-pager -l
Step 4: Check Auto-Start Configuration
sudo systemctl is-enabled php8.3-fpm
Step 5: Verify PHP Version
php -v
β You should see PHP version 8.3.x displayed with Zend Engine information.
How Nginx and PHP-FPM Work Together
- π¨ Client sends HTTP request for a PHP file to Nginx
- π Nginx receives request and identifies it as PHP content
- π€ Nginx forwards request to PHP-FPM via FastCGI protocol (Unix socket)
- βοΈ PHP-FPM processes the PHP script (connects to MariaDB if needed)
- π₯ PHP-FPM returns the generated HTML to Nginx
- π Nginx sends response back to the client
β Stack Installation Verification
Complete System Check
# Check all services
sudo systemctl status nginx
sudo systemctl status mariadb
sudo systemctl status php8.3-fpm
# Verify auto-start enabled
sudo systemctl is-enabled nginx
sudo systemctl is-enabled mariadb
sudo systemctl is-enabled php8.3-fpm
# Check versions
nginx -v
mysql --version
php -v
β Installation Complete!
Your L(EMP) stack is now fully installed and configured. All services should be:
- β Running (active)
- β Enabled for auto-start on boot
- β Displaying correct version numbers
Quick Reference Commands
| Service | Start | Stop | Restart | Status |
|---|---|---|---|---|
| Nginx | sudo systemctl start nginx |
sudo systemctl stop nginx |
sudo systemctl restart nginx |
sudo systemctl status nginx |
| MariaDB | sudo systemctl start mariadb |
sudo systemctl stop mariadb |
sudo systemctl restart mariadb |
sudo systemctl status mariadb |
| PHP-FPM | sudo systemctl start php8.3-fpm |
sudo systemctl stop php8.3-fpm |
sudo systemctl restart php8.3-fpm |
sudo systemctl status php8.3-fpm |
π Next Steps
What's Coming Next?
Now that your L(EMP) stack is installed, the next section will cover configuring your server to send emails directly without requiring SMTP plugins. This is essential for WordPress notifications, password resets, and other system emails.
Recommended Additional Configurations
- π Secure MariaDB installation (
mysql_secure_installation) - π§ Configure Nginx server blocks (virtual hosts)
- β‘ Optimize PHP-FPM settings for performance
- π Set up SSL/TLS certificates (Let's Encrypt)
- π Configure logging and monitoring
- π‘οΈ Implement firewall rules (UFW)
π§ Common Troubleshooting
Issue: Nginx won't start after installation
Cause: IPv6 disabled but Nginx trying to bind to IPv6 address
Solution: Comment out the IPv6 listen directive in
/etc/nginx/sites-available/default
Issue: Port 80 already in use
Cause: Another service using port 80
Check: sudo netstat -tulpn | grep :80
Solution: Stop conflicting service or configure Nginx to use different port
Issue: PHP files downloading instead of executing
Cause: Nginx not configured to pass PHP requests to PHP-FPM
Solution: Configure Nginx server block to process PHP files (covered in later sections)