Tools: Update: Installing the LEMP Stack on Ubuntu 26.04

Tools: Update: Installing the LEMP Stack on Ubuntu 26.04

Install Nginx

Install MySQL

Install PHP and PHP-FPM

Configure Firewall Rules

Configure a Virtual Host

Secure with Let's Encrypt SSL

Test the LEMP Stack

Next Steps The LEMP stack — Linux, Nginx, MySQL, and PHP — powers dynamic web applications with Nginx's high-concurrency architecture at the front and PHP-FPM's FastCGI process pool handling PHP execution. Ubuntu 26.04 ships with PHP 8.5, giving you a modern base to build on. This guide sets up a production-ready LEMP stack, secures it with a Let's Encrypt certificate, and verifies the full setup with a PHP page that reads from MySQL. By the end, you'll have a fully operational LEMP server ready to host web applications. 1. Update the APT package index: 3. Enable and start the service: 1. Install the MySQL server package: 2. Enable and start the service: 3. Run the security script: 4. Set the root password in the MySQL shell: PHP-FPM handles PHP execution through a FastCGI process pool, offering better isolation and performance than mod_php. 1. Install PHP and required extensions: What you just installed: 2. Enable and start PHP-FPM: 3. Verify the installed version: 1. Create the web root directory: 2. Create a test HTML page: 3. Create the virtual host configuration: 4. Enable the site, test the configuration, and reload: 1. Install Certbot with the Nginx plugin: 2. Generate and install the certificate: Certbot updates the virtual host to redirect HTTP to HTTPS automatically. 3. Test the auto-renewal timer: 1. Create the test database: 2. Create the PHP test page: 3. Visit the test page: Open https://app.example.com/test.php in a browser. The text LEMP stack is working! confirms Nginx, PHP, and MySQL are communicating correctly. 4. Remove the test file: The LEMP stack is now running and serving requests over HTTPS. From here you can: For the full guide with additional tips, visit the original article on Vultr Docs. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

$ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install nginx -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install nginx -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install nginx -y $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable nginx $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start nginx $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable nginx $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start nginx $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable nginx $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start nginx $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install mysql-server -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install mysql-server -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install mysql-server -y $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable mysql $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start mysql $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable mysql $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start mysql $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable mysql $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start mysql $ -weight: 600;">sudo mysql_secure_installation $ -weight: 600;">sudo mysql_secure_installation $ -weight: 600;">sudo mysql_secure_installation $ -weight: 600;">sudo mysql $ -weight: 600;">sudo mysql $ -weight: 600;">sudo mysql ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password'; FLUSH PRIVILEGES; EXIT; ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password'; FLUSH PRIVILEGES; EXIT; ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password'; FLUSH PRIVILEGES; EXIT; $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install php php-fpm php-mysql php-cli -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install php php-fpm php-mysql php-cli -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install php php-fpm php-mysql php-cli -y $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable php8.5-fpm $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start php8.5-fpm $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable php8.5-fpm $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start php8.5-fpm $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">enable php8.5-fpm $ -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start php8.5-fpm $ php --version $ php --version $ php --version $ -weight: 600;">sudo ufw allow 80/tcp $ -weight: 600;">sudo ufw allow 443/tcp $ -weight: 600;">sudo ufw allow 80/tcp $ -weight: 600;">sudo ufw allow 443/tcp $ -weight: 600;">sudo ufw allow 80/tcp $ -weight: 600;">sudo ufw allow 443/tcp $ -weight: 600;">sudo mkdir -p /var/www/app.example.com $ -weight: 600;">sudo chown -R www-data:www-data /var/www/app.example.com $ -weight: 600;">sudo mkdir -p /var/www/app.example.com $ -weight: 600;">sudo chown -R www-data:www-data /var/www/app.example.com $ -weight: 600;">sudo mkdir -p /var/www/app.example.com $ -weight: 600;">sudo chown -R www-data:www-data /var/www/app.example.com $ echo "<h1>Hello from LEMP on Ubuntu 26.04</h1>" | -weight: 600;">sudo tee /var/www/app.example.com/index.html $ echo "<h1>Hello from LEMP on Ubuntu 26.04</h1>" | -weight: 600;">sudo tee /var/www/app.example.com/index.html $ echo "<h1>Hello from LEMP on Ubuntu 26.04</h1>" | -weight: 600;">sudo tee /var/www/app.example.com/index.html $ -weight: 600;">sudo nano /etc/nginx/sites-available/app.example.com.conf $ -weight: 600;">sudo nano /etc/nginx/sites-available/app.example.com.conf $ -weight: 600;">sudo nano /etc/nginx/sites-available/app.example.com.conf server { listen 80; server_name app.example.com; root /var/www/app.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.5-fpm.sock; } access_log /var/log/nginx/app.example.com-access.log; error_log /var/log/nginx/app.example.com-error.log; } server { listen 80; server_name app.example.com; root /var/www/app.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.5-fpm.sock; } access_log /var/log/nginx/app.example.com-access.log; error_log /var/log/nginx/app.example.com-error.log; } server { listen 80; server_name app.example.com; root /var/www/app.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.5-fpm.sock; } access_log /var/log/nginx/app.example.com-access.log; error_log /var/log/nginx/app.example.com-error.log; } $ -weight: 600;">sudo ln -s /etc/nginx/sites-available/app.example.com.conf /etc/nginx/sites-enabled/ $ -weight: 600;">sudo nginx -t $ -weight: 600;">sudo -weight: 500;">systemctl reload nginx $ -weight: 600;">sudo ln -s /etc/nginx/sites-available/app.example.com.conf /etc/nginx/sites-enabled/ $ -weight: 600;">sudo nginx -t $ -weight: 600;">sudo -weight: 500;">systemctl reload nginx $ -weight: 600;">sudo ln -s /etc/nginx/sites-available/app.example.com.conf /etc/nginx/sites-enabled/ $ -weight: 600;">sudo nginx -t $ -weight: 600;">sudo -weight: 500;">systemctl reload nginx $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install certbot python3-certbot-nginx -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install certbot python3-certbot-nginx -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install certbot python3-certbot-nginx -y $ -weight: 600;">sudo certbot --nginx -d app.example.com --agree-tos $ -weight: 600;">sudo certbot --nginx -d app.example.com --agree-tos $ -weight: 600;">sudo certbot --nginx -d app.example.com --agree-tos $ -weight: 600;">sudo certbot renew --dry-run $ -weight: 600;">sudo certbot renew --dry-run $ -weight: 600;">sudo certbot renew --dry-run $ mysql -u root -p $ mysql -u root -p $ mysql -u root -p CREATE DATABASE lemp_test; CREATE USER 'lemp_user'@'localhost' IDENTIFIED BY 'secure_password'; GRANT ALL PRIVILEGES ON lemp_test.* TO 'lemp_user'@'localhost'; USE lemp_test; CREATE TABLE greetings (id INT AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255)); INSERT INTO greetings (message) VALUES ('LEMP stack is working!'); FLUSH PRIVILEGES; EXIT; CREATE DATABASE lemp_test; CREATE USER 'lemp_user'@'localhost' IDENTIFIED BY 'secure_password'; GRANT ALL PRIVILEGES ON lemp_test.* TO 'lemp_user'@'localhost'; USE lemp_test; CREATE TABLE greetings (id INT AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255)); INSERT INTO greetings (message) VALUES ('LEMP stack is working!'); FLUSH PRIVILEGES; EXIT; CREATE DATABASE lemp_test; CREATE USER 'lemp_user'@'localhost' IDENTIFIED BY 'secure_password'; GRANT ALL PRIVILEGES ON lemp_test.* TO 'lemp_user'@'localhost'; USE lemp_test; CREATE TABLE greetings (id INT AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255)); INSERT INTO greetings (message) VALUES ('LEMP stack is working!'); FLUSH PRIVILEGES; EXIT; $ -weight: 600;">sudo nano /var/www/app.example.com/test.php $ -weight: 600;">sudo nano /var/www/app.example.com/test.php $ -weight: 600;">sudo nano /var/www/app.example.com/test.php <?php $conn = new mysqli('localhost', 'lemp_user', 'secure_password', 'lemp_test'); if ($conn->connect_error) { die('Connection failed: ' . $conn->connect_error); } $result = $conn->query('SELECT message FROM greetings'); while ($row = $result->fetch_assoc()) { echo $row['message']; } $conn->close(); ?> <?php $conn = new mysqli('localhost', 'lemp_user', 'secure_password', 'lemp_test'); if ($conn->connect_error) { die('Connection failed: ' . $conn->connect_error); } $result = $conn->query('SELECT message FROM greetings'); while ($row = $result->fetch_assoc()) { echo $row['message']; } $conn->close(); ?> <?php $conn = new mysqli('localhost', 'lemp_user', 'secure_password', 'lemp_test'); if ($conn->connect_error) { die('Connection failed: ' . $conn->connect_error); } $result = $conn->query('SELECT message FROM greetings'); while ($row = $result->fetch_assoc()) { echo $row['message']; } $conn->close(); ?> $ -weight: 600;">sudo rm /var/www/app.example.com/test.php $ -weight: 600;">sudo rm /var/www/app.example.com/test.php $ -weight: 600;">sudo rm /var/www/app.example.com/test.php - php: core PHP interpreter - php-fpm: FastCGI Process Manager for Nginx - php-mysql: MySQL driver for PHP database connections - php-cli: command-line PHP interpreter - Deploy WordPress or Laravel on this stack - Add phpMyAdmin for a browser-based database management interface - Enable HTTP/2 in Nginx by adding http2 to the listen directive