A LAMP stack (Linux, Apache, MariaDB — the production replacement for MySQL, PHP) remains a solid, widely used foundation for hosting dynamic websites (WordPress, Laravel, custom PHP apps, etc.) on CentOS Stream.
In 2026, we focus on CentOS Stream 9 (or Stream 10 if you’re on the latest branch), using modern best practices: security hardening, performance tweaks, HTTPS by default, least-privilege principles, and production reliability.
Prerequisites
- Fresh CentOS Stream 9 (or 10) minimal install
- Root or sudo access
- Static IP or domain pointing to the server
- Firewall enabled (firewalld)
- At least 2 GB RAM, 2 vCPUs recommended for light production
Run all commands as root or with sudo.
Step 1: Update the System & Enable EPEL
Always start here for security patches and extra packages.
dnf update -y && dnf upgrade -y
dnf install epel-release -y
dnf update -yReboot if kernel was updated:
rebootStep 2: Install & Configure Apache (httpd)
dnf install httpd httpd-tools -yBasic production hardening in /etc/httpd/conf/httpd.conf (edit with vi or nano):
- Change ServerTokens Prod and ServerSignature Off (hide version info)
- Set Timeout 60, KeepAlive On, MaxKeepAliveRequests 100, KeepAliveTimeout 5
- In <Directory “/var/www/html”>, set Options -Indexes +FollowSymLinks (disable directory listing)
Enable and start:
systemctl enable --now httpdAllow HTTP/HTTPS in firewall:
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reloadTest: Open your server’s IP in a browser → you should see the Apache test page.
Step 3: Install & Secure MariaDB
CentOS Stream uses MariaDB (drop-in MySQL replacement).
dnf install mariadb-server -y
systemctl enable --now mariadbSecure the installation (very important for production):
mysql_secure_installationAnswer:
- Set root password? → Yes, strong password
- Remove anonymous users? → Yes
- Disallow root login remotely? → Yes (unless needed)
- Remove test database? → Yes
- Reload privilege tables? → Yes
Optional: Tune /etc/my.cnf.d/mariadb-server.cnf under [mysqld] for production:
innodb_buffer_pool_size = 512M # Adjust to ~60-70% of RAM if dedicated DB
max_connections = 100
innodb_log_file_size = 128MRestart MariaDB after changes:
systemctl restart mariadbStep 4: Install PHP (Recommended: PHP 8.2 or 8.3 for 2026)
CentOS Stream 9 ships PHP 8.0/8.1 by default in AppStream, but use the official remi repository for newer, secure versions (PHP 8.2 or 8.3 are still supported in 2026).
dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm -y
dnf module reset php -y
dnf module enable php:remi-8.3 -y # or php:remi-8.2 if you preferInstall PHP + essential extensions for most apps (WordPress, Laravel, etc.):
dnf install php php-fpm php-mysqlnd php-gd php-curl php-mbstring php-xml php-zip php-intl php-opcache php-bcmath php-json -yProduction PHP hardening in /etc/php.ini:
expose_php = Off
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300
date.timezone = Asia/Hong_Kong # Change to your timezoneEnable OPcache (big performance win):
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=1 # Set to 0 in very strict productionFor Apache integration, use mod_php (simple) or PHP-FPM (better performance/scalability).
Option A: mod_php (easier for small sites)
dnf install php php-common php-cli php-fpm php-mysqlnd ... # already doneRestart Apache:
systemctl restart httpdOption B: PHP-FPM (recommended for production)
systemctl enable --now php-fpmEdit /etc/httpd/conf.modules.d/10-php.conf (or create virtual host file) to proxy to FPM instead of mod_php.
Basic virtual host example /etc/httpd/conf.d/yourdomain.conf:
<VirtualHost *:80>
ServerName yourdomain.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost/"
</FilesMatch>
</VirtualHost>Enable mod_proxy_fcgi if needed:
dnf install mod_proxy_fcgi -yRestart services:
systemctl restart httpd php-fpmStep 5: Production Security Hardening Essentials
Enable HTTPS (mandatory in 2026)
Install Certbot:
Bashdnf install certbot python3-certbot-apache -yGet certificate:
Bashcertbot --apache -d yourdomain.com -d www.yourdomain.comAuto-renew works via cron.
SELinux (leave enforcing)
Restore contexts after changes:
Bashrestorecon -Rv /var/www/htmlFail2Ban (block brute-force attacks)
Bashdnf install fail2ban -y systemctl enable --now fail2banCreate jail for Apache & SSH.
Disable unused modules/services
Bashsystemctl disable --now avahi-daemon cupsRegular automatic updates (use dnf-automatic)
Bashdnf install dnf-automatic -yEdit /etc/dnf/automatic.conf → apply_updates = yes
Enable timer:
Bashsystemctl enable --now dnf-automatic-install.timerPermissions & ownership
Bashchown -R apache:apache /var/www/html find /var/www/html -type d -exec chmod 755 {} \; find /var/www/html -type f -exec chmod 644 {} \;
Step 6: Test the Full Stack
Create /var/www/html/info.php:
<?php phpinfo(); ?>Visit http://your-server-ip/info.php (or HTTPS) → should show PHP info.
Delete it afterward (security risk if left public).
For database test:
mysql -u root -p
CREATE DATABASE testdb;
EXIT;You’re now running a production-ready LAMP stack on CentOS Stream.
Ongoing Maintenance Tips
- Monitor logs: /var/log/httpd/, /var/log/mariadb/, /var/log/php-fpm/
- Backup regularly (database dumps + files)
- Use tools like clamav, lynis, or aide for extra scanning
- Consider migrating to Nginx + PHP-FPM for higher concurrency later
This setup balances security, performance, and ease of management for most production PHP sites in 2026. If you’re running a specific app (WordPress, Laravel, etc.), let me know for tailored tweaks! 🚀