October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk11 min

How to Set Up a LEMP Stack With Nginx on a Linux VPS

A release-aware, step-by-step guide to installing Nginx, MariaDB, PHP-FPM and UFW on an Ubuntu or Debian VPS, configuring PHP through FastCGI, securing the database and firewall, and adding HTTPS.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A LEMP stack on a fresh Linux VPS consists of Linux, Nginx, a MySQL-compatible database such as MariaDB, and PHP running through PHP-FPM. The reliable setup sequence is: create a non-root sudo account, update the server, install Nginx, MariaDB, PHP-FPM, the PHP database extension and UFW, verify the locally installed PHP-FPM socket, configure an Nginx server block, harden the database and firewall, then add HTTPS after DNS points to the VPS.

The commands below target Ubuntu or Debian systems. Package names, service names and PHP-FPM socket paths vary by release, so treat version-specific values as local settings to discover rather than strings to copy blindly.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What a LEMP stack does

LEMP is Linux, Nginx, a MySQL- or MariaDB-compatible database, and PHP. Nginx handles connections and static files, then forwards requests for dynamic PHP pages to PHP-FPM over FastCGI. PHP executes the application code and uses MariaDB or MySQL for persistent data. Keeping those roles separate makes it possible to serve static assets efficiently while isolating application and database access.

Nginx uses server blocks, the equivalent of Apache virtual hosts, to map one or more hostnames to different site directories. A single VPS can therefore host one site with a simple configuration or several sites with separate blocks, roots, logs and PHP settings.

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.

Prerequisites and release caveats

  • A fresh Ubuntu or Debian VPS with a public IPv4 address, and IPv6 if you intend to serve it.
  • SSH access using a key, plus a separate non-root account with sudo privileges.
  • A domain name or fully qualified domain name (FQDN) whose DNS record will point to the VPS address.
  • Permission to change both the provider’s network firewall and the VPS’s host firewall.
  • A maintenance window for package installation and any reboot requested by the provider.

Published tutorials cover very different releases, including Ubuntu 18.04-era instructions, Debian 10 and Ubuntu 20.04 examples, and an Ubuntu 26.04 walkthrough. Their PHP versions, service names and socket filenames are not interchangeable. Use the current package metadata for your release and inspect the installed files before editing Nginx.

Confirm the distribution before installing

cat /etc/os-release

Record the release name and architecture. If the image is not Ubuntu or Debian, stop and use that distribution’s package and service documentation; the commands in this guide intentionally use the apt and ufw conventions common to Ubuntu and Debian.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install the packages

1. Connect and update

From your workstation, connect as the provisioning user (replace the example address and account):

ssh [email protected]

Update package indexes and already-installed packages before adding the web stack:

sudo apt update
sudo apt upgrade -y

Reboot if the package manager or your VPS provider indicates that a kernel or core library requires it, then reconnect over SSH.

2. Install Nginx, MariaDB, PHP-FPM, the database extension and UFW

On a standard Ubuntu or Debian repository configuration, the complete installation can be performed with:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo apt install -y ufw nginx mariadb-server php-fpm php-mysql

php-fpm resolves to the release’s default PHP-FPM package. php-mysql supplies the mysqli and PDO MySQL drivers used by many applications. If an application requires additional extensions, install only the modules it documents, such as a matching XML, GD, mbstring or curl package.

3. Enable and start services

Packages often start services automatically, but verify and enable them for boot:

Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.
sudo systemctl enable --now nginx
sudo systemctl enable --now mariadb
sudo systemctl enable --now php-fpm

Some distributions expose PHP-FPM under a versioned unit, such as php8.3-fpm, instead of the generic alias. Find the installed unit rather than guessing:

systemctl list-unit-files | grep -E 'php.*fpm'
systemctl list-units --type=service | grep -E 'php.*fpm'

Then enable the unit shown on your server, for example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo systemctl enable --now php8.3-fpm

Check each service and read its status output for startup errors:

systemctl status nginx --no-pager
systemctl status mariadb --no-pager
systemctl status php8.3-fpm --no-pager

Find the correct PHP-FPM socket

Nginx must send FastCGI requests to the Unix socket created by the PHP-FPM package. The filename normally contains the installed PHP major and minor version, so an old example such as php7.2-fpm.sock may be wrong on a current system.

List sockets provided by the running service:

sudo find /run/php -maxdepth 1 -type s -printf '%fn'

You can also inspect the FPM pool configuration:

grep -R '^listens*=' /etc/php/*/fpm/pool.d/

Copy the exact result, for example /run/php/php8.3-fpm.sock, into the Nginx fastcgi_pass directive later. If the directory is empty, the FPM service is not running or its pool configuration has an error; check journalctl -u php8.3-fpm before configuring Nginx.

Harden MariaDB before connecting an application

Run the vendor hardening assistant

Run the program supplied by MariaDB or your distribution:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo mysql_secure_installation

Follow its prompts to remove anonymous accounts, prevent unnecessary remote administrative access, remove the test database and reload privilege tables. The exact questions vary by MariaDB release. Do not enable remote database administration merely because a prompt offers it.

Create a database and least-privilege account

Do not put the database administrator credentials in a web application. Log in locally as an administrator and create a database plus a user restricted to that database:

Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by
sudo mariadb
CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'replace-with-a-long-random-password';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Use a password generated by a password manager, not the example text. Keep MariaDB listening on localhost unless a deliberate architecture requires remote connections. If remote access is necessary, restrict the bind address, source IPs and firewall rules, and use encrypted connections according to the database documentation.

Configure UFW without locking yourself out

Allow your existing SSH path before enabling UFW. The rule name below matches the standard OpenSSH profile:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo ufw allow 'OpenSSH'
sudo ufw allow 'Nginx HTTP'
sudo ufw enable
sudo ufw status verbose

For HTTPS, add the secure web profile after you are ready to serve TLS:

sudo ufw allow 'Nginx HTTPS'

If your SSH daemon uses a non-standard port, allow that port explicitly before enabling the firewall. The VPS provider’s firewall is separate from UFW; permit TCP 22 (or your chosen SSH port), 80 and 443 in the provider panel as well. Do not open the MariaDB port to the public internet for a local-only database.

Create the site directory and permissions

Use a directory named for the domain:

sudo mkdir -p /var/www/example.com/public
sudo chown -R $USER:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 755 {} ;
sudo find /var/www/example.com -type f -exec chmod 644 {} ;

The web server needs to read the document tree. Applications that upload files or write caches need a narrowly scoped writable directory; do not make the entire site world-writable. Decide whether deployments happen as your account, a dedicated release user or a CI system, and keep ownership consistent.

Create a temporary static file to verify the first request:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
printf '%sn' '<h1>Nginx is serving example.com</h1>' | sudo tee /var/www/example.com/public/index.html

Write an Nginx server block for PHP

Create the configuration in sites-available:

sudo nano /etc/nginx/sites-available/example.com

Replace the domain and socket path with your own values:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com/public;
    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;
    }
}

The distribution’s snippets/fastcgi-php.conf normally sets the request parameters and safely constructs the script filename. If your release stores the snippet elsewhere, locate the packaged file and use its documented path. The .ht deny rule prevents legacy Apache files such as .htaccess from being downloaded if they are accidentally placed in the document root.

Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.

Enable the block and remove a conflicting default

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

Run nginx -t before every reload. If the test reports a duplicate server name, a syntax error or a missing include, correct that output before reloading. Keep the default site enabled only when it does not compete with the hostnames in your intended configuration.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Verify static files, PHP and the database

Test the HTTP response

curl -I http://example.com

A working static site should return an HTTP status such as 200 (or the intentional redirect status you configured). If DNS is not ready, test locally with the VPS address and a Host header:

curl -I -H 'Host: example.com' http://203.0.113.10

Test PHP-FPM with a temporary page

cat <<'PHP' | sudo tee /var/www/example.com/public/info.php
<?php
phpinfo();
PHP

Open http://example.com/info.php. The page should be rendered as HTML by PHP, not offered as a download. Confirm that the displayed PHP version and loaded modules match the packages installed on this VPS.

Delete this file immediately after testing because it reveals paths, versions and environment details:

sudo rm /var/www/example.com/public/info.php

Test an application database connection

Use the application’s documented configuration format and the separate account created earlier. A minimal PDO check, saved temporarily outside a public directory when possible, is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<?php
$pdo = new PDO(
    'mysql:host=127.0.0.1;dbname=appdb;charset=utf8mb4',
    'appuser',
    getenv('APP_DB_PASSWORD'),
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
echo 'Database connection succeeded';

Do not hard-code production passwords in a web-accessible file. Remove diagnostic scripts after the connection test and verify that the real application’s migrations or health check can create and read the expected tables.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Add HTTPS after DNS resolves

Point the domain’s A and, if used, AAAA records at the VPS and wait until public DNS resolves to the correct address. Obtain a certificate from a certificate authority with a client such as Certbot, following the client instructions for your distribution and Nginx. The client generally validates the HTTP site, writes the certificate configuration and can add an HTTP-to-HTTPS redirect.

Before requesting the certificate, confirm that TCP 80 is reachable; the common HTTP validation method needs it. Permit HTTPS in both firewalls:

sudo ufw allow 'Nginx HTTPS'udo ufw status

After the client updates Nginx, inspect the resulting server blocks rather than assuming the redirect is correct. Test both hostnames:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -I http://example.com
curl -I https://example.com

Check renewal using the client’s dry-run or equivalent test command, then schedule and monitor its timer or cron job. A certificate that works today but is never renewed will eventually take the site offline.

Troubleshoot the common failures

Symptom Likely cause Checks and fix
Nginx will not start or reload Syntax error, duplicate host, or port 80 already occupied Run sudo nginx -t; inspect sudo ss -ltnp | grep ':80'; stop or reconfigure Apache or another process using the port.
502 Bad Gateway PHP-FPM is stopped or fastcgi_pass points at the wrong socket Check the versioned FPM service with systemctl status, list /run/php, compare the exact socket path, then reload Nginx.
PHP source downloads or appears as text The PHP location block or FastCGI include is absent or not matched Confirm location ~ .php$, the distribution snippet and the installed FPM socket; run nginx -t.
Static files work but the domain times out DNS points elsewhere or a provider/UFW firewall blocks the port Check A and AAAA records, test with the VPS IP and Host header, and permit ports 80 and 443 at both firewall layers.
SSH disappears after enabling UFW The actual SSH port was not allowed Use the provider console or recovery access, allow the correct port, then reload UFW. Always add the SSH rule first on future installations.
Database connection is refused Wrong host, credentials, permissions or service state Check systemctl status mariadb, verify the database and user grants, and use localhost or 127.0.0.1 consistently with the application’s connection method.

Production hardening and operations

  • Keep the operating system, Nginx, PHP, PHP extensions and MariaDB patched through the distribution’s security updates.
  • Use SSH keys, disable routine root login, and limit SSH exposure to trusted source addresses where practical.
  • Back up both the database and application files. Test restoring a backup on a separate location; a backup that has never been restored is only an assumption.
  • Monitor disk space, memory, CPU, certificate expiry and service health. Log rotation should prevent Nginx, PHP-FPM and MariaDB logs from filling the volume.
  • Review Nginx access/error logs, the PHP-FPM journal and MariaDB logs when an application fails rather than exposing errors to visitors.
  • Keep secrets outside the public document root and restrict file permissions. Rotate credentials when staff, deployment systems or providers change.
  • Tune PHP-FPM worker counts, database buffers and caching only after measuring the workload. There is no universal throughput figure for a generic LEMP installation.

Choosing the components and layout

Ubuntu or Debian

Choice Strength Important trade-off
Ubuntu Broad VPS documentation and packages that are familiar to many administrators Exact PHP defaults and support lifetime depend on the Ubuntu release; an older image can provide an outdated runtime.
Debian Conservative, stable base with predictable major-release maintenance Packages may lag newer upstream versions, so applications needing a newer PHP release require a deliberate repository strategy.

For either distribution, use the current supported release offered by your provider and apply security updates. Do not infer a socket name or service unit from a tutorial written for another release.

MariaDB or MySQL

Both implement the MySQL client and protocol expectations used by many PHP applications, but defaults, release cadence and administration tools differ. Choose the database already supported by your application, your team’s operational experience and the backup tooling available from the VPS provider. Whichever you select, create a separate application account and keep the service private unless remote access is required.

Distribution Nginx packages or an upstream repository

Distribution packages simplify security updates, dependency management and integration with the operating system. An official upstream Nginx repository can expose a newer release, but it adds repository trust and upgrade decisions. Pick one source deliberately; mixing packages from several repositories complicates rollback and support.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

One site or multiple server blocks

A single site can use one focused block and one document root. Multiple sites should have one block per hostname, separate roots and, when appropriate, separate Unix users and PHP-FPM pools. Keep each block independently testable, and ensure no broad default block accidentally catches traffic intended for another domain.

Final pre-launch checklist

  1. DNS A/AAAA records resolve to the intended VPS.
  2. The non-root sudo account works with SSH keys.
  3. Nginx, MariaDB and the correct versioned PHP-FPM service are enabled and running.
  4. The PHP-FPM socket in fastcgi_pass exists locally.
  5. The server block has the correct server_name, document root and PHP include.
  6. sudo nginx -t succeeds before each reload.
  7. UFW and the provider firewall allow SSH, HTTP and HTTPS, but not an unnecessary public database port.
  8. Anonymous database access and test data are removed, and the application uses a dedicated database user.
  9. Temporary phpinfo() and connection-test files are deleted.
  10. HTTPS works, HTTP redirects as intended, and certificate renewal has been tested.
  11. Backups, monitoring, log review and a recovery procedure are in place.

Frequently Asked Questions

Which PHP-FPM socket should I put in Nginx?

Use the socket created by the PHP-FPM package on that VPS. List sockets with sudo find /run/php -maxdepth 1 -type s -printf '%fn' and copy the full path into fastcgi_pass; do not assume a filename from an older tutorial.

Can I expose MariaDB so another server can connect?

Only when the architecture requires it. Keep the database bound locally by default. If remote access is necessary, restrict the bind address, source IPs, database grants and firewall rules, and configure encrypted transport.

Why does PHP download instead of execute?

Nginx is not matching PHP requests or is missing the distribution FastCGI include, or PHP-FPM is unavailable. Check the PHP location block, the include path, the installed socket and the FPM service status.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.