---
title: "Install latest Nginx, MariaDB, and PHP on Debian and Ubuntu"
tags: ['Debian', 'Ubuntu', 'Linux', 'PHP', 'Nginx', 'MariaDB', 'MySQL']
published: 2025-04-27 17:52:54
updated: 2026-07-06 00:00:00
excerpt: "Install latest Nginx, MariaDB, and PHP packages for a LEMP stack on Debian and Ubuntu."
---
> This file is the raw Markdown source of an m.ac post; the canonical version lives at https://m.ac/install-nginx-mariadb-php-debian-ubuntu/
> The full index of posts and pages is at https://m.ac/llms.txt — read the index first before crawling further.

This guide installs latest Nginx, MariaDB, and PHP packages for a LEMP stack on Debian and Ubuntu.

Updated July 6, 2026: PHP 8.5 and MariaDB 12.3 LTS.

## Introduction

When Debian prepares a new stable release, it uses a [freeze policy](https://release.debian.org/trixie/freeze_policy.html). Package versions are locked near release time, and they usually stay on that major version for the life of the release. Some packages get newer builds through [Debian backports](https://backports.debian.org/), but many do not.

That is fine for a lot of servers. For web apps that care about newer Nginx, MariaDB, or PHP features, it can be annoying. This guide uses trusted third-party repositories for those components while keeping the rest of the system on Debian or Ubuntu packages.

## 1. Prerequisites

Use [**Debian Stable**](https://www.debian.org/releases/) or **oldstable**. Debian **sid** is not supported here. On Ubuntu, use an [**Ubuntu LTS**](https://releases.ubuntu.com/) release rather than an interim release.

The commands below use `sudo`. If you prefer a root shell, run `sudo -i` first and drop `sudo` from the commands.

Update the system and install the tools needed to add APT repositories:

```bash
sudo apt update -y
sudo apt upgrade -y
sudo apt full-upgrade -y
sudo apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates -y
```

## 2. Install Nginx

[**N.WTF**](https://n.wtf/) syncs official Nginx source and packaging, then builds it with a current OpenSSL version.

### 2.1 Add GPG key

```bash
curl -sS https://n.wtf/public.key | sudo gpg --dearmor -o /usr/share/keyrings/n.wtf.gpg
```

### 2.2 Add repository

```bash
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror-cdn.xtom.com/sb/nginx/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/n.wtf.list
```

On Debian, [extrepo](/use-extrepo-add-third-party-repositories-debian/) can add the same repository:

```bash
sudo apt install extrepo -y
sudo extrepo enable n.wtf
```

### 2.3 Update system and install Nginx

```bash
sudo apt update
sudo apt install nginx-extras -y
```

Check that Nginx was installed:

```bash
root@debian ~ # nginx -v
nginx version: nginx-n.wtf/1.31.2
```

## 3. Install PHP

Use PHP packages from [Ondřej Surý](https://deb.sury.org/), who maintains widely used PHP builds for Debian and Ubuntu.

### 3.1 Add GPG key and repository

```bash
sudo wget -O /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php.list
```

Ondřej Surý rotates this GPG key roughly every two years. If `apt update` starts failing with a signature error, re-run the `wget` command above to fetch the current key.

On Debian, you can also use extrepo instead:

```bash
sudo extrepo enable sury
```

### 3.2 Install specific PHP version

Avoid installing broad `php-*` packages directly. They may pull a PHP version your application does not expect.

After adding the repository, update APT:

```bash
sudo apt update
```

Then install one specific PHP version and the extensions you need. This extension set works for a typical WordPress site:

Install PHP 8.5 (Opcache is enabled by default in PHP 8.5):

```bash
sudo apt install php8.5-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,soap,gmp,bcmath} -y
```

Install PHP 8.4

```bash
sudo apt install php8.4-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 8.3

```bash
sudo apt install php8.3-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 8.2

```bash
sudo apt install php8.2-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

The PHP versions below are EOL and are no longer officially supported.

Install PHP 8.1

```bash
sudo apt install php8.1-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 8.0

```bash
sudo apt install php8.0-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 7.4

```bash
sudo apt install php7.4-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 7.3

```bash
sudo apt install php7.3-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 7.2 (mcrypt was deprecated in PHP 7.1 and removed from core in 7.2)

```bash
sudo apt install php7.2-{fpm,cli,mysql,curl,gd,mbstring,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 7.1

```bash
sudo apt install php7.1-{fpm,cli,mysql,curl,gd,mbstring,mcrypt,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 7.0

```bash
sudo apt install php7.0-{fpm,cli,mysql,curl,gd,mbstring,mcrypt,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Install PHP 5.6

```bash
sudo apt install php5.6-{fpm,cli,mysql,curl,gd,mbstring,mcrypt,xml,zip,imap,opcache,soap,gmp,bcmath} -y
```

Search for any other PHP extensions your application needs:

```
apt search php8.5-*
```

Next, adjust the matching `php.ini` file:

-   For **PHP 8.5**, edit `/etc/php/8.5/fpm/php.ini`.
-   For **PHP 7.4**, edit `/etc/php/7.4/fpm/php.ini`.
-   For another version, change the version number in the path.

For PHP-FPM, disable `cgi.fix_pathinfo`:

This avoids an old class of path handling problems when Nginx passes requests to PHP-FPM.

```bash
sudo sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/' /etc/php/8.5/fpm/php.ini 
```

Adjust upload and post limits:

Change `upload_max_filesize` and `post_max_size` if your application needs larger uploads:

```bash
sudo sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 10M/' /etc/php/8.5/fpm/php.ini
sudo sed -i 's/post_max_size = 8M/post_max_size = 10M/' /etc/php/8.5/fpm/php.ini
```

If you install multiple PHP versions, choose the default CLI version with:

```bash
sudo update-alternatives --config php
```

Restart PHP-FPM after editing its configuration:

```bash
sudo systemctl restart php8.5-fpm
```

Now add an Nginx site configuration.

Create a new configuration file for your site under `/etc/nginx/sites-available/`:

```bash
sudo bash -c 'cat > /etc/nginx/sites-available/example.com.conf << EOF
server {
        listen 80;
        listen [::]:80;

# Web root, I recommend using /var/www
        root /var/www/example.com;
        index index.php index.html index.htm;

# Replace example.com with your domain name
        server_name example.com;

        location / {
            try_files \$uri \$uri/ =404;
        }

# Enable PHP 8.5-FPM. For PHP 7.4, use fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php8.5-fpm.sock;
        }
}
EOF'
```

Link it into `/etc/nginx/sites-enabled`:

```bash
sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf
```

Test the configuration and reload Nginx:

```bash
sudo nginx -t
sudo nginx -s reload
```

Create `/var/www/example.com` and make `www-data` the owner:

```bash
sudo mkdir -p /var/www/example.com
sudo chown www-data:www-data /var/www/example.com -R
```

Create `phpinfo.php` to test PHP:

```bash
sudo -u www-data bash -c 'cat > /var/www/example.com/phpinfo.php << EOF
<?php phpinfo(); ?>
EOF'
```

Visit `http://example.com/phpinfo.php` after the **A** or **AAAA** DNS records for `example.com` point to this server.

[![phpinfo page showing PHP 8.4 running with FPM/FastCGI on Debian](https://macdn.net/2026/07/07/m42tm/php8-4-phpinfo.webp)](https://macdn.net/2026/07/07/m42tm/php8-4-phpinfo.webp)

## 4. Install MariaDB

This setup uses MariaDB instead of MySQL for historical and licensing reasons.

### 4.1 Add GPG key

```bash
curl -sSL https://supplychain.mariadb.com/MariaDB-Server-GPG-KEY | sudo gpg --dearmor -o /usr/share/keyrings/mariadb.gpg
```

### 4.2 Add repository

Debian:

```bash
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/mariadb.gpg] https://dlm.mariadb.com/repo/mariadb-server/12.3/repo/debian $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/mariadb.list
```

Or use extrepo:

```bash
sudo extrepo enable mariadb-12.3
```

Ubuntu:

```bash
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/mariadb.gpg] https://dlm.mariadb.com/repo/mariadb-server/12.3/repo/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/mariadb.list
```

### 4.3 Install MariaDB

```bash
sudo apt update
sudo apt install mariadb-server mariadb-client -y
```

After installing MariaDB, run `sudo mariadb-secure-installation` if you want to set a root password and apply the usual basic hardening prompts.

### 4.4 Create database and test

Before creating a database, generate a random password. The `openssl` command works well:

```bash
openssl rand -hex 16
```

Or

```bash
openssl rand -base64 16
```

Or install `pwgen`:

```bash
sudo apt install pwgen -y
pwgen 16
```

Log in to MariaDB as `root`. By default, local root login uses Unix socket authentication, so you do not need a MariaDB root password:

```bash
sudo mariadb
```

Create an example database called `example_database`:

```sql
CREATE DATABASE example_database DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

Create an example user `example_user` and grant permissions:

```sql
GRANT ALL ON example_database.* TO 'example_user'@'localhost' IDENTIFIED BY 'Your_Powerful_Strong_Password';
FLUSH PRIVILEGES;
```

Exit MariaDB:

```sql
EXIT;
```

Create `mysql-test.php` in `/var/www/example.com`:

```bash
sudo -u www-data tee /var/www/example.com/mysql-test.php > /dev/null << 'EOF'
<?php
$dbname = 'example_database';    //MySQL database
$dbuser = 'example_user';   //MySQL user
$dbpass = 'Your_Powerful_Strong_Password';
$dbhost = 'localhost';  //use localhost if you install locally
$link = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");
mysqli_select_db($link, $dbname) or die("Could not open the db '$dbname'");
$test_query = "SHOW TABLES FROM $dbname";
$result = mysqli_query($link, $test_query);
$tblCnt = 0;
while($tbl = mysqli_fetch_array($result)) {
  $tblCnt++;
  #echo $tbl[0]."<br />\n";
}
if (!$tblCnt) {
  echo "MySQL is working fine. There are no tables.";
} else {
  echo "MySQL is working fine. There are $tblCnt tables.";
}
?>
EOF
```

The quoted `'EOF'` delimiter keeps the shell from touching anything inside, so the PHP lands on disk exactly as written.

Visit `http://example.com/mysql-test.php` to verify the database connection.

If the page shows `MySQL is working fine. There are no tables.`, PHP can connect to MariaDB.

Once both tests pass, delete the test files. `mysql-test.php` has your database password in it, and neither belongs on a public web root:

```bash
sudo rm /var/www/example.com/phpinfo.php /var/www/example.com/mysql-test.php
```
