Apache 2, PHP 8.4, MariaDB, phpMyAdmin setup

How to Install Apache, PHP, and MariaDB on Debian 13 (Trixie)

0 comment(s)

Revised guide for Debian 13. Native APT stack, no XAMPP, no third-party repository needed for PHP 8.4.

Target versions (official Debian 13 repositories):

Component Approximate version
Apache 2.4.x
PHP 8.4.x
MariaDB 11.8.x
phpMyAdmin 5.2.x

1. Introduction


1.1. Objective


Set up a local development platform with:

  • Apache2
  • PHP 8.4
  • MariaDB
  • phpMyAdmin

Each component is installed and verified before moving on to the next.

1.2. Why Avoid XAMPP?


XAMPP is handy for getting started, but it's not very flexible under Linux: changing PHP versions, integrating services with systemd, or aligning with Debian’s package management practices can become cumbersome.

On Debian 13, PHP 8.4, MariaDB 11.8, and Apache are already in the official repositories. No need for the Sury repository for this stack.

2. Environment Preparation


2.1. Check Your Debian Version


Bash
cat /etc/os-release

You should see VERSION_CODENAME=trixie (Debian 13).

2.2. Update Packages


Bash
sudo apt update && sudo apt upgrade -y

3. Installation of Main Services


3.1. Apache


Apache serves your HTTP pages on port 80 by default.

Install the package first, otherwise systemctl will return Unit apache2.service does not exist:

Bash
sudo apt install apache2 -y
sudo systemctl enable --now apache2
sudo systemctl status apache2 --no-pager

The status should indicate active (running).

Browser verification (default port 80): http://localhost/

If the Apache page doesn't appear:

Bash
sudo systemctl start apache2
sudo systemctl status apache2 --no-pager

Useful commands:

Bash
sudo systemctl stop apache2
sudo systemctl restart apache2
sudo systemctl reload apache2

3.1.1. Change HTTP port to 90 (optional)


An incalculable number of applications use port 80, which can lead to specific conflicts. If your Apache server starts after an application that already uses it, you may encounter issues.

On Debian, the port is configured in two places: global listening (ports.conf) and each Virtual Host. Do not change only one of them.

A. Global Listening:

Bash
sudo nano /etc/apache2/ports.conf

Replace:

Listen 80

with:

Listen 90

Leave Listen 443 as is if the SSL section is present (unnecessary for this local HTTP guide).

B. Default Virtual Host:

Bash
sudo nano /etc/apache2/sites-available/000-default.conf

Replace:

<VirtualHost *:80>

with:

<VirtualHost *:90>

C. Test the configuration, then reload:

Bash
sudo apache2ctl configtest
sudo systemctl reload apache2

configtest should display Syntax OK.

D. Check that port 90 is listening:

Bash
ss -tlnp | grep ':90'
  1. Browser access: http://localhost:90/

Use http://, not https://. Apache listens to plain HTTP on port 90. If the browser forces HTTPS (Firefox's HTTPS-Only mode, HSTS, etc.), you'll get an SSL_ERROR_RX_RECORD_TOO_LONG error. In this case: type explicitly http://localhost:90/ or temporarily disable HTTPS-Only for localhost.

From now on, all local URLs use port 90 (http://localhost:90/, http://localhost:90/info.php, http://localhost:90/phpmyadmin).

If you create other vhosts later, also put <VirtualHost *:90> (or the chosen port) in each site file.

3.2. MariaDB


MariaDB replaces MySQL in Debian repositories. The API remains compatible for most PHP projects.

Bash
sudo apt install mariadb-server -y
sudo systemctl enable --now mariadb
sudo systemctl status mariadb --no-pager

Secure the installation:

On Debian, MariaDB is already secured by default. The script also displays:

MariaDB is secure by default in Debian. Running this script is useless at best...

We still run it to clearly choose the root authentication mode:

Bash
sudo mariadb-secure-installation

Two options exist. Choose one, note your choice, and follow the instructions for Option A or Option B in the rest of the guide.

Option A β€” simple Option B β€” safer
root authentication SQL password unix_socket
Account for phpMyAdmin / apps root + password (no separate dev user) dev + password (created right after the script)
Terminal admin access mariadb -u root -p sudo mariadb
Create a dev user? No Yes (mandatory)

Warning β€” Option A.
Logging into phpMyAdmin (and possibly other apps) with root is the simplest path. It's also the least secure: a leaked root password equals access to all databases. This approach is fine for a personal local PC, but it’s less clean and poses more risks. Option B exists precisely for those who prefer never exposing root to the web.

Option A β€” root + password (simple)


Responses in mariadb-secure-installation:

Question Response
Current password for root Enter (blank)
Switch to unix_socket authentication n
Change the root password? Y β†’ choose a password and note it down
Remove anonymous users? Y
Disallow root login remotely? Y
Remove test database? Y
Reload privilege tables? Y

Check:

Bash
mariadb -u root -p

If Option A for the rest of the tutorial: use only root + this password (phpMyAdmin, PDO examples, etc.). Do not create an dev user.

Option B β€” unix_socket + dev user (more secure)


Responses in mariadb-secure-installation:

Question Response
Current password for root Enter (blank)
Switch to unix_socket authentication Y
Change the root password? N
Remove anonymous users? Y
Disallow root login remotely? Y
Remove test database? Y
Reload privilege tables? Y

Admin terminal (no SQL password for root) :

Bash
sudo mariadb

Why a dev user in Option B? phpMyAdmin can connect as root when root has an SQL password β€” that's Option A. In Option B, root is using unix_socket: MariaDB accepts root only if the Linux process is already root (sudo mariadb). Apache / phpMyAdmin run under www-data, so a web login as root fails. You need an SQL user with a password (dev).

Create immediately dev (web/app account for the rest of the tutorial if option B) :

SQL
CREATE USER 'dev'@'localhost' IDENTIFIED BY 'change_me_strong_password';
GRANT ALL PRIVILEGES ON *.* TO 'dev'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

Replace change_me_strong_password with a real password and note it down.

Verify:

Bash
mariadb -u dev -p

If you choose Option B for the rest of the tutorial: phpMyAdmin, PDO, etc. β†’ use dev + this password. Never use root from the web.

More restrictive variant (single database):

SQL
CREATE DATABASE mon_projet;
CREATE USER 'dev'@'localhost' IDENTIFIED BY 'change_me_strong_password';
GRANT ALL PRIVILEGES ON mon_projet.* TO 'dev'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Details of script questions (common to both options)


Enter current password for root
Current root password to allow the script. On a fresh Debian install: often empty β†’ Enter.

Switch to unix_socket authentication

  • n β†’ Option A (SQL password).
  • Y β†’ Option B (Linux socket / sudo).

Change the root password?

  • Option A: Y + set the password.
  • Option B: n (not needed daily with the socket).

Remove anonymous users? β†’ Y (unnecessary user accounts, regardless of mode)
Disallow root login remotely? β†’ Y (root access only locally; "disallow" = prevent remote access)
Remove test database? β†’ Y
Reload privilege tables? β†’ Y

On the machine where this guide was followed live: Option A (root simple, no dev). Option B is documented for those who choose it.

3.3. PHP 8.4


On Debian 13, PHP 8.4 is available natively. No Sury repository is required.

Bash
sudo apt install \
php8.4 \
php8.4-cli \
libapache2-mod-php8.4 \
php8.4-mysql \
php8.4-xml \
php8.4-mbstring \
php8.4-curl \
php8.4-zip \
php8.4-sqlite3 \
php8.4-gd \
php8.4-intl \
-y

Reload Apache to enable the PHP module:

Bash
sudo systemctl restart apache2

Check the CLI:

Bash
php -v

You should see a line like PHP 8.4.x.

Create a test file:

Bash
echo '<?php phpinfo();' | sudo tee /var/www/html/info.php

Open http://localhost:90/info.php, verify PHP 8.4, then delete the file:

Bash
sudo rm /var/www/html/info.php

Do not leave info.php in place outside of a trusted environment as it exposes server configuration.

3.4. phpMyAdmin


Mandatory order: install the package (Β§3.4.1) β†’ verify that the files exist β†’ only then enable Apache (Β§3.4.2). Without the package, /etc/phpmyadmin/apache.conf does not exist: a ln creates a broken link and a2enconf fails with Conf phpmyadmin does not exist!.

3.4.1. Installation


Bash
sudo apt update
sudo apt install phpmyadmin -y

During installation (debconf screens):

  1. Choose the web server: apache2 (Space to check, Tab, Enter).
  2. Should dbconfig-common configure the phpMyAdmin database? β†’ Yes. MariaDB is already installed; dbconfig-common will create for you the internal database and user that phpMyAdmin needs. Answer No only if you want to set everything up manually (unnecessary for a simple dev environment).
  3. Set a password for the MySQL/MariaDB user phpmyadmin (note it; this is not the same account as root or dev for connecting to the web interface).

Checkpoint β€” proceed to 3.4.2 only if this is OK:

Bash
dpkg -l phpmyadmin | grep '^ii'
ls -la /etc/phpmyadmin/apache.conf
  • The first command should show ii phpmyadmin
  • The second should list the file (not "No files")

If phpmyadmin is not ii, stop and reinstall (sudo apt install phpmyadmin -y) before configuring Apache.

3.4.2. Enable the Apache Configuration


Do this only after completing checkpoint Β§3.4.1.

The package provides /etc/phpmyadmin/apache.conf. Apache should load it via conf-available β†’ a2enconf.

Often, the installer has already created the link. Check:

Bash
ls -la /etc/apache2/conf-available/phpmyadmin.conf
  • If the file/link exists and points to /etc/phpmyadmin/apache.conf, activate and reload only:
Bash
sudo a2enconf phpmyadmin
sudo systemctl reload apache2
  • Otherwise, create the link (with backup if a file already occupies the name):
Bash
# Abort if the package config is missing (do not create a broken symlink)
test -f /etc/phpmyadmin/apache.conf || {
echo "ERROR: /etc/phpmyadmin/apache.conf missing β€” finish Β§3.4.1 first"
exit 1
}
# Keep a copy if a file already occupies that name
if [ -e /etc/apache2/conf-available/phpmyadmin.conf ]; then
sudo cp -a /etc/apache2/conf-available/phpmyadmin.conf \
/etc/apache2/conf-available/phpmyadmin.conf.bak
fi
sudo ln -sf /etc/phpmyadmin/apache.conf \
/etc/apache2/conf-available/phpmyadmin.conf
sudo a2enconf phpmyadmin
sudo systemctl reload apache2
  • test -f : blocks if the package is not present (avoids broken symlinks).
  • cp -a : true backup before replacement.
  • ln -sf : link to the package configuration.

3.4.3. Access


URL: http://localhost:90/phpmyadmin

  • If option A: login root + password from mariadb-secure-installation. No dev.
  • If option B: login dev + password created in Β§3.2.
    A web login root fails here because of unix_socket (in option A, root + pwd works).

3.4.4. User dev β€” reminder / repair (option B only)


If option A: skip this section. You remain on root.

If option B: dev was already created in Β§3.2. Here, just in case of forgetting or resetting the password:

Bash
sudo mariadb
SQL
CREATE USER 'dev'@'localhost' IDENTIFIED BY 'change_me_strong_password';
GRANT ALL PRIVILEGES ON *.* TO 'dev'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

Change the password for dev:

SQL
ALTER USER 'dev'@'localhost' IDENTIFIED BY 'new_password';
FLUSH PRIVILEGES;
EXIT;

A dedicated database (recommended for a project, always option B):

SQL
CREATE DATABASE mon_projet;
CREATE USER 'dev'@'localhost' IDENTIFIED BY 'change_me_strong_password';
GRANT ALL PRIVILEGES ON mon_projet.* TO 'dev'@'localhost';
FLUSH PRIVILEGES;
EXIT;

3.4.5 Troubleshooting Connection


Connect as admin:

Bash
# Si option A :
mariadb -u root -p
# Si option B :
sudo mariadb

List users:

SQL
SELECT User, Host, plugin FROM mysql.user;
  • If option A: root has a password plugin β†’ phpMyAdmin = root.
  • If option B: root generally has plugin = unix_socket β†’ phpMyAdmin = dev.

Change a password:

SQL
-- Si option A :
ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';
-- Si option B :
ALTER USER 'dev'@'localhost' IDENTIFIED BY 'new_password';
FLUSH PRIVILEGES;

Exit:

SQL
EXIT;

3.4.6 Quick Security (local)


For a local development machine, access via localhost is often sufficient. To restrict further, edit the Apache phpMyAdmin config and limit access, for example:

Require local

Then:

Bash
sudo systemctl reload apache2

4 PHP Configuration


4.1 Check Active Version


Bash
php -v
php -m

4.2 Multiple PHP Versions (optional)


If you install other branches later (e.g., via Sury for PHP 8.5), switch the CLI with:

Bash
sudo update-alternatives --display php
sudo update-alternatives --config php

For Apache mod_php, enable only one PHP module at a time:

Bash
# Example: switch from php8.4 to another installed version
sudo a2dismod php8.4
sudo a2enmod phpX.Y
sudo systemctl restart apache2

Replace phpX.Y with the actual installed version.

4.3 Apache php.ini File


Bash
sudo nano /etc/php/8.4/apache2/php.ini

After modification:

Bash
sudo systemctl restart apache2

Common local settings:

display_errors = On
error_reporting = E_ALL
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M

5 Essential Files


5.1 Apache


Role Path
Main configuration /etc/apache2/apache2.conf
Listening ports /etc/apache2/ports.conf
Document root /var/www/html/
Available sites /etc/apache2/sites-available/
Enabled sites /etc/apache2/sites-enabled/
Default vhost /etc/apache2/sites-available/000-default.conf
Access logs /var/log/apache2/access.log
Error logs /var/log/apache2/error.log

Enable / disable a vhost:

Bash
sudo a2ensite nom-du-site.conf
sudo a2dissite nom-du-site.conf
sudo systemctl reload apache2

5.2 PHP


Role Path
php.ini (Apache) /etc/php/8.4/apache2/php.ini
php.ini (CLI) /etc/php/8.4/cli/php.ini
Extensions see php -i | grep extension_dir

5.3 MariaDB


Role Path
Server configuration /etc/mysql/mariadb.conf.d/50-server.cnf
Data /var/lib/mysql/
Error logs /var/log/mysql/error.log

5.4 phpMyAdmin


Role Path
App configuration /etc/phpmyadmin/config.inc.php
Apache configuration /etc/phpmyadmin/apache.conf
Logs /var/log/apache2/error.log and access.log

6.Validation Checklist


Bash
# Services
systemctl is-active apache2
systemctl is-active mariadb
# Versions
apache2 -v
php -v
mariadb --version
# Ports
ss -tlnp | grep -E ':90|:3306'
  • http://localhost:90/ responds
  • Apache is listening on port 90 (not 80)
  • php -v displays 8.4.x
  • http://localhost:90/phpmyadmin opens
  • If option A: phpMyAdmin works with root + password (no dev)
  • If option B: user dev created (Β§3.2) and phpMyAdmin works with dev + password
  • info.php has been deleted

7. Characteristics of Debian 13


  • PHP 8.4 is native: no need for the Sury repository or deprecated apt-key.
  • MariaDB is at version 11.8, and the security script is called mariadb-secure-installation.
  • Apache remains at version 2.4, with familiar tools like a2enmod, a2ensite, and systemctl.
  • This guide uses port HTTP 90 (ports.conf + Virtual Host).
  • MariaDB: Option A = simple root (no dev); Option B = unix_socket + dev. Option B is available for those who prefer it based on warning A.

8. Possible Next Steps


For local projects with a custom domain name (monprojet.local), configure an Apache Virtual Host pointing to a dedicated folder (outside of /var/www/html if desired), then add the entry in /etc/hosts.

Detailed article here: Set Up an Apache VirtualHost on Debian 13 for Local PHP Projects

You may also like:

Comments

No approved comments yet.

Sign in with a commenter account to post a comment. Sign in.