How to Install LAMP Stack on CentOS Stream 10

Install LAMP stack on CentOS Stream 10 with Apache, MariaDB, PHP-FPM, firewalld, SELinux-safe permissions, verification, and fixes on a fresh VPS.
A polished 3D server rack with glowing web, database, and PHP components on a midnight-blue background with an orange accent.

Install LAMP stack on CentOS Stream 10 with Apache, MariaDB, and PHP-FPM in about 10–15 minutes. You will finish with a boot-persistent web server, a locally secured database, and a disposable PHP test that proves the full stack is processing requests.

Prerequisites

  • A fresh CentOS Stream 10 VPS with at least 1 GB of RAM and 10 GB of free disk space.
  • SSH access as root, or a normal user with working sudo privileges.
  • A public IPv4 address if the website must be reachable from the internet; use SERVER_IP in the examples.
  • A domain such as YOUR_DOMAIN is optional for this base setup, but needed before you configure a trusted HTTPS certificate.
  • If you need the server, choose a VPSLake Linux VPS with root access and CentOS Stream 10.

Step 1: Update CentOS Stream and install the stack

Updating the package metadata first prevents an old cache from causing dependency errors, and the native AppStream packages keep the installation aligned with this release.

sudo dnf update -y
sudo dnf install -y httpd firewalld mariadb-server mariadb php php-cli php-fpm php-mysqlnd php-gd php-mbstring php-opcache curl

Start the services and enable them for future boots. PHP-FPM is the FastCGI process manager used by the EL10 family, so Apache can hand PHP requests to a separate, managed service.

sudo systemctl enable --now firewalld httpd mariadb php-fpm
sudo systemctl is-active firewalld httpd mariadb php-fpm

Expected output is four active lines:

active
active
active
active

CentOS Stream follows the Enterprise Linux 10 PHP-FPM model described in the official PHP and Apache documentation.

Step 2: Allow web traffic through firewalld

The daemons can be healthy while the site remains unreachable because the host firewall still blocks incoming connections. Keep SSH open, then allow only the web services needed for a normal HTTP-to-HTTPS deployment.

sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --list-services

The final command should include ssh, http, and https, along with any services already enabled by your VPS image:

cockpit dhcpv6-client http https ssh

Do not add the mysql service or TCP port 3306. A PHP application on this same VPS can use MariaDB locally, and keeping the database off the public network removes an unnecessary attack surface. If SSH uses a custom port, allow that port before reloading the firewall instead of relying on the ssh service definition.

Step 3: Confirm Apache before adding PHP code

A local configuration check separates Apache problems from firewall and PHP problems, so test the web server before changing application files.

sudo apachectl configtest
curl -I http://127.0.0.1/

You should see a valid configuration followed by a successful response:

Syntax OK
HTTP/1.1 200 OK

The response headers and date vary. From another computer, open http://SERVER_IP/; the default Apache page should load. If the local request works but the browser cannot connect, return to Step 2 and check the VPS provider’s separate network firewall.

Step 4: Secure and verify MariaDB

The MariaDB hardening script removes anonymous accounts and test data while restricting administrative access to the local machine.

sudo mariadb-secure-installation

Answer the prompts to remove anonymous users, disallow remote root login, remove the test database, and reload the privilege tables. On current MariaDB packages, the root@localhost account commonly uses Unix-socket authentication; accept that secure option instead of inventing a database root password unless your application specifically requires password-based administration.

Test the local client and print the server version:

sudo mariadb -e "SELECT VERSION() AS mariadb_version;"
sudo mariadb -e "SHOW DATABASES;"

The first query returns a mariadb_version value. The second should list system databases such as information_schema, mysql, and performance_schema. See the MariaDB secure-installation documentation for the purpose of each hardening prompt.

Step 5: Test PHP through PHP-FPM

The PHP packages provide the interpreter and MariaDB driver, while PHP-FPM executes .php requests without requiring the older embedded Apache PHP module.

Check the installed release and the important database modules, then restart the two services so Apache loads the PHP configuration:

php -v
php -m | grep -E 'mysqli|mysqlnd|PDO|pdo_mysql'
sudo systemctl restart php-fpm httpd

The version is controlled by the enabled CentOS Stream 10 repositories. The module check should include mysqli, mysqlnd, PDO, and pdo_mysql.

Create a harmless test page, request it locally, and remove it immediately after the check. This confirms PHP execution without publishing the detailed server settings shown by phpinfo().

printf '%s\n' '<?php echo "PHP is working\\n"; ?>' | sudo tee /var/www/html/stack-test.php >/dev/null
curl -fsS http://127.0.0.1/stack-test.php
sudo rm -f /var/www/html/stack-test.php

Expected output:

PHP is working

Verify the LAMP stack

Run the final checks together to prove that systemd, Apache, PHP-FPM, and MariaDB are all responding:

sudo systemctl is-active httpd php-fpm mariadb
curl -fsS http://127.0.0.1/
sudo mariadb -e "SELECT VERSION() AS mariadb_version;"

The service check should return three active lines. curl should return the Apache welcome page or your own index content, and the SQL query should return a version value. Before deploying a login page or other sensitive application, point YOUR_DOMAIN to the VPS and configure HTTPS.

Troubleshooting

Job for httpd.service failed

Apache found a malformed configuration file, commonly a typo in a virtual-host or PHP handler file. Read the exact error, fix the named file, and validate again before restarting.

sudo apachectl configtest
sudo journalctl -u httpd -n 40 --no-pager
sudo systemctl restart httpd

curl works locally but the site times out remotely

Apache is listening, but firewalld or the VPS provider’s external firewall is blocking the request. Confirm the services and listening sockets, then allow HTTP and HTTPS without exposing MariaDB.

sudo firewall-cmd --zone=public --list-services
sudo ss -ltnp | grep -E ':(80|443)\b'
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload

If port 80 is listening locally and the rules are present, allow TCP 80 and 443 in the VPS control panel’s network firewall as well.

The browser downloads PHP or displays PHP source

Apache is treating the file as static content because PHP-FPM is stopped or its handler was not loaded. Check the service and the PHP-specific Apache configuration, then restart both services.

sudo systemctl status php-fpm --no-pager
sudo test -f /etc/httpd/conf.d/php.conf && echo 'PHP-FPM Apache config found'
sudo journalctl -u php-fpm -n 40 --no-pager
sudo systemctl restart php-fpm httpd

Do not solve this by disabling SELinux or installing an obsolete PHP module; fix the service or the configuration reported by the logs.

Access denied for user 'root'@'localhost'

This usually means MariaDB is using Unix-socket authentication, which is normal on a fresh installation. Run local administrative queries through sudo mariadb rather than forcing -u root -p.

sudo mariadb -e "SELECT USER(), CURRENT_USER();"

For an application, create a separate database user with only the permissions it needs instead of changing the root account.

Hardening

  • Replace the default Apache page with a named virtual host for YOUR_DOMAIN, then install a trusted certificate and redirect HTTP to HTTPS.
  • Keep MariaDB on localhost unless a separate application server needs access; if remote access is necessary, restrict it to a specific source address and use TLS.
  • Keep website files readable rather than writable by everyone. For files copied into /var/www/html, restore the default SELinux labels with sudo restorecon -Rv /var/www/html.
  • Review the complete firewall state with sudo firewall-cmd --zone=public --list-all after adding each service.

FAQ

Is MariaDB a replacement for MySQL in a PHP application?

MariaDB supports the MySQL client protocol and the common PHP database APIs used by many applications. Check the application’s compatibility matrix before using a feature that depends on a specific MySQL release.

Do I need to open port 3306 for PHP?

No. When PHP and MariaDB run on one VPS, the application can connect through the local socket or loopback interface. Open 3306 only for a documented remote client, and restrict the source instead of allowing the whole internet.

Which PHP version does CentOS Stream 10 install?

The enabled Stream 10 repositories determine the available version and point releases. Run php -v after installation rather than hard-coding a version that may change during the release lifecycle.

Can I use the default Apache page in production?

It is useful for the first connectivity test, but it is not a finished website configuration. Replace it with a virtual host, application files, HTTPS, and an application-specific database user before launch.

Samrat Ghosh
Written by

Samrat Ghosh

Founder & Infrastructure Engineer

Samrat Ghosh is the founder of VPSLake, where he builds and runs the remote desktop and VPS hosting infrastructure the company is built on. He writes hands-on guides about RDP, Windows Server, VPS management and secure remote access - the practical documentation he wishes had…

Previous Article

How to Rent a Server in 2026: VPS or Dedicated?

Write a Comment

Leave a Comment

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

Subscribe to our Newsletter

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨