Installing Nginx + PHP + MySQL on Ubuntu (LEMP Stack)
Last updated: 23 September 2026
LEMP = Linux + Engine-X (Nginx) + MariaDB/MySQL + PHP. This guide installs the full stack to run a PHP site on a clean Ubuntu 22.04/24.04 server: Nginx, PHP-FPM, MariaDB, a virtual host (server block) and Let's Encrypt SSL.
sudo.
1. Nginx
sudo apt update
sudo apt install nginx -y
sudo systemctl enable --now nginx
If UFW already allows 80,443/tcp, opening the server's IP in a browser shows the Nginx welcome page.
2. MariaDB
sudo apt install mariadb-server -y
sudo systemctl enable --now mariadb
sudo mysql_secure_installation
In the mysql_secure_installation questions: Y for unix_socket auth for root, remove anonymous users, disable remote root login, remove the test database, reload privilege tables.
A database and user for the application
sudo mysql
CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'A_STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON app_db.* TO 'app_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
3. PHP-FPM
sudo apt install php-fpm php-mysql php-mbstring php-xml php-curl php-zip php-gd php-intl php-bcmath -y
Check the version (typically 8.3 on Ubuntu 24.04):
php -v
systemctl status php8.3-fpm
ondrej/php PPA:
sudo add-apt-repository ppa:ondrej/php then sudo apt install php8.2-fpm ...
4. A server block for the site
sudo mkdir -p /var/www/yoursite.com/public
sudo chown -R $USER:www-data /var/www/yoursite.com
/etc/nginx/sites-available/yoursite.com:
server {
listen 80;
server_name yoursite.com www.yoursite.com;
root /var/www/yoursite.com/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
sudo ln -s /etc/nginx/sites-available/yoursite.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Test
echo "<?php phpinfo();" | sudo tee /var/www/yoursite.com/public/info.php
http://yoursite.com/info.php should show the PHP info page. Delete it after testing: sudo rm /var/www/yoursite.com/public/info.php
5. DNS
Point your domain's A record at the server's IP address:
yoursite.com. A 203.0.113.10
www.yoursite.com. A 203.0.113.10
Wait for propagation (until dig yoursite.com +short returns the IP).
6. Free SSL (Let's Encrypt)
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yoursite.com -d www.yoursite.com
Certbot obtains the certificate, updates the Nginx config to HTTPS and adds a redirect. Auto-renewal is set up via certbot.timer; test:
sudo certbot renew --dry-run
Details: What is an SSL Certificate?
7. Tighten the settings
Typical settings in /etc/php/8.3/fpm/php.ini:
upload_max_filesize = 32M
post_max_size = 32M
memory_limit = 256M
max_execution_time = 60
date.timezone = Europe/Istanbul
sudo systemctl restart php8.3-fpm
Common problems
- 502 Bad Gateway: the PHP version in the
fastcgi_passpath does not match the installed version. Runls /run/php/to see the correct socket. - 403 Forbidden: the
rootdirectory is wrong or the permissions are off.www-datamust be able to read. - PHP file downloads instead of running: the
location ~ \.php$block is missing, ornginx -treports an error. - certbot "DNS problem": the A record has not propagated yet; verify with
digand try again.