LAMP Stack Installation (Linux, Apache, MySQL, PHP): Complete Production Guide

Introduction

The LAMP stack (Linux, Apache, MySQL, PHP) is one of the most popular and battle-tested web development platforms for hosting dynamic websites and web applications. This open-source software bundle has powered millions of websites worldwide, from small blogs to enterprise applications. The LAMP stack provides a robust, flexible, and cost-effective solution for web hosting that combines the stability of Linux, the reliability of Apache, the power of MySQL/MariaDB, and the versatility of PHP.

In this comprehensive guide, you'll learn how to install and configure a production-ready LAMP stack on Linux servers (Ubuntu/Debian and CentOS/Rocky Linux). We'll cover security hardening, performance optimization, best practices, and troubleshooting to ensure your web applications run efficiently and securely.

What You'll Learn

  • Complete LAMP stack installation on Ubuntu/Debian and CentOS/Rocky Linux
  • Apache web server configuration and virtual host setup
  • MySQL/MariaDB installation, security configuration, and optimization
  • PHP installation with multiple version support
  • Security hardening techniques and SSL/TLS certificate configuration
  • Performance tuning and optimization strategies
  • Monitoring and troubleshooting common issues
  • Production-ready configurations and best practices

Why Choose LAMP Stack?

The LAMP stack offers several compelling advantages:

  • Mature and Stable: Decades of development and testing
  • Extensive Community Support: Large community with abundant resources
  • Cost-Effective: All components are free and open-source
  • Flexibility: Easily customizable for various use cases
  • Wide Compatibility: Supports most PHP applications including WordPress, Drupal, Magento
  • Well-Documented: Extensive documentation and tutorials available
  • Enterprise-Ready: Used by major organizations worldwide

Prerequisites

Before beginning the LAMP stack installation, ensure you have:

System Requirements

  • Operating System: Ubuntu 20.04/22.04 LTS, Debian 10/11, CentOS 7/8, or Rocky Linux 8/9
  • RAM: Minimum 1GB (2GB+ recommended for production)
  • Disk Space: At least 10GB free space (20GB+ recommended)
  • CPU: 1+ cores (2+ cores recommended for production)
  • Network: Active internet connection for package downloads

Access Requirements

  • Root or sudo access to the server
  • SSH access to the server
  • Basic knowledge of Linux command line
  • Understanding of networking concepts (IP addresses, DNS, ports)

Pre-Installation Checklist

  1. Update system packages to latest versions
  2. Configure firewall rules to allow HTTP (80) and HTTPS (443)
  3. Set up DNS records pointing to your server
  4. Prepare domain names for virtual hosts
  5. Plan your directory structure for web applications

Installation

Step 1: System Update and Preparation

First, update your system packages to ensure you have the latest security patches and software versions.

For Ubuntu/Debian:

# Update package repository cache
sudo apt update

# Upgrade all installed packages
sudo apt upgrade -y

# Install essential utilities
sudo apt install -y curl wget vim git unzip software-properties-common

For CentOS/Rocky Linux:

# Update package repository cache
sudo dnf update -y

# Install EPEL repository (Extra Packages for Enterprise Linux)
sudo dnf install -y epel-release

# Install essential utilities
sudo dnf install -y curl wget vim git unzip

Step 2: Apache Web Server Installation

Apache HTTP Server is the A in LAMP, providing the web serving capabilities.

Ubuntu/Debian Installation:

# Install Apache web server
sudo apt install -y apache2

# Enable Apache to start on boot
sudo systemctl enable apache2

# Start Apache service
sudo systemctl start apache2

# Verify Apache is running
sudo systemctl status apache2

CentOS/Rocky Linux Installation:

# Install Apache (httpd package)
sudo dnf install -y httpd

# Enable Apache to start on boot
sudo systemctl enable httpd

# Start Apache service
sudo systemctl start httpd

# Verify Apache is running
sudo systemctl status httpd

Configure Firewall for Apache:

Ubuntu/Debian (UFW):

# Allow Apache through firewall
sudo ufw allow 'Apache Full'

# Verify firewall rules
sudo ufw status

CentOS/Rocky Linux (firewalld):

# Allow HTTP traffic
sudo firewall-cmd --permanent --add-service=http

# Allow HTTPS traffic
sudo firewall-cmd --permanent --add-service=https

# Reload firewall rules
sudo firewall-cmd --reload

# Verify firewall rules
sudo firewall-cmd --list-all

Verify Apache Installation:

Open your web browser and navigate to your server's IP address:

http://your_server_ip

You should see the Apache default welcome page.

Step 3: MySQL/MariaDB Installation

MySQL (or MariaDB) provides the database management system for the LAMP stack.

Ubuntu/Debian Installation:

# Install MariaDB server (recommended over MySQL)
sudo apt install -y mariadb-server mariadb-client

# Enable MariaDB to start on boot
sudo systemctl enable mariadb

# Start MariaDB service
sudo systemctl start mariadb

# Verify MariaDB is running
sudo systemctl status mariadb

CentOS/Rocky Linux Installation:

# Install MariaDB server
sudo dnf install -y mariadb-server mariadb

# Enable MariaDB to start on boot
sudo systemctl enable mariadb

# Start MariaDB service
sudo systemctl start mariadb

# Verify MariaDB is running
sudo systemctl status mariadb

Secure MySQL/MariaDB Installation:

Run the security script to remove default insecure settings:

sudo mysql_secure_installation

Follow the prompts:

  1. Set root password: Choose a strong password
  2. Remove anonymous users: Yes
  3. Disallow root login remotely: Yes (for security)
  4. Remove test database: Yes
  5. Reload privilege tables: Yes

Test MySQL/MariaDB Connection:

# Login to MySQL as root
sudo mysql -u root -p

# Once logged in, check version
SELECT VERSION();

# Exit MySQL
EXIT;

Step 4: PHP Installation

PHP is the scripting language that processes dynamic content in the LAMP stack.

Ubuntu/Debian Installation:

# Install PHP and common modules
sudo apt install -y php libapache2-mod-php php-mysql php-cli php-curl php-gd php-mbstring php-xml php-xmlrpc php-zip php-intl php-bcmath php-json php-soap

# Restart Apache to load PHP module
sudo systemctl restart apache2

# Verify PHP version
php -v

CentOS/Rocky Linux Installation:

# Install PHP and common modules
sudo dnf install -y php php-mysqlnd php-cli php-curl php-gd php-mbstring php-xml php-xmlrpc php-zip php-intl php-bcmath php-json php-soap

# Restart Apache to load PHP module
sudo systemctl restart httpd

# Verify PHP version
php -v

Test PHP Installation:

Create a PHP info file to verify PHP is working:

# Create PHP info file
sudo bash -c 'cat > /var/www/html/info.php <<EOF
<?php
phpinfo();
?>
EOF'

# Set proper permissions
sudo chmod 644 /var/www/html/info.php

Access the PHP info page in your browser:

http://your_server_ip/info.php

You should see detailed PHP configuration information.

Important: Remove the info.php file after verification for security:

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

Step 5: Verify LAMP Stack Installation

Create a simple PHP script that connects to MySQL to verify all components work together:

sudo bash -c 'cat > /var/www/html/test_db.php <<EOF
<?php
\$servername = "localhost";
\$username = "root";
\$password = "your_mysql_root_password";

// Create connection
\$conn = new mysqli(\$servername, \$username, \$password);

// Check connection
if (\$conn->connect_error) {
    die("Connection failed: " . \$conn->connect_error);
}
echo "LAMP Stack is working! PHP successfully connected to MySQL.";
\$conn->close();
?>
EOF'

Access the test script:

http://your_server_ip/test_db.php

Important: Delete this test file after verification:

sudo rm /var/www/html/test_db.php

Configuration

Apache Configuration

Main Configuration Files:

  • Ubuntu/Debian: /etc/apache2/apache2.conf
  • CentOS/Rocky: /etc/httpd/conf/httpd.conf

Configure Apache Virtual Hosts:

Virtual hosts allow you to host multiple websites on a single server.

Ubuntu/Debian Virtual Host:

# Create directory for your website
sudo mkdir -p /var/www/example.com/public_html

# Set ownership
sudo chown -R $USER:$USER /var/www/example.com/public_html

# Set permissions
sudo chmod -R 755 /var/www/example.com

# Create sample index page
cat > /var/www/example.com/public_html/index.html <<EOF
<!DOCTYPE html>
<html>
<head>
    <title>Welcome to Example.com</title>
</head>
<body>
    <h1>Success! The example.com virtual host is working!</h1>
</body>
</html>
EOF

# Create virtual host configuration
sudo bash -c 'cat > /etc/apache2/sites-available/example.com.conf <<EOF
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/example.com/public_html

    <Directory /var/www/example.com/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog \${APACHE_LOG_DIR}/example.com-error.log
    CustomLog \${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
EOF'

# Enable the virtual host
sudo a2ensite example.com.conf

# Enable mod_rewrite (for URL rewriting)
sudo a2enmod rewrite

# Test Apache configuration
sudo apache2ctl configtest

# Restart Apache
sudo systemctl restart apache2

CentOS/Rocky Virtual Host:

# Create directory for your website
sudo mkdir -p /var/www/example.com/public_html

# Set ownership
sudo chown -R apache:apache /var/www/example.com/public_html

# Set permissions
sudo chmod -R 755 /var/www/example.com

# Create sample index page
sudo bash -c 'cat > /var/www/example.com/public_html/index.html <<EOF
<!DOCTYPE html>
<html>
<head>
    <title>Welcome to Example.com</title>
</head>
<body>
    <h1>Success! The example.com virtual host is working!</h1>
</body>
</html>
EOF'

# Create virtual host configuration
sudo bash -c 'cat > /etc/httpd/conf.d/example.com.conf <<EOF
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/example.com/public_html

    <Directory /var/www/example.com/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog /var/log/httpd/example.com-error.log
    CustomLog /var/log/httpd/example.com-access.log combined
</VirtualHost>
EOF'

# Test Apache configuration
sudo httpd -t

# Restart Apache
sudo systemctl restart httpd

Apache Performance Tuning:

Edit the MPM (Multi-Processing Module) configuration:

Ubuntu/Debian:

sudo vim /etc/apache2/mods-available/mpm_prefork.conf

CentOS/Rocky:

sudo vim /etc/httpd/conf.modules.d/00-mpm.conf

Recommended MPM Prefork settings for a server with 2GB RAM:

<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers         10
    MaxRequestWorkers      150
    MaxConnectionsPerChild   3000
</IfModule>

MySQL/MariaDB Configuration

Main Configuration File:

  • Ubuntu/Debian: /etc/mysql/mariadb.conf.d/50-server.cnf
  • CentOS/Rocky: /etc/my.cnf.d/mariadb-server.cnf

Create Database and User:

# Login to MySQL
sudo mysql -u root -p

# Create database
CREATE DATABASE myapp_db;

# Create user with password
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'strong_password_here';

# Grant privileges
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';

# Flush privileges
FLUSH PRIVILEGES;

# Exit
EXIT;

MySQL Performance Tuning:

Edit MySQL configuration file and add these optimizations:

[mysqld]
# Basic settings
max_connections = 100
connect_timeout = 10
wait_timeout = 600
max_allowed_packet = 64M
thread_cache_size = 128
sort_buffer_size = 4M
bulk_insert_buffer_size = 16M
tmp_table_size = 32M
max_heap_table_size = 32M

# InnoDB settings (for 2GB RAM server)
innodb_buffer_pool_size = 512M
innodb_log_file_size = 128M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1

# Query cache (deprecated in newer versions)
query_cache_limit = 2M
query_cache_size = 64M

# Logging
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 2

Restart MySQL to apply changes:

sudo systemctl restart mariadb

PHP Configuration

Main Configuration File:

  • Ubuntu/Debian: /etc/php/8.x/apache2/php.ini
  • CentOS/Rocky: /etc/php.ini

Recommended PHP Settings:

Edit the php.ini file and adjust these settings:

# Memory and execution limits
memory_limit = 256M
max_execution_time = 300
max_input_time = 300
post_max_size = 64M
upload_max_filesize = 64M

# Error reporting (for production)
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
log_errors = On
error_log = /var/log/php_errors.log

# Security settings
expose_php = Off
allow_url_fopen = On
allow_url_include = Off

# Session settings
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1

# Timezone
date.timezone = America/New_York

# OPcache settings (performance)
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 60
opcache.fast_shutdown = 1

Restart Apache to apply PHP changes:

# Ubuntu/Debian
sudo systemctl restart apache2

# CentOS/Rocky
sudo systemctl restart httpd

Deployment

Deploying a PHP Application

Method 1: Manual Deployment

# Create application directory
sudo mkdir -p /var/www/myapp.com/public_html

# Upload your application files using SCP
scp -r /path/to/local/app/* user@server_ip:/var/www/myapp.com/public_html/

# Or use rsync for incremental updates
rsync -avz --progress /path/to/local/app/ user@server_ip:/var/www/myapp.com/public_html/

# Set proper ownership
sudo chown -R www-data:www-data /var/www/myapp.com/public_html  # Ubuntu/Debian
sudo chown -R apache:apache /var/www/myapp.com/public_html      # CentOS/Rocky

# Set proper permissions
sudo find /var/www/myapp.com/public_html -type d -exec chmod 755 {} \;
sudo find /var/www/myapp.com/public_html -type f -exec chmod 644 {} \;

Method 2: Git-Based Deployment

# Install git if not already installed
sudo apt install git -y  # Ubuntu/Debian
sudo dnf install git -y  # CentOS/Rocky

# Clone repository
cd /var/www/myapp.com
sudo git clone https://github.com/username/myapp.git public_html

# Set proper ownership
sudo chown -R www-data:www-data /var/www/myapp.com/public_html  # Ubuntu/Debian

# Configure automatic updates (optional)
cd /var/www/myapp.com/public_html
sudo git config --global --add safe.directory /var/www/myapp.com/public_html

Deploy WordPress Example:

# Download WordPress
cd /tmp
wget https://wordpress.org/latest.tar.gz

# Extract WordPress
tar -xzf latest.tar.gz

# Move to web directory
sudo mv wordpress/* /var/www/myapp.com/public_html/

# Create wp-config.php
sudo cp /var/www/myapp.com/public_html/wp-config-sample.php /var/www/myapp.com/public_html/wp-config.php

# Edit wp-config.php with database credentials
sudo vim /var/www/myapp.com/public_html/wp-config.php

# Set proper ownership
sudo chown -R www-data:www-data /var/www/myapp.com/public_html

# Set proper permissions
sudo find /var/www/myapp.com/public_html -type d -exec chmod 755 {} \;
sudo find /var/www/myapp.com/public_html -type f -exec chmod 644 {} \;

SSL/TLS Certificate Installation

Secure your site with Let's Encrypt free SSL certificates:

Ubuntu/Debian:

# Install Certbot
sudo apt install -y certbot python3-certbot-apache

# Obtain and install certificate
sudo certbot --apache -d example.com -d www.example.com

# Test automatic renewal
sudo certbot renew --dry-run

CentOS/Rocky:

# Install Certbot
sudo dnf install -y certbot python3-certbot-apache

# Obtain and install certificate
sudo certbot --apache -d example.com -d www.example.com

# Test automatic renewal
sudo certbot renew --dry-run

Certbot will automatically configure Apache for HTTPS and set up automatic renewal.

Monitoring

Apache Monitoring

Enable Apache Status Module:

Ubuntu/Debian:

# Enable status module
sudo a2enmod status

# Restart Apache
sudo systemctl restart apache2

CentOS/Rocky:

# Add to Apache configuration
sudo bash -c 'cat >> /etc/httpd/conf.d/status.conf <<EOF
<Location "/server-status">
    SetHandler server-status
    Require local
</Location>
EOF'

# Restart Apache
sudo systemctl restart httpd

Access server status:

http://localhost/server-status

Monitor Apache Logs:

# Real-time access log monitoring
sudo tail -f /var/log/apache2/access.log  # Ubuntu/Debian
sudo tail -f /var/log/httpd/access_log    # CentOS/Rocky

# Real-time error log monitoring
sudo tail -f /var/log/apache2/error.log   # Ubuntu/Debian
sudo tail -f /var/log/httpd/error_log     # CentOS/Rocky

# Analyze most requested URLs
awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20

# Analyze HTTP status codes
awk '{print $9}' /var/log/apache2/access.log | sort | uniq -c | sort -rn

# Analyze top visitor IPs
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20

MySQL/MariaDB Monitoring

Monitor Database Performance:

# Login to MySQL
sudo mysql -u root -p

# Show current processes
SHOW PROCESSLIST;

# Show database status
SHOW STATUS;

# Show InnoDB status
SHOW ENGINE INNODB STATUS\G

# Show slow queries
SHOW VARIABLES LIKE 'slow_query_log%';

# Monitor database connections
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';

Monitor MySQL Logs:

# View MySQL error log
sudo tail -f /var/log/mysql/error.log

# View slow query log
sudo tail -f /var/log/mysql/slow-query.log

# Analyze slow queries with mysqldumpslow
sudo mysqldumpslow -s t -t 10 /var/log/mysql/slow-query.log

PHP Monitoring

Monitor PHP Errors:

# View PHP error log
sudo tail -f /var/log/php_errors.log

# Monitor PHP-FPM status (if using PHP-FPM)
sudo systemctl status php7.4-fpm  # Ubuntu/Debian
sudo systemctl status php-fpm      # CentOS/Rocky

Check PHP OPcache Status:

Create a simple status script:

sudo bash -c 'cat > /var/www/html/opcache-status.php <<EOF
<?php
if (function_exists("opcache_get_status")) {
    \$status = opcache_get_status();
    echo "<pre>";
    print_r(\$status);
    echo "</pre>";
} else {
    echo "OPcache is not enabled";
}
?>
EOF'

Access: http://your_server_ip/opcache-status.php

Remember to delete this file after checking:

sudo rm /var/www/html/opcache-status.php

System Resource Monitoring

# Monitor CPU and memory usage
htop

# Monitor disk usage
df -h

# Monitor disk I/O
iostat -x 1

# Monitor network connections
netstat -tunlp

# Monitor Apache connections
netstat -an | grep :80 | wc -l

# Monitor MySQL connections
netstat -an | grep :3306 | wc -l

Automated Monitoring Script

Create a monitoring script:

sudo bash -c 'cat > /usr/local/bin/lamp-monitor.sh <<EOF
#!/bin/bash

echo "=== LAMP Stack Monitoring Report ==="
echo "Date: \$(date)"
echo ""

echo "=== Apache Status ==="
systemctl status apache2 | head -3 || systemctl status httpd | head -3
echo "Active connections: \$(netstat -an | grep :80 | wc -l)"
echo ""

echo "=== MySQL Status ==="
systemctl status mariadb | head -3
echo "Active connections: \$(netstat -an | grep :3306 | wc -l)"
echo ""

echo "=== Disk Usage ==="
df -h | grep -E "Filesystem|/dev/|/var"
echo ""

echo "=== Memory Usage ==="
free -h
echo ""

echo "=== Top Processes by CPU ==="
ps aux --sort=-%cpu | head -6
echo ""

echo "=== Top Processes by Memory ==="
ps aux --sort=-%mem | head -6
EOF'

# Make executable
sudo chmod +x /usr/local/bin/lamp-monitor.sh

# Run the script
sudo /usr/local/bin/lamp-monitor.sh

Troubleshooting

Apache Not Starting

Issue: Apache fails to start

Check error logs:

# Ubuntu/Debian
sudo journalctl -u apache2 -n 50
sudo tail -n 50 /var/log/apache2/error.log

# CentOS/Rocky
sudo journalctl -u httpd -n 50
sudo tail -n 50 /var/log/httpd/error_log

Common solutions:

  1. Port already in use:
# Check what's using port 80
sudo lsof -i :80
sudo netstat -tunlp | grep :80

# Kill the conflicting process or change Apache port
  1. Configuration syntax error:
# Test configuration
sudo apache2ctl configtest  # Ubuntu/Debian
sudo httpd -t               # CentOS/Rocky

# Fix syntax errors shown in output
  1. Missing SSL certificate:
# If SSL certificate is missing, temporarily disable SSL virtual host
sudo a2dissite example.com-ssl.conf  # Ubuntu/Debian

# Or comment out SSL virtual host in CentOS/Rocky

MySQL Connection Errors

Issue: "Can't connect to MySQL server"

Solutions:

  1. Check if MySQL is running:
sudo systemctl status mariadb
sudo systemctl start mariadb
  1. Check MySQL socket file:
# Find socket file location
mysql_config --socket

# Verify socket file exists
ls -l /var/run/mysqld/mysqld.sock

# If missing, restart MySQL
sudo systemctl restart mariadb
  1. Check firewall and bind-address:
# Edit MySQL configuration
sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf

# Ensure bind-address is set correctly
bind-address = 127.0.0.1  # For local connections only
# or
bind-address = 0.0.0.0    # For remote connections (less secure)

# Restart MySQL
sudo systemctl restart mariadb
  1. Verify user credentials:
# Login to MySQL
sudo mysql -u root -p

# Check user exists
SELECT User, Host FROM mysql.user;

# Grant proper privileges
GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'localhost';
FLUSH PRIVILEGES;

PHP Not Executing

Issue: PHP files download instead of executing

Solutions:

  1. Verify PHP module is loaded:
# Ubuntu/Debian
apache2ctl -M | grep php

# CentOS/Rocky
httpd -M | grep php

# If not loaded, enable PHP module
sudo a2enmod php7.4  # Ubuntu/Debian

# Restart Apache
sudo systemctl restart apache2  # Ubuntu/Debian
sudo systemctl restart httpd    # CentOS/Rocky
  1. Check Apache configuration:
# Ensure DirectoryIndex includes PHP files
# Add to Apache configuration or .htaccess:
DirectoryIndex index.php index.html

# Add PHP handler
AddHandler application/x-httpd-php .php
  1. Verify PHP installation:
php -v
php -m  # List PHP modules

Permission Errors

Issue: "403 Forbidden" or permission denied errors

Solutions:

  1. Set proper ownership:
# Ubuntu/Debian
sudo chown -R www-data:www-data /var/www/your_site

# CentOS/Rocky
sudo chown -R apache:apache /var/www/your_site
  1. Set proper permissions:
# Directories: 755
sudo find /var/www/your_site -type d -exec chmod 755 {} \;

# Files: 644
sudo find /var/www/your_site -type f -exec chmod 644 {} \;

# Writable directories (uploads, cache): 775
sudo chmod 775 /var/www/your_site/uploads
  1. Check SELinux (CentOS/Rocky):
# Check SELinux status
getenforce

# Set correct SELinux context
sudo chcon -R -t httpd_sys_content_t /var/www/your_site
sudo chcon -R -t httpd_sys_rw_content_t /var/www/your_site/uploads

# Or disable SELinux temporarily for testing
sudo setenforce 0

# To make permanent, edit /etc/selinux/config

High Memory Usage

Issue: Server running out of memory

Solutions:

  1. Optimize Apache MPM settings:
# Reduce MaxRequestWorkers in MPM configuration
# See Apache Performance Tuning section above
  1. Optimize MySQL memory usage:
# Reduce buffer pool size in MySQL configuration
innodb_buffer_pool_size = 256M  # Instead of 512M

# Restart MySQL
sudo systemctl restart mariadb
  1. Enable PHP OPcache:
# Verify OPcache is enabled in php.ini
opcache.enable = 1
opcache.memory_consumption = 128

# Restart Apache
sudo systemctl restart apache2  # Ubuntu/Debian
sudo systemctl restart httpd    # CentOS/Rocky
  1. Monitor and kill high-memory processes:
# Find memory-hungry processes
ps aux --sort=-%mem | head -10

# Kill specific process if necessary
sudo kill -9 PID

Slow Website Performance

Issue: Website loads slowly

Diagnostic steps:

  1. Check server load:
uptime
top
htop
  1. Analyze Apache access logs:
# Find slow requests
awk '$NF > 1000 {print $0}' /var/log/apache2/access.log | tail -20
  1. Identify slow MySQL queries:
# Enable slow query log
sudo mysql -u root -p

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;

# Check slow query log
sudo tail -f /var/log/mysql/slow-query.log
  1. Check PHP execution time:
# Add to PHP script for debugging
ini_set('display_errors', 1);
error_reporting(E_ALL);

$start = microtime(true);
// Your code here
$end = microtime(true);
echo "Execution time: " . ($end - $start) . " seconds";

Performance optimization:

  1. Enable caching (see Performance Tuning section)
  2. Optimize database queries and add indexes
  3. Enable compression (Gzip/Brotli)
  4. Use a CDN for static content
  5. Optimize images and assets
  6. Implement PHP OPcache
  7. Use Redis or Memcached for session storage

Security Best Practices

Apache Security Hardening

  1. Hide Apache version information:
# Edit Apache configuration
sudo vim /etc/apache2/conf-available/security.conf  # Ubuntu/Debian
sudo vim /etc/httpd/conf/httpd.conf                  # CentOS/Rocky

# Add or modify these lines
ServerTokens Prod
ServerSignature Off
  1. Disable directory listing:
# In virtual host configuration
Options -Indexes +FollowSymLinks
  1. Restrict access by IP (if needed):
<Directory /var/www/admin>
    Require ip 192.168.1.0/24
    Require ip 10.0.0.5
</Directory>
  1. Enable ModSecurity (Web Application Firewall):
# Ubuntu/Debian
sudo apt install -y libapache2-mod-security2

# Enable module
sudo a2enmod security2

# Restart Apache
sudo systemctl restart apache2

MySQL Security Hardening

  1. Disable remote root login:
sudo mysql -u root -p

DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
FLUSH PRIVILEGES;
  1. Use strong passwords:
# Set password policy
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 12;
  1. Regular backups:
# Create backup script
sudo bash -c 'cat > /usr/local/bin/mysql-backup.sh <<EOF
#!/bin/bash
DATE=\$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/mysql"
mkdir -p \$BACKUP_DIR
mysqldump -u root -p\$MYSQL_ROOT_PASSWORD --all-databases | gzip > \$BACKUP_DIR/all_databases_\$DATE.sql.gz
find \$BACKUP_DIR -type f -mtime +7 -delete
EOF'

sudo chmod +x /usr/local/bin/mysql-backup.sh
  1. Limit database user privileges:
# Grant only necessary privileges
GRANT SELECT, INSERT, UPDATE, DELETE ON database_name.* TO 'user'@'localhost';
# Avoid using GRANT ALL unless necessary

PHP Security Hardening

  1. Disable dangerous functions:
# Add to php.ini
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
  1. Configure file upload security:
# Add to php.ini
file_uploads = On
upload_max_filesize = 10M
max_file_uploads = 5

# In your PHP application, validate file types
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($_FILES['file']['type'], $allowed_types)) {
    die('Invalid file type');
}
  1. Use prepared statements for database queries:
// Bad (vulnerable to SQL injection)
$query = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "'";

// Good (using prepared statements)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute(['username' => $_POST['username']]);
  1. Enable open_basedir restriction:
# Add to php.ini or virtual host configuration
open_basedir = /var/www/your_site:/tmp

Firewall Configuration

  1. Configure UFW (Ubuntu/Debian):
# Enable firewall
sudo ufw enable

# Allow SSH
sudo ufw allow 22/tcp

# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Allow MySQL only from specific IP (if needed)
sudo ufw allow from 192.168.1.100 to any port 3306

# View rules
sudo ufw status verbose
  1. Configure firewalld (CentOS/Rocky):
# Enable firewall
sudo systemctl enable firewalld
sudo systemctl start firewalld

# Allow HTTP and HTTPS
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

# Allow MySQL only from specific IP (if needed)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="3306" protocol="tcp" accept'

# Reload firewall
sudo firewall-cmd --reload

# View rules
sudo firewall-cmd --list-all

Fail2Ban for Brute Force Protection

# Install Fail2Ban
sudo apt install -y fail2ban     # Ubuntu/Debian
sudo dnf install -y fail2ban     # CentOS/Rocky

# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Edit configuration
sudo vim /etc/fail2ban/jail.local

# Add Apache protection
[apache-auth]
enabled = true
port = http,https
logpath = /var/log/apache2/error.log
maxretry = 3
bantime = 3600

# Enable and start Fail2Ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# Check status
sudo fail2ban-client status

Performance Optimization

Enable Apache Caching

  1. Enable mod_cache:
# Ubuntu/Debian
sudo a2enmod cache
sudo a2enmod cache_disk
sudo a2enmod expires
sudo a2enmod headers

# Restart Apache
sudo systemctl restart apache2
  1. Configure caching in virtual host:
<VirtualHost *:80>
    # ... other configuration ...

    # Enable caching
    CacheEnable disk /
    CacheRoot /var/cache/apache2/mod_cache_disk
    CacheDefaultExpire 3600
    CacheMaxExpire 86400

    # Browser caching
    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresByType image/jpg "access plus 1 year"
        ExpiresByType image/jpeg "access plus 1 year"
        ExpiresByType image/gif "access plus 1 year"
        ExpiresByType image/png "access plus 1 year"
        ExpiresByType text/css "access plus 1 month"
        ExpiresByType application/javascript "access plus 1 month"
        ExpiresByType text/html "access plus 1 hour"
    </IfModule>
</VirtualHost>

Enable Gzip Compression

# Ubuntu/Debian
sudo a2enmod deflate

# Add to virtual host or .htaccess
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
    AddOutputFilterByType DEFLATE application/javascript application/json
    AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>

# Restart Apache
sudo systemctl restart apache2

MySQL Query Optimization

  1. Enable query cache:
# Add to MySQL configuration
query_cache_type = 1
query_cache_size = 64M
query_cache_limit = 2M
  1. Add indexes to frequently queried columns:
# Analyze slow queries
EXPLAIN SELECT * FROM table WHERE column = 'value';

# Add index if needed
CREATE INDEX idx_column ON table(column);

# View existing indexes
SHOW INDEX FROM table;
  1. Optimize tables regularly:
# Run optimization
sudo mysql -u root -p

OPTIMIZE TABLE table_name;

# Or optimize all tables in a database
mysqlcheck -u root -p --optimize database_name

PHP OPcache Configuration

OPcache caches compiled PHP code in memory, significantly improving performance:

# Verify OPcache is enabled
php -i | grep opcache

# Recommended OPcache settings in php.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=0

# Restart Apache
sudo systemctl restart apache2  # Ubuntu/Debian
sudo systemctl restart httpd    # CentOS/Rocky

Use Redis for Session Storage

Installing Redis for PHP session storage improves performance:

# Install Redis
sudo apt install -y redis-server php-redis  # Ubuntu/Debian
sudo dnf install -y redis php-redis         # CentOS/Rocky

# Configure PHP to use Redis for sessions
sudo vim /etc/php/8.x/apache2/php.ini

# Add these lines
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"

# Restart services
sudo systemctl restart redis
sudo systemctl restart apache2  # Ubuntu/Debian
sudo systemctl restart httpd    # CentOS/Rocky

Conclusion

You now have a fully functional, production-ready LAMP stack configured with security hardening, performance optimizations, and monitoring tools. This comprehensive setup provides a solid foundation for hosting PHP-based web applications ranging from simple websites to complex web platforms.

Key Takeaways

  • Security First: Always implement security best practices including SSL/TLS, strong passwords, firewall rules, and regular updates
  • Performance Matters: Enable caching, compression, and optimize database queries for better performance
  • Regular Monitoring: Set up monitoring tools and review logs regularly to catch issues early
  • Backup Everything: Implement automated backup strategies for both files and databases
  • Keep Updated: Regularly update all components (Linux, Apache, MySQL, PHP) for security patches
  • Documentation: Document your configuration and customizations for future reference

Next Steps

  1. Implement Automated Backups: Set up daily automated backups of your databases and web files
  2. Configure Monitoring: Install monitoring tools like Nagios, Zabbix, or use cloud-based solutions
  3. Set Up Staging Environment: Create a staging environment to test changes before production
  4. Implement CI/CD: Automate deployment with tools like Jenkins, GitLab CI, or GitHub Actions
  5. Consider High Availability: For critical applications, implement load balancing and database replication
  6. Performance Testing: Regularly perform load testing to identify bottlenecks
  7. Security Audits: Conduct regular security audits and vulnerability scans

Additional Resources

Support and Community

If you encounter issues or need help:

  • Stack Overflow: Search or ask questions about specific problems
  • Server Fault: For system administration questions
  • Apache Users Mailing List: For Apache-specific issues
  • MySQL Forums: For database-related questions
  • PHP Community: PHP.net and various PHP forums

The LAMP stack remains one of the most reliable and widely-adopted web hosting solutions. With proper configuration, security measures, and ongoing maintenance, your LAMP stack will provide years of reliable service for your web applications.

Happy deploying!