Install a LAMP stack on Debian 13 and Debian 12: Apache2, PHP 8, MariaDB and phpMyAdmin

Published on Updated on 7 min read

Apache2, PHP 8, MariaDB and phpMyAdmin on Debian 13 or Debian 12: the complete setup step by step, including hardening and troubleshooting.

Do you want to install Apache2, PHP 8, a MySQL database and phpMyAdmin, in other words a complete LAMP stack, on your Debian 13 (Trixie) or Debian 12 (Bookworm) server? This guide takes you through the whole setup step by step, from the web server to a secured database login.

Important note about the database server: Debian does not ship a mysql-server package, in no current release. On Debian you always install MariaDB. MariaDB grew out of MySQL, speaks the same protocol and the same query language, and tools such as phpMyAdmin or the PHP extension php-mysql work with it unchanged. So whenever this guide mentions MySQL databases, MariaDB is what runs underneath.

Requirements

You need SSH access with root privileges (or a user with sudo permissions) on a current Debian. Debian 13 "Trixie" and Debian 12 "Bookworm" are recommended. Debian 10 reached its end of support in June 2024 and no longer receives regular security updates, which makes it unsuitable for production use.

Start by refreshing the package list and installing the available updates:

apt update

apt upgrade -y

Install Apache2 and the base packages

Install the web server together with the helper packages you will need in the following steps:

apt install -y nano curl wget unzip ca-certificates apt-transport-https lsb-release gnupg apache2

Then open http://<your-server-IP>/ in your browser. If the Apache2 default page shows up, the web server is already running.

Install PHP 8

Which PHP version you get from the package sources depends on your distribution. That is why a command with a fixed version number such as apt install php8.4 fails on Debian 12, where only PHP 8.2 is available. This overview shows the version shipped by each release (as of July 2026):

DistributionPHP version from the package sources
Debian 13PHP 8.4
Debian 12PHP 8.2
Debian 11PHP 7.4

For that reason, use the meta packages without a version number. They automatically pull in the version that matches your distribution and behave the same way on every Debian:

apt install -y php php-cli php-common php-curl php-gd php-intl php-mbstring php-mysql php-opcache php-readline php-xml php-zip php-bz2 libapache2-mod-php

If you prefer to run PHP through FPM instead of the Apache module, the same principle applies. Here too the meta package gets you there reliably, while versioned names such as php8.4-fpm only exist on Debian 13:

apt install -y php-fpm

To see which version was actually installed, run:

php -v

If you need a version that your Debian release does not provide (PHP 8.4 on Debian 12, for example), add the PHP repository maintained by Ondřej Surý. The signing key is installed through its own keyring package and is tied to exactly this repository in the sources line via signed-by=:

curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb

dpkg -i /tmp/debsuryorg-archive-keyring.deb

echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/php.list

apt update

The once common route via apt-key add has been deprecated since Debian 11 and should no longer be used, because a key stored that way would be valid for every package source on the system.

Only this package source makes the versioned package names available across all Debian releases. After that you can install the PHP version you want together with the usual extensions:

apt install -y php8.4 php8.4-cli php8.4-common php8.4-curl php8.4-gd php8.4-intl php8.4-mbstring php8.4-mysql php8.4-opcache php8.4-readline php8.4-xml php8.4-zip php8.4-bz2 libapache2-mod-php8.4

If several PHP versions end up running side by side, define which one Apache2 should use:

a2dismod php8.2

a2enmod php8.4

systemctl restart apache2

Use php -v to check which version is active on the command line.

Install and secure MariaDB as the database server

As mentioned at the beginning, there is no mysql-server package on Debian. The database server is called MariaDB here, and the release depends on your Debian version:

DistributionDatabase server from the package sources
Debian 13MariaDB 11.8
Debian 12MariaDB 10.11
Debian 11MariaDB 10.5

Install the server and start the hardening step right after that:

apt install -y mariadb-server mariadb-client

mysql_secure_installation

The script asks several questions. Current MariaDB versions first ask whether to switch to unix_socket authentication. That option makes sense, because the database user root can then only log in as the system user root. Answer y to all remaining questions (remove anonymous users, disallow remote login for root, drop the test database, reload the privileges). Also set a strong database password.

Then check whether the service is running:

systemctl status mariadb

Install phpMyAdmin

You have two options for phpMyAdmin. The phpmyadmin package is part of the package sources in every current Debian version and can be installed in a single step:

apt install phpmyadmin -y

Convenient, but the version often lags behind what the developers currently ship. If you want the latest release, download phpMyAdmin directly instead. That is exactly the route the following steps take:

cd /usr/share && wget https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.zip -O phpmyadmin.zip && unzip phpmyadmin.zip && rm phpmyadmin.zip && mv phpMyAdmin-*-all-languages phpmyadmin && chmod -R 0755 phpmyadmin

Next, create the configuration file:

cp /usr/share/phpmyadmin/config.sample.inc.php /usr/share/phpmyadmin/config.inc.php

phpMyAdmin needs a random value as its blowfish_secret, which is used to encrypt the session data in the cookie. Generate such a value:

openssl rand -base64 32

Then enter it in the configuration file:

nano /usr/share/phpmyadmin/config.inc.php

The relevant line reads:

$cfg['blowfish_secret'] = 'ENTER_THE_GENERATED_VALUE_HERE';

Connect phpMyAdmin to Apache2

Create a dedicated Apache2 configuration file for phpMyAdmin:

nano /etc/apache2/conf-available/phpmyadmin.conf

The contents for phpmyadmin.conf:

#PHPMyAdmin Apache2 configuration

Alias /phpmyadmin /usr/share/phpmyadmin

<Directory /usr/share/phpmyadmin>
    Options SymLinksIfOwnerMatch
    DirectoryIndex index.php
</Directory>

<Directory /usr/share/phpmyadmin/templates>
    Require all denied
</Directory>
<Directory /usr/share/phpmyadmin/libraries>
    Require all denied
</Directory>
<Directory /usr/share/phpmyadmin/setup/lib>
    Require all denied
</Directory>

Enable the configuration, reload Apache2 and create the temporary directory with the right permissions:

a2enconf phpmyadmin && systemctl reload apache2 && mkdir -p /usr/share/phpmyadmin/tmp/ && chown -R www-data:www-data /usr/share/phpmyadmin/tmp/

Create a database user

Log in to the database as the system user root:

mysql -u root

Now create your own database user. Do not use "root", "admin", "user" or "username" as the name, pick a user name of your own and a long, random password:

#IMPORTANT! REPLACE USER AND PASSWORD WITH YOUR OWN CREDENTIALS.

CREATE USER 'USER'@'localhost' IDENTIFIED BY 'PASSWORD';

GRANT ALL PRIVILEGES ON *.* TO 'USER'@'localhost' WITH GRANT OPTION;

FLUSH PRIVILEGES;

For individual applications you should additionally create users with limited privileges that may only access their own database:

CREATE DATABASE myapp;

CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'PASSWORD';

GRANT ALL PRIVILEGES ON myapp.* TO 'appuser'@'localhost';

FLUSH PRIVILEGES;

You can leave the database console at any time with:

exit

Test the LAMP stack

Open phpMyAdmin at http://<your-server-IP>/phpmyadmin and log in with the user you just created. If the login works, Apache2, PHP and MariaDB are working together correctly.

You can also verify the PHP integration with a short test file:

echo "<?php phpinfo();" > /var/www/html/info.php

After opening http://<your-server-IP>/info.php, make sure you delete the file again, because it reveals details about your server configuration:

rm /var/www/html/info.php

Security notes for production use

A freshly installed LAMP stack is not secured yet. You should add these points:

  • phpMyAdmin is a popular target. Restrict access to your own IP address by using Require ip 203.0.113.10 in the Directory block instead of leaving it open to everyone.
  • Set up HTTPS so that passwords are not transmitted in clear text. Without encryption, your credentials can be read on the way to the server.
  • Keep phpMyAdmin up to date. Because you installed it manually, apt upgrade does not update it automatically.
  • Create regular database backups and store them off the server.

Common errors and how to fix them

The browser downloads the PHP file instead of running it: The PHP module is not active in Apache2. Enable it with a2enmod php8.4 and restart the web server with systemctl restart apache2.

phpMyAdmin reports "The configuration file now needs a secret passphrase": The value for blowfish_secret is missing in config.inc.php. Generate it with openssl rand -base64 32 and enter it there.

"Access denied for user" when logging in to phpMyAdmin: After mysql_secure_installation the database user root normally uses unix_socket authentication and therefore cannot log in through the web interface. Use the additional user you created.

Apache2 no longer starts after a configuration change: Check the configuration with apachectl configtest, the output names the file and line of the error.

Frequently asked questions

Why does Debian install MariaDB instead of MySQL?
No current Debian version contains a package called mysql-server. The database server it ships is MariaDB, a server that grew out of MySQL and uses the same protocol and the same query language. Debian 13 ships MariaDB 11.8, Debian 12 version 10.11 and Debian 11 version 10.5.
Which PHP version does Debian ship?
Debian 13 comes with PHP 8.4, Debian 12 with PHP 8.2 and Debian 11 still with PHP 7.4. For that reason, use the meta packages without a version number, so php and php-fpm. A command with a fixed number such as apt install php8.4 fails on Debian 12, where that package does not exist.
How do I get a newer PHP version than the one Debian provides?
Through the PHP repository maintained by Ondřej Surý. The signing key comes into the system as its own keyring package and is tied to exactly that package source via signed-by. Only then do versioned package names such as php8.4-fpm become available on every Debian release.
Why does the browser download the PHP file instead of running it?
In that case the PHP module is not active in Apache2. Enable it with a2enmod plus the name of your PHP version, for example a2enmod php8.4, then restart Apache2 with systemctl restart apache2.
Why can I not log in to phpMyAdmin as root?
After running mysql_secure_installation the database user root normally uses unix_socket authentication and therefore cannot log in through the web interface. Create your own database user for that purpose.

LAMP Apache2 PHP MariaDB MySQL phpMyAdmin Debian 13 Debian