Install Nginx, MySQL (or MariaDB) and PHP-FPM with apt, then add an Nginx server block that passes .php files to PHP-FPM.
8.5 wherever this article says 8.3. Replace example.com with your domain and 203.0.113.10 with your server's IP address.LEMP stands for Linux, Nginx ("engine-x"), MySQL and PHP. Connect to the server as a user with sudo rights (see Connect to your server with SSH). On a new server, do the basic security steps first: Secure a new Linux server: first 10 steps.
1. Install Nginx
sudo apt update
sudo apt install nginx
Open the web ports in the firewall (if UFW is on, see Set up a firewall with UFW on Ubuntu):
sudo ufw allow 'Nginx Full'
Open http://203.0.113.10 in your browser. You should see Welcome to nginx!
2. Install MySQL or MariaDB
Install one of the two, not both. Most PHP apps work with either.
sudo apt install mysql-server
or
sudo apt install mariadb-server
Check that it runs: sudo systemctl status mysql (MariaDB: sudo systemctl status mariadb) should show active (running). On Ubuntu, the database's root user logs in through the system's root account, without a password. Open the database console:
sudo mysql
Create a database and a user for your website (choose your own names and a strong password):
CREATE DATABASE example_db;
CREATE USER 'example_user'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON example_db.* TO 'example_user'@'localhost';
EXIT;
The database only listens on the server itself, which is what you want. Your website connects to localhost with this user.
3. Install PHP-FPM
Nginx doesn't run PHP itself: it hands PHP files to PHP-FPM. Install it with the MySQL extension:
sudo apt install php8.3-fpm php8.3-mysql
Most apps (WordPress, for example) also need a few common extensions:
sudo apt install php8.3-curl php8.3-gd php8.3-mbstring php8.3-xml php8.3-zip php8.3-intl
Check that PHP-FPM runs and find its socket, which Nginx needs in the next step:
sudo systemctl status php8.3-fpm
ls /run/php/
The list contains php8.3-fpm.sock.
4. Create the website in Nginx
Create the website's folder and make your user its owner:
sudo mkdir -p /var/www/example.com sudo chown -R $USER:$USER /var/www/example.comCreate the server block:
sudo nano /etc/nginx/sites-available/example.comPaste this, change the domain, then save with Ctrl+O, Enter, and close with Ctrl+X:
server { listen 80; listen [::]:80; server_name example.com www.example.com; root /var/www/example.com; index index.php index.html; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } location ~ /\.ht { deny all; } }Turn the site on, test the configuration and reload Nginx:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginxnginx -tmust say syntax is ok and test is successful. If this is the only site on the server, you can switch off the welcome page withsudo unlink /etc/nginx/sites-enabled/default(then test and reload again).
5. Test PHP
Create a test file:
echo '<?php phpinfo();' | sudo tee /var/www/example.com/info.php
Open http://example.com/info.php (or use the server's IP address if the domain doesn't point to the server yet and this is the only site). You should see the PHP information page with Server API: FPM/FastCGI and a mysqli section. Then delete the file, because it shows details attackers like to know:
sudo rm /var/www/example.com/info.php
6. Next steps
- Add free HTTPS: Install a free SSL certificate with Certbot.
- For WordPress and other apps with pretty links, change the line in
location /totry_files $uri $uri/ /index.php?$args;and reload Nginx. - Apps that save uploads or updates need write access for PHP, which runs as the user
www-data. Give it only the folders that need it, for examplesudo chown -R www-data:www-data /var/www/example.com/wp-content. - PHP settings are in
/etc/php/8.3/fpm/php.ini. After a change, runsudo systemctl restart php8.3-fpm. - Want phpMyAdmin? See Install phpMyAdmin on Ubuntu.
Common problems
502 Bad Gateway
Nginx can't reach PHP-FPM. Check that it runs (sudo systemctl status php8.3-fpm) and that the socket in fastcgi_pass matches the file in /run/php/. The error log /var/log/nginx/error.log shows the details.
The browser downloads the .php file instead of showing the page
The location ~ \.php$ block is missing or Nginx wasn't reloaded. Check the server block, run sudo nginx -t and sudo systemctl reload nginx, and clear your browser cache.
413 Request Entity Too Large when uploading
Nginx allows uploads of 1 MB by default. Add client_max_body_size 64M; to the server block, and raise upload_max_filesize and post_max_size in php.ini. Reload Nginx and restart PHP-FPM.
You still see the Welcome to nginx page
Your domain's request lands in the default site. Check that server_name contains the exact domain you open, that the link in sites-enabled exists, and reload Nginx.
Access denied for user when the app connects to the database
Check the database name, username and password in the app's settings, and that the host is localhost. Log in with sudo mysql and run the GRANT line again if needed.
Related articles
- Install a free SSL certificate with Certbot
- Set up a firewall with UFW on Ubuntu
- Install phpMyAdmin on Ubuntu
- Back up a server with rsync and cron
Still stuck? Open a support ticket and we'll help.