I ran LAMP for a long time. Apache, MySQL, PHP — it did the job. But every time I checked memory usage on a smaller server, Apache was sitting there using RAM even when nothing was happening. Nginx handles the same workload with a noticeably lighter footprint, especially when you're on a budget server or running multiple services on one machine.
Switching to the LEMP stack (Linux, Nginx, MySQL, PHP-FPM) made my PHP apps feel snappier and left more headroom for databases and other processes. It's been my default ever since.
The PHP-FPM part is where new people sometimes get confused — PHP doesn't run inside Nginx the way it does with Apache's mod_php. Instead, PHP-FPM is a separate process manager that Nginx communicates with via a socket. Once you understand that model, the config clicks into place.
This guide installs and configures the full stack on Ubuntu 22.04, including Nginx virtual hosts, PHP-FPM socket configuration, and HTTPS.
I run this on Tencent Cloud Lighthouse with Ubuntu 22.04 LTS. The 2 GB RAM plan handles LEMP comfortably — Nginx's low memory footprint leaves plenty of headroom for your application and database. If you need a LEMP stack specifically for PHP applications like WordPress or Laravel, Lighthouse also offers LNMP application images that pre-configure the entire stack for you. For custom PHP apps where you want more control over the configuration, the manual setup in this guide is the right approach. Lighthouse's console-level firewall also makes it easy to open the right ports without touching the OS-level UFW rules.
Key Takeaways
- Use the Lighthouse LNMP application image for instant LEMP stack setup
- PHP-FPM runs as a separate process — Nginx proxies PHP requests to it via socket
- The socket path in
fastcgi_passmust match the actual PHP-FPM socket (/var/run/php/phpX.X-fpm.sock)- Test PHP-FPM is connected: create a
.phpfile that returnsphpinfo()output- Pool config in
/etc/php/X.X/fpm/pool.d/www.confcontrols PHP-FPM workers
| LAMP (Apache) | LEMP (Nginx) | |
|---|---|---|
| Web server | Apache | Nginx |
| PHP handler | mod_php (in-process) | PHP-FPM (separate process) |
| Memory at idle | Higher | Lower |
.htaccess support |
Yes (native) | No (needs Nginx config equivalent) |
| Static file performance | Good | Excellent |
| Concurrency model | Thread/process | Event-driven |
Choose LEMP when: you want lower memory usage, better static file performance, or plan to run multiple services on the same server.
Choose LAMP when: you're deploying an application that relies heavily on .htaccess directives or Apache-specific modules.
⚡ Shortcut: Tencent Cloud Lighthouse has a pre-built LNMP application image (Linux + Nginx + MySQL + PHP). If you select it when creating your instance, Nginx, MySQL, and PHP-FPM are already installed and configured — skip this entire manual installation. The guide below is for cases where you need precise control over versions or configurations, or where you're adding LEMP to an existing server.
sudo apt update
sudo apt install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# Open ports
sudo ufw allow 'Nginx Full'
# Verify
curl http://localhost
# Should return the Nginx welcome page HTML
sudo apt install -y mysql-server
sudo systemctl start mysql
sudo systemctl enable mysql
# Run security hardening
sudo mysql_secure_installation
Answer the prompts:
With Nginx, PHP runs as a separate process via PHP-FPM (FastCGI Process Manager) rather than being embedded in the web server. This is slightly more complex to configure but more efficient.
sudo apt install -y php-fpm php-mysql
# Install common PHP extensions
sudo apt install -y \
php-curl \
php-gd \
php-mbstring \
php-xml \
php-zip \
php-intl \
php-bcmath
# Check the PHP-FPM version that was installed
php-fpm8.1 --version
# Note the version number (8.1 in this example) — you'll need it for Nginx config
PHP-FPM starts automatically and communicates with Nginx via a Unix socket:
# Find the socket path
ls /run/php/
# You should see: php8.1-fpm.sock (or similar)
Note the socket filename — you'll use it in the Nginx configuration.
Edit the Nginx default site config (or create a new one) to pass PHP requests to PHP-FPM:
sudo nano /etc/nginx/sites-available/default
Replace the contents with:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm;
server_name _;
location / {
try_files $uri $uri/ =404;
}
# Pass PHP scripts to PHP-FPM
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# Update this path to match your PHP-FPM socket
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
# Deny access to .htaccess files
location ~ /\.ht {
deny all;
}
}
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
sudo nano /var/www/html/info.php
<?php phpinfo(); ?>
Visit http://YOUR_SERVER_IP/info.php. You should see the PHP info page showing the Nginx server API and PHP-FPM configuration.
Delete the file after testing:
sudo rm /var/www/html/info.php
sudo mysql
CREATE DATABASE myapp;
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'choose_a_strong_password';
GRANT ALL PRIVILEGES ON myapp.* TO 'myapp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
sudo mkdir -p /var/www/mysite
sudo chown -R www-data:www-data /var/www/mysite
sudo nano /var/www/mysite/index.php
<?php echo "<h1>mysite.com is running on LEMP.</h1>"; ?>
Create the Nginx site config:
sudo nano /etc/nginx/sites-available/mysite
server {
listen 80;
listen [::]:80;
server_name mysite.com www.mysite.com;
root /var/www/mysite;
index index.php index.html;
access_log /var/log/nginx/mysite_access.log;
error_log /var/log/nginx/mysite_error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d mysite.com -d www.mysite.com
Certbot modifies your Nginx config and handles auto-renewal. Test it:
sudo certbot renew --dry-run
The most common LEMP configuration error: the PHP-FPM socket path in your Nginx config doesn't match the actual socket.
Symptoms: Nginx returns a 502 Bad Gateway when accessing PHP files.
# Find the actual socket path
ls /run/php/
# Example output: php8.1-fpm.pid php8.1-fpm.sock
# Check your Nginx config uses the correct path
grep fastcgi_pass /etc/nginx/sites-enabled/*
If there's a mismatch, update the fastcgi_pass line in your Nginx config to use the actual socket name, then reload.
Also check PHP-FPM is actually running:
sudo systemctl status php8.1-fpm
If it's not running, start it:
sudo systemctl start php8.1-fpm
sudo systemctl enable php8.1-fpm
# Nginx
sudo nginx -t # Test config
sudo systemctl reload nginx # Reload config
tail -f /var/log/nginx/error.log # Watch errors
# PHP-FPM
sudo systemctl status php8.1-fpm # Check status
sudo systemctl restart php8.1-fpm # Restart
php -v # Check PHP version
php -m # List modules
# MySQL
sudo mysql # Connect as root
mysql -u USER -p DATABASE # Connect as user
mysqldump -u USER -p DB > backup.sql # Backup database
| Issue | Likely Cause | Fix |
|---|---|---|
| Connection refused | Service not running or wrong port | Check systemctl status SERVICE and verify firewall rules |
| Permission denied | Wrong file ownership or permissions | Check file ownership with ls -la and use chown/chmod to fix |
| 502 Bad Gateway | Backend service not running | Restart the backend service; check logs with journalctl -u SERVICE |
| SSL certificate error | Certificate expired or domain mismatch | Run sudo certbot renew and verify domain DNS points to server IP |
| Service not starting | Config error or missing dependency | Check logs with journalctl -u SERVICE -n 50 for specific error |
| Out of disk space | Logs or data accumulation | Run df -h to identify usage; clean logs or attach CBS storage |
| High memory usage | Too many processes or memory leak | Check with htop; consider upgrading instance plan if consistently high |
| Firewall blocking traffic | Port not open in UFW or Lighthouse console | Open port in Lighthouse console firewall AND sudo ufw allow PORT |
Does Lighthouse have a pre-built LNMP image?
Yes — the LNMP application image comes with Nginx + MySQL + PHP-FPM pre-configured. Select it to skip all manual installation.
What is PHP-FPM and why use it with Nginx?
PHP-FPM is a separate PHP process manager. Nginx communicates with it via a Unix socket, allowing PHP and Nginx to run as independent processes with better resource management.
Where is the PHP-FPM socket located?
On Ubuntu with PHP 8.2: /var/run/php/php8.2-fpm.sock. Reference this path in your Nginx fastcgi_pass directive.
What is the difference between LNMP and LEMP?
Same stack: Linux + Nginx + MySQL + PHP. Different abbreviation spellings, same setup.
How do I run multiple PHP versions on one server?
Install multiple PHP-FPM versions via the ondrej/php PPA. Configure each Nginx site to use the appropriate PHP-FPM socket path.
Launch your cloud server today:
👉 Tencent Cloud Lighthouse — Lightweight Ubuntu VPS
👉 View current pricing and promotions
👉 Explore all active deals and offers