Start by disabling unnecessary modules and restricting directory permissions:
# Disable risky modules
a2dismod autoindex status cgi
# Secure directory permissions
chmod 750 /var/www/html
chown -R www-data:www-data /var/www/html
After installation, run the security script and implement these changes:
mysql_secure_installation
# In MySQL console:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'ComplexP@ssw0rd';
DELETE FROM mysql.user WHERE User='';
FLUSH PRIVILEGES;
Edit php.ini with these critical settings:
expose_php = Off
allow_url_fopen = Off
display_errors = Off
log_errors = On
disable_functions = exec,passthru,shell_exec,system
Set up basic firewall rules:
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow http
ufw allow https
ufw enable
Install and configure the web application firewall:
apt install libapache2-mod-security2
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
# Enable Core Rule Set
git clone https://github.com/coreruleset/coreruleset /etc/modsecurity/crs/
- Set up automatic security updates:
apt install unattended-upgrades
- Implement log monitoring with fail2ban
- Schedule regular backups with verification
- Monitor for suspicious processes:
ps auxf
Securing a LAMP server requires a multi-layered approach addressing each component:
- Linux: OS-level hardening and user permissions
- Apache: Web server configuration and module management
- MySQL/MariaDB: Database access controls
- PHP: Runtime security and sandboxing
# Disable unnecessary services
sudo systemctl list-unit-files --type=service | grep enabled
sudo systemctl disable [unnecessary-service]
# Configure firewall (UFW example)
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
# Automatic security updates
sudo apt-get install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
Essential directives for /etc/apache2/apache2.conf
:
ServerTokens Prod
ServerSignature Off
TraceEnable Off
Header always append X-Frame-Options SAMEORIGIN
Header set X-Content-Type-Options nosniff
Header set X-XSS-Protection "1; mode=block"
# Disable directory listing
Options -Indexes
# Restrict HTTP methods
<LimitExcept GET POST>
Deny from all
</LimitExcept>
# Run mysql_secure_installation
sudo mysql_secure_installation
# Create application-specific users
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT SELECT, INSERT, UPDATE ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
# Enable binary logging for audit
[mysqld]
log-bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
Key settings for php.ini
:
expose_php = Off
display_errors = Off
log_errors = On
allow_url_fopen = Off
allow_url_include = Off
disable_functions = exec,passthru,shell_exec,system
upload_max_filesize = 2M
post_max_size = 4M
For WordPress installations (example):
# .htaccess protection
<Files wp-config.php>
Order Allow,Deny
Deny from all
</Files>
# Disable XML-RPC
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
# Install and configure fail2ban
sudo apt-get install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Configure for Apache
[apache]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/*error.log
maxretry = 3
# Regular vulnerability scanning
sudo apt-get install lynis
sudo lynis audit system
# Simple backup script
#!/bin/bash
DATE=$(date +%Y-%m-%d)
mysqldump -u root -p[password] --all-databases > /backups/mysql-$DATE.sql
tar -czvf /backups/web-$DATE.tar.gz /var/www/html/
find /backups/ -type f -mtime +30 -exec rm {} \;