What is LAMP?
LAMP is a powerful, time-tested open-source web development platform that powers millions of websites worldwide. The acronym represents four key components that work together to create dynamic, database-driven web applications.
The Components
Stable, secure operating system
Industry-leading web server
Robust database management
Dynamic content processing
Why LAMP?
- Battle-Tested: Powers major platforms like WordPress, Drupal, and countless enterprise applications
- Open Source: Completely free with strong community support and extensive documentation
- Flexible: Suitable for everything from personal blogs to high-traffic e-commerce sites
- Well-Supported: Extensive libraries, frameworks, and tools available
- Performance: Optimized for speed with mature caching and optimization solutions
What You'll Build
By the end of this guide, you'll have a fully functional web server capable of:
- Serving static and dynamic web content via Apache
- Processing PHP scripts for dynamic page generation
- Managing data with MySQL/MariaDB databases
- Hosting multiple websites with virtual hosts
- Running popular CMS platforms like WordPress or Drupal
Perfect For: This stack is ideal for web developers, system administrators, and anyone looking to host their own web applications. Whether you're building a personal blog, development environment, or production server, LAMP provides a solid foundation.
System Preparation
Before installing the LAMP stack components, we need to prepare the system and ensure it's up to date.
Update System Packages
First, update your package lists and upgrade existing packages:
# Update package lists
sudo apt update
# Upgrade installed packages
sudo apt upgrade -y
# Install essential tools
sudo apt install -y curl wget git nano software-properties-common apt-transport-https ca-certificates
Best Practice: Always update your system before installing new software to ensure you get the latest security patches and bug fixes.
Set System Hostname (Optional)
If you're setting up a production server, configure a proper hostname:
# Set hostname
sudo hostnamectl set-hostname lamp-server
# Edit hosts file
sudo nano /etc/hosts
# Add this line (replace with your IP):
# 192.168.1.100 lamp-server.local lamp-server
Configure Firewall with iptables
Set up iptables for robust network security:
# Install iptables-persistent to save rules
sudo apt install -y iptables-persistent
# Flush existing rules (clean slate)
sudo iptables -F
sudo iptables -X
sudo iptables -Z
# Set default policies
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
# Allow loopback interface
sudo iptables -A INPUT -i lo -j ACCEPT
# Allow established and related connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow SSH (port 22) - CRITICAL: Don't skip this!
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow HTTP (port 80)
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# Allow HTTPS (port 443)
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow ping (ICMP)
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# Log dropped packets (optional, useful for debugging)
sudo iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-DROP: " --log-level 7
# Save the rules
sudo netfilter-persistent save
# Verify rules
sudo iptables -L -v -n
Critical: Always configure SSH access (port 22) before setting the default INPUT policy to DROP, or you will lock yourself out of remote systems!
iptables Management: View rules: sudo iptables -L -v -n | Save rules: sudo netfilter-persistent save | Reload rules: sudo netfilter-persistent reload
Verify System Resources
Ensure your system meets the minimum requirements:
# Check available memory
free -h
# Check disk space
df -h
# Check CPU info
lscpu
Step 1: Install Apache Web Server
Apache HTTP Server is the most widely-used web server software. It's reliable, powerful, and highly configurable.
Installation
# Install Apache
sudo apt install -y apache2
# Start Apache service
sudo systemctl start apache2
# Enable Apache to start on boot
sudo systemctl enable apache2
# Check status
sudo systemctl status apache2
Verify Installation
Test that Apache is running correctly:
# Check Apache version
apache2 -v
# Test configuration syntax
sudo apache2ctl configtest
# Test from command line
curl http://localhost
Open your web browser and navigate to http://your-server-ip. You should see the Apache default page.
Success Indicator: If you see the "Apache2 Debian Default Page" with the message "It works!", Apache is installed correctly and serving content.
Important Apache Directories
| Directory | Purpose |
|---|---|
/var/www/html/ |
Default web root directory |
/etc/apache2/ |
Apache configuration files |
/etc/apache2/sites-available/ |
Virtual host configurations |
/etc/apache2/sites-enabled/ |
Enabled virtual hosts (symlinks) |
/var/log/apache2/ |
Apache log files |
Enable Essential Apache Modules
Enable commonly used modules for enhanced functionality:
# Enable mod_rewrite (URL rewriting)
sudo a2enmod rewrite
# Enable mod_ssl (HTTPS support)
sudo a2enmod ssl
# Enable mod_headers (HTTP headers control)
sudo a2enmod headers
# Restart Apache to apply changes
sudo systemctl restart apache2
Module Explanation: mod_rewrite is essential for clean URLs and many CMS platforms. mod_ssl enables HTTPS connections. mod_headers allows you to modify HTTP response headers for security and caching.
Basic Apache Commands
# Start Apache
sudo systemctl start apache2
# Stop Apache
sudo systemctl stop apache2
# Restart Apache (full restart)
sudo systemctl restart apache2
# Reload configuration (no downtime)
sudo systemctl reload apache2
# Check syntax of config files
sudo apache2ctl configtest
# View Apache status
sudo systemctl status apache2
Step 2: Install MySQL/MariaDB
MySQL is a powerful relational database management system. On Debian 12, you can choose between MySQL or MariaDB (a MySQL fork). We'll use MariaDB as it's the default in Debian repositories.
Installation
# Install MariaDB server and client
sudo apt install -y mariadb-server mariadb-client
# Start MariaDB service
sudo systemctl start mariadb
# Enable MariaDB to start on boot
sudo systemctl enable mariadb
# Check status
sudo systemctl status mariadb
MySQL vs MariaDB: MariaDB is a drop-in replacement for MySQL, developed by MySQL's original creators. It's fully compatible with MySQL and offers better performance in many scenarios.
Secure MySQL Installation
Run the security script to improve MySQL security:
sudo mysql_secure_installation
Answer the prompts as follows:
- Enter current password for root: Press Enter (no password set yet)
- Switch to unix_socket authentication: N (No)
- Change the root password: Y (Yes) - Enter a strong password
- Remove anonymous users: Y (Yes)
- Disallow root login remotely: Y (Yes)
- Remove test database: Y (Yes)
- Reload privilege tables: Y (Yes)
Security Critical: Always set a strong root password and remove anonymous users. Never allow root remote login in production environments.
Verify Installation
# Check MariaDB version
mysql --version
# Login to MySQL (as root)
sudo mysql -u root -p
# Once logged in, try these commands:
SHOW DATABASES;
SELECT VERSION();
EXIT;
Create a Database and User
Create a sample database and user for your applications:
# Login to MySQL
sudo mysql -u root -p
# Create a database
CREATE DATABASE myapp_db;
# Create a user with password
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'secure_password';
# Grant privileges
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';
# Flush privileges
FLUSH PRIVILEGES;
# Verify
SHOW DATABASES;
SELECT User, Host FROM mysql.user;
# Exit
EXIT;
Best Practice: Create separate database users for each application with only the privileges they need. Never use the root account for application connections.
Basic MySQL Commands
# Start MySQL
sudo systemctl start mariadb
# Stop MySQL
sudo systemctl stop mariadb
# Restart MySQL
sudo systemctl restart mariadb
# Check MySQL status
sudo systemctl status mariadb
# View MySQL logs
sudo journalctl -u mariadb -n 50
Step 3: Install PHP
PHP is the scripting language that processes your dynamic content. Debian 12 includes PHP 8.2, which offers significant performance improvements and modern features.
Installation
Install PHP along with essential modules:
# Install PHP and common extensions
sudo apt install -y php php-cli php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-xmlrpc php-zip php-intl
# Restart Apache to load PHP module
sudo systemctl restart apache2
PHP Extensions Explained
| Extension | Purpose |
|---|---|
php-cli |
Command-line PHP interpreter |
php-mysql |
MySQL/MariaDB database connectivity |
php-curl |
HTTP requests and API calls |
php-gd |
Image processing and manipulation |
php-mbstring |
Multibyte string handling (internationalization) |
php-xml |
XML parsing and processing |
php-zip |
ZIP archive handling |
Verify PHP Installation
# Check PHP version
php -v
# View loaded PHP modules
php -m
# Check PHP configuration
php -i | grep "Configuration File"
Configure PHP
Edit the PHP configuration file to optimize settings:
# Edit PHP configuration for Apache
sudo nano /etc/php/8.2/apache2/php.ini
Recommended changes for better performance and security:
# Find and modify these directives:
# Maximum execution time for scripts (seconds)
max_execution_time = 300
# Maximum file upload size
upload_max_filesize = 64M
post_max_size = 64M
# Memory limit per script
memory_limit = 256M
# Timezone (change to yours)
date.timezone = Europe/Paris
# Display errors (disable in production!)
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
Production Security: Always set display_errors = Off in production environments. Displaying errors can expose sensitive information about your server configuration.
Restart Apache
After modifying PHP settings, restart Apache:
sudo systemctl restart apache2
Check PHP Integration with Apache
# Verify PHP module is loaded
apache2ctl -M | grep php
# Should show: php_module (shared)
Testing Your LAMP Stack
Now let's verify that all components are working together correctly.
Test 1: PHP Info Page
Create a PHP info page to verify PHP is processing correctly:
# Create PHP info file
sudo nano /var/www/html/info.php
Add this content:
<?php
phpinfo();
?>
Save and exit (Ctrl+X, Y, Enter), then visit http://your-server-ip/info.php in your browser.
What to Look For: You should see a detailed page showing PHP version, loaded extensions, configuration settings, and environment variables. This confirms PHP is working with Apache.
Security: Delete this file after testing! It exposes sensitive server information.
sudo rm /var/www/html/info.php
Test 2: PHP-MySQL Connection
Create a test script to verify PHP can connect to MySQL:
# Create test script
sudo nano /var/www/html/dbtest.php
Add this content (replace with your database credentials):
<?php
// Database credentials
$servername = "localhost";
$username = "myapp_user";
$password = "secure_password";
$database = "myapp_db";
// Create connection
$conn = new mysqli($servername, $username, $password, $database);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
echo "<h1>Success!</h1>";
echo "<p>Successfully connected to MySQL database: <strong>" . $database . "</strong></p>";
echo "<p>MySQL version: <strong>" . $conn->server_info . "</strong></p>";
$conn->close();
?>
Visit http://your-server-ip/dbtest.php. You should see a success message with the database name and MySQL version.
Security: Delete this test file immediately after verification!
sudo rm /var/www/html/dbtest.php
Test 3: Create a Sample Application
Create a simple web page that uses all three components:
# Create sample page
sudo nano /var/www/html/index.php
Add this content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LAMP Stack - Running!</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 50px auto;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.card {
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
padding: 30px;
backdrop-filter: blur(10px);
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
}
h1 { margin-top: 0; }
.info { background: rgba(255,255,255,0.2); padding: 15px; border-radius: 5px; margin: 10px 0; }
.success { color: #4ade80; font-weight: bold; }
</style>
</head>
<body>
<div class="card">
<h1>🚀 LAMP Stack is Running!</h1>
<div class="info">
<h3>Server Information</h3>
<p><strong>Server Software:</strong> <?php echo $_SERVER['SERVER_SOFTWARE']; ?></p>
<p><strong>PHP Version:</strong> <?php echo phpversion(); ?></p>
<p><strong>Server Name:</strong> <?php echo $_SERVER['SERVER_NAME']; ?></p>
<p><strong>Server IP:</strong> <?php echo $_SERVER['SERVER_ADDR']; ?></p>
</div>
<div class="info">
<h3>System Status</h3>
<p class="success">✓ Linux: Debian 12 (Bookworm)</p>
<p class="success">✓ Apache: Running</p>
<p class="success">✓ MySQL/MariaDB: Running</p>
<p class="success">✓ PHP: <?php echo phpversion(); ?></p>
</div>
<p style="margin-top: 30px; text-align: center; opacity: 0.8;">
Your LAMP stack is configured and ready for development!
</p>
</div>
</body>
</html>
Visit http://your-server-ip/ to see your new landing page!
Success! If you see the styled page with your server information, congratulations! Your LAMP stack is fully operational.
Troubleshooting Common Issues
| Issue | Solution |
|---|---|
| PHP code shows as plain text | Check Apache PHP module: apache2ctl -M | grep php |
| Cannot connect to database | Verify MySQL is running: sudo systemctl status mariadb |
| Permission denied errors | Check file ownership: sudo chown -R www-data:www-data /var/www/html |
| Changes don't appear | Clear browser cache or restart Apache: sudo systemctl restart apache2 |
Security Hardening
Secure your LAMP stack against common vulnerabilities and attacks.
1. Secure Apache
# Hide Apache version information
sudo nano /etc/apache2/conf-available/security.conf
# Set these directives:
ServerTokens Prod
ServerSignature Off
# Enable the security configuration
sudo a2enconf security
# Restart Apache
sudo systemctl restart apache2
2. Disable Directory Listing
# Edit Apache configuration
sudo nano /etc/apache2/apache2.conf
# Find the Directory section for /var/www/ and change:
Options Indexes FollowSymLinks
# to:
Options -Indexes +FollowSymLinks
# Restart Apache
sudo systemctl restart apache2
3. Set Proper File Permissions
# Set ownership to Apache user
sudo chown -R www-data:www-data /var/www/html
# Set directory permissions
sudo find /var/www/html -type d -exec chmod 755 {} \;
# Set file permissions
sudo find /var/www/html -type f -exec chmod 644 {} \;
Permission Explained: 755 for directories (rwxr-xr-x) allows the owner to modify, while others can only read and execute. 644 for files (rw-r--r--) allows owner to write, others to only read.
4. Enable HTTPS with Let's Encrypt
Install Certbot for free SSL certificates:
# Install Certbot
sudo apt install -y certbot python3-certbot-apache
# Obtain and install certificate (replace with your domain)
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com
# Test automatic renewal
sudo certbot renew --dry-run
5. Configure PHP Security
# Edit PHP configuration
sudo nano /etc/php/8.2/apache2/php.ini
# Add/modify these security settings:
expose_php = Off
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
allow_url_fopen = Off
allow_url_include = Off
sql.safe_mode = On
# Restart Apache
sudo systemctl restart apache2
6. Install Fail2Ban
Protect against brute-force attacks:
# Install Fail2Ban
sudo apt install -y fail2ban
# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Edit configuration
sudo nano /etc/fail2ban/jail.local
# Enable Apache protections (find and uncomment):
[apache-auth]
enabled = true
[apache-badbots]
enabled = true
[apache-noscript]
enabled = true
[apache-overflows]
enabled = true
# Start Fail2Ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Check status
sudo fail2ban-client status
7. Regular Updates
Keep your system and packages updated:
# Update package lists and upgrade
sudo apt update && sudo apt upgrade -y
# Enable automatic security updates
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
8. Backup Strategy
Create a simple backup script:
# Create backup directory
sudo mkdir -p /var/backups/lamp
# Create backup script
sudo nano /usr/local/bin/lamp-backup.sh
Add this content:
#!/bin/bash
# LAMP Stack Backup Script
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/var/backups/lamp"
# Backup web files
tar -czf $BACKUP_DIR/www_$DATE.tar.gz /var/www/html
# Backup all databases
mysqldump --all-databases -u root -p > $BACKUP_DIR/databases_$DATE.sql
# Keep only last 7 days of backups
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
echo "Backup completed: $DATE"
# Make executable
sudo chmod +x /usr/local/bin/lamp-backup.sh
# Test the backup
sudo /usr/local/bin/lamp-backup.sh
# Add to crontab for daily backups at 2 AM
sudo crontab -e
# Add this line:
0 2 * * * /usr/local/bin/lamp-backup.sh >> /var/log/lamp-backup.log 2>&1
Backup Critical: Store backups on a separate disk or remote location. Local-only backups won't protect against hardware failure or ransomware.
Security Checklist
- ✓ iptables firewall configured with proper rules
- ✓ Apache version information hidden
- ✓ Directory listing disabled
- ✓ Proper file permissions set
- ✓ HTTPS/SSL certificate installed
- ✓ PHP security settings configured
- ✓ Fail2Ban installed and running
- ✓ Automatic security updates enabled
- ✓ Regular backups scheduled
- ✓ Strong MySQL root password set
- ✓ MySQL remote root login disabled
- ✓ Test/demo files removed
Next Steps & Resources
Virtual Hosts (Multiple Websites)
Configure Apache to host multiple websites on one server:
# Create directory for new site
sudo mkdir -p /var/www/mysite.com/public_html
# Set permissions
sudo chown -R www-data:www-data /var/www/mysite.com
sudo chmod -R 755 /var/www/mysite.com
# Create virtual host configuration
sudo nano /etc/apache2/sites-available/mysite.com.conf
Add this configuration:
<VirtualHost *:80>
ServerName mysite.com
ServerAlias www.mysite.com
ServerAdmin admin@mysite.com
DocumentRoot /var/www/mysite.com/public_html
<Directory /var/www/mysite.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/mysite.com_error.log
CustomLog ${APACHE_LOG_DIR}/mysite.com_access.log combined
</VirtualHost>
# Enable the site
sudo a2ensite mysite.com.conf
# Disable default site (optional)
sudo a2dissite 000-default.conf
# Test configuration
sudo apache2ctl configtest
# Reload Apache
sudo systemctl reload apache2
Install Popular CMS Platforms
WordPress
# Download WordPress
cd /tmp
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
sudo mv wordpress /var/www/html/
# Set permissions
sudo chown -R www-data:www-data /var/www/html/wordpress
sudo chmod -R 755 /var/www/html/wordpress
# Create database for WordPress
sudo mysql -u root -p
CREATE DATABASE wordpress_db;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
# Visit http://your-server-ip/wordpress to complete installation
phpMyAdmin (Optional)
Install phpMyAdmin for easier database management:
# Install phpMyAdmin
sudo apt install -y phpmyadmin
# During installation:
# - Select "apache2" (use spacebar to select)
# - Configure database: Yes
# - Enter MySQL root password
# - Set phpMyAdmin password
# Restart Apache
sudo systemctl restart apache2
# Access at: http://your-server-ip/phpmyadmin
phpMyAdmin Security: For production servers, secure phpMyAdmin by changing its URL, enabling HTTPS, and restricting access by IP address.
Performance Optimization
Enable Apache MPM Event
# Disable prefork MPM
sudo a2dismod mpm_prefork
# Enable event MPM and PHP-FPM
sudo a2enmod mpm_event proxy_fcgi setenvif
sudo a2enconf php8.2-fpm
# Restart services
sudo systemctl restart apache2 php8.2-fpm
Install and Configure OPcache
# Install OPcache (should already be installed)
sudo apt install -y php8.2-opcache
# Configure OPcache
sudo nano /etc/php/8.2/apache2/conf.d/10-opcache.ini
# Add/modify:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
# Restart Apache
sudo systemctl restart apache2
Install Memcached
# Install Memcached and PHP extension
sudo apt install -y memcached php-memcached
# Start and enable Memcached
sudo systemctl enable memcached
sudo systemctl start memcached
# Restart Apache
sudo systemctl restart apache2
Monitoring & Maintenance
Check Service Status
# View all services
sudo systemctl status apache2 mariadb
# Check resource usage
htop
# (install with: sudo apt install htop)
# Monitor Apache connections
sudo ss -tulpn | grep :80
sudo ss -tulpn | grep :443
# View Apache access logs
sudo tail -f /var/log/apache2/access.log
# View Apache error logs
sudo tail -f /var/log/apache2/error.log
# View MySQL logs
sudo tail -f /var/log/mysql/error.log
Disk Space Management
# Check disk usage
df -h
# Find large files
sudo du -h /var/www | sort -rh | head -20
# Clean old logs
sudo journalctl --vacuum-time=7d
# Rotate Apache logs
sudo logrotate -f /etc/logrotate.conf
Useful Commands Reference
| Task | Command |
|---|---|
| Restart all services | sudo systemctl restart apache2 mariadb |
| Check Apache syntax | sudo apache2ctl configtest |
| List enabled modules | apache2ctl -M |
| List enabled sites | ls /etc/apache2/sites-enabled/ |
| MySQL root login | sudo mysql -u root -p |
| Check PHP version | php -v |
| List PHP modules | php -m |
| View system logs | sudo journalctl -xe |
Additional Resources
- Apache Documentation: httpd.apache.org/docs
- MySQL Documentation: dev.mysql.com/doc
- PHP Documentation: php.net/docs
- Debian Wiki: wiki.debian.org
- Let's Encrypt: letsencrypt.org
Troubleshooting Resources
- Apache logs:
/var/log/apache2/ - MySQL logs:
/var/log/mysql/ - PHP error log:
/var/log/php_errors.log(if configured) - System logs:
sudo journalctl -xe - Service status:
sudo systemctl status [service]
Congratulations! You now have a fully functional, secure LAMP stack ready for development or production use. Start building your web applications, deploy your favorite CMS, or experiment with PHP frameworks like Laravel or Symfony.
What's Next?
- Deploy your first web application or CMS
- Set up automated backups to remote storage
- Configure monitoring with tools like Netdata or Prometheus
- Implement advanced caching with Redis or Varnish
- Explore containerization with Docker for easier deployment
- Learn about load balancing for high-traffic sites