NGINX PHP-FPM Configuration Guide

Complete WordPress Security & Performance Setup

Table of Contents

1. Logs Management

Proper log management is essential for monitoring server activity, debugging issues, and identifying security threats. NGINX and PHP-FPM logs provide valuable insights into your server's operations.

Viewing NGINX Logs

Navigate to the NGINX log directory and view log files:

cd /var/log/nginx
ls
sudo cat log_file_name.log
sudo less log_file_name.log
Tip: Use less for large log files as it allows pagination and search functionality.

2. PHP-FPM Pool Configuration

PHP-FPM pools allow you to run multiple PHP applications with different users and configurations, enhancing security and resource management.

PHP-FPM Pool Architecture

NGINX Web Server
Unix Socket Communication
PHP-FPM Pool (example.com)
PHP Application

Step 1: Create System User

Create a dedicated user for your website to improve security isolation:

sudo useradd username

Step 2: Configure User Groups

Add users to appropriate groups for proper permissions:

sudo usermod -a -G username_group www-data
sudo usermod -a -G www-data username_group
sudo usermod -a -G username_group $USER

Step 3: Create PHP-FPM Pool Configuration

Navigate to the PHP-FPM pool directory and create a new configuration:

cd /etc/php/8.3/fpm/pool.d/
ls
sudo cp www.conf example.com.conf
sudo nano example.com.conf

Essential Pool Configuration

; Start a new pool named 'example' [example] ; Unix user/group of the child processes user = username group = username ; The address on which to accept FastCGI requests listen = /run/php/php8.3-fpm-example.com.sock ; Set open file descriptor rlimit rlimit_files = 15000 ; Set max core size rlimit rlimit_core = 100 ; PHP error logging configuration php_flag[display_errors] = off php_admin_value[error_log] = /var/log/fpm-php.example.com.log php_admin_flag[log_errors] = on

Step 4: Create FPM Log File

Create and configure the PHP-FPM log file with proper permissions:

sudo touch /var/log/fpm-php.example.com.log
sudo chown username:www-data /var/log/fpm-php.example.com.log
sudo chmod 660 /var/log/fpm-php.example.com.log

Step 5: Reload PHP-FPM Service

sudo systemctl reload php8.3-fpm

Step 6: Verify Socket Configuration

sudo grep "listen = /" /etc/php/8.3/fpm/pool.d/example.com.conf

Step 7: Configure NGINX to Use Pool Socket

sudo nano /etc/nginx/sites-available/example.com.conf

Update the FastCGI pass directive:

fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;

Step 8: Test and Reload NGINX

sudo nginx -t
sudo systemctl reload nginx

Advanced PHP-FPM Security Configuration

File Permissions Setup

Set secure file and directory permissions:

sudo chown -R username:username /var/www/example.com/public_html/
sudo find /var/www/example.com/public_html/ -type d -exec chmod 770 {} \;
sudo find /var/www/example.com/public_html/ -type f -exec chmod 660 {} \;

PHP Function Security

Enable or disable specific PHP functions for security:

sudo nano /etc/php/8.3/fpm/pool.d/example.com.conf
; Enable URL fopen if needed php_admin_flag[allow_url_fopen] = on ; Disable dangerous functions php_admin_value[disable_functions] = shell_exec, opcache_get_configuration, opcache_get_status, disk_total_space, diskfreespace, dl, exec, passthru, pclose, pcntl_alarm, pcntl_exec, pcntl_fork, pcntl_get_last_error, pcntl_getpriority, pcntl_setpriority, pcntl_signal, pcntl_signal_dispatch, pcntl_sigprocmask, pcntl_sigtimedwait, pcntl_sigwaitinfo, pcntl_strerror, pcntl_waitpid, pcntl_wait, pcntl_wexitstatus, pcntl_wifcontinued, pcntl_wifexited, pcntl_wifsignaled, pcntl_wifstopped, pcntl_wstopsig, pcntl_wtermsig, popen, posix_getpwuid, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, posix_uname, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, show_source, system

Hardened Permissions (Production)

For production environments, implement stricter permissions:

sudo find /var/www/example.com/public_html/ -type d -exec chmod 550 {} \;
sudo find /var/www/example.com/public_html/ -type f -exec chmod 440 {} \;
sudo find /var/www/example.com/public_html/wp-content/ -type d -exec chmod 770 {} \;
sudo find /var/www/example.com/public_html/wp-content/ -type f -exec chmod 660 {} \;

Temporary Directory Configuration

Create and configure isolated temporary directories:

cd /var/www/example.com/
sudo mkdir tmp/
sudo chown username:username tmp/
sudo chmod 770 tmp/
sudo nano /etc/php/8.3/fpm/pool.d/example.com.conf
php_admin_value[upload_tmp_dir] = /var/www/example.com/tmp/ php_admin_value[sys_temp_dir] = /var/www/example.com/tmp/ php_admin_value[open_basedir] = /var/www/example.com/public_html/:/var/www/example.com/tmp/
sudo systemctl reload php8.3-fpm
Important: The open_basedir directive restricts PHP file operations to specified directories, preventing unauthorized file access.

3. SSL/TLS Configuration

Implementing SSL/TLS certificates ensures encrypted communication between your server and clients, protecting data integrity and privacy.

Step 1: Install Certbot

sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflare

Step 2: Obtain SSL Certificate

Use the webroot method to obtain Let's Encrypt certificates:

sudo certbot certonly --webroot -w /var/www/example.com/public_html/ -d example.com -d www.example.com

Step 3: Generate DH Parameters

Create Diffie-Hellman parameters for enhanced security:

cd /etc/nginx/
sudo mkdir ssl/
cd ssl/
sudo openssl dhparam -out dhparam.pem 2048

Step 4: Create SSL Certificate Configuration

sudo nano /etc/nginx/ssl/ssl_certs_example.com.conf
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

Step 5: Create Global SSL Configuration

sudo nano /etc/nginx/ssl/ssl_all_sites.conf
# CONFIGURATION RESULTS IN A+ RATING AT SSLLABS.COM # DATE: MAY 2025 # SSL CACHING AND PROTOCOLS ssl_session_cache shared:SSL:20m; ssl_session_timeout 180m; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305; ssl_dhparam /etc/nginx/ssl/dhparam.pem; # LETS ENCRYPT REMOVED SUPPORT FOR SSL STAPLING ON 7 MAY 2025 # ssl_stapling on; # ssl_stapling_verify on; # Resolver set to Cloudflare resolver 1.1.1.1 1.0.0.1; resolver_timeout 15s; ssl_session_tickets off; # HSTS HEADERS add_header Strict-Transport-Security "max-age=31536000;" always; # Enable QUIC and HTTP/3 ssl_early_data on; add_header Alt-Svc 'h3=":$server_port"; ma=86400'; add_header x-quic 'H3'; quic_retry on;
SSL Labs Rating: This configuration achieves an A+ rating on SSL Labs testing.

4. HTTP/3 & QUIC Setup

HTTP/3 uses QUIC protocol for improved performance, reduced latency, and better connection reliability.

HTTP/3 Architecture

Client Request (HTTP/3 / QUIC)
Port 443 UDP (QUIC)
NGINX Server
Multiplexed Streams

Server Block Configuration

Configure your NGINX server block to support HTTP/3:

HTTP to HTTPS Redirect

server { listen 80; server_name example.com www.example.com; # 301 permanent redirect to HTTPS return 301 https://example.com$request_uri; }

Primary HTTPS Server (with reuseport)

server { listen 443 ssl; http2 on; listen 443 quic reuseport; http3 on; server_name example.com www.example.com; # Include SSL configurations include /etc/nginx/ssl/ssl_certs_example.com.conf; include /etc/nginx/ssl/ssl_all_sites.conf; # Additional configuration... }

Additional HTTPS Servers (without reuseport)

server { listen 443 ssl; http2 on; listen 443 quic; http3 on; server_name other.example.com; # Include SSL configurations # ... }
Note: Use reuseport only on the first server block listening on port 443. Additional server blocks should omit this directive.

Testing HTTP/3 Configuration

Disable browser caching temporarily to test HTTP/3:

location / { # Prevents browser caching - use only for testing add_header Cache-Control 'no-cache,no-store'; # Remove after confirming HTTP/3 is enabled }

Add HTTP_HOST Parameter

Include the HTTP_HOST parameter in PHP processing:

location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_param HTTP_HOST $host; fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock; include /etc/nginx/includes/fastcgi_optimize.conf; }

Test SSL/TLS Configuration

curl -I http://example.com
curl -I http://www.example.com
curl -I https://www.example.com
curl -I https://example.com

Test and Reload NGINX

sudo nginx -t
sudo systemctl reload nginx

Verification Tools

Tool Purpose URL
SSL Labs SSL/TLS Configuration Testing https://www.ssllabs.com/ssltest/
HTTP/3 Check Verify HTTP/3 Support https://http3check.net/
Browser DevTools Network Protocol Inspection Console → Network → Protocol Column
Browser Verification: In Chrome/Edge DevTools, enable the "Protocol" column in the Network tab. Look for "h3" indicating HTTP/3 is active.

5. Security Headers

HTTP security headers protect your website from common vulnerabilities such as clickjacking, XSS, and MIME-type sniffing attacks.

Certificate Management with Certbot

Certbot Commands Reference

Command Description
sudo certbot certificates List all certificates
sudo certbot delete Delete a certificate
sudo certbot renew Renew certificates
sudo certbot renew --force-renewal Force certificate renewal

Automated SSL Certificate Renewal

Configure automatic renewal using cron jobs:

sudo crontab -e
# Renew certificates on the 14th and 28th of each month at 1:00 AM 00 1 14,28 * * certbot renew --force-renewal # Reload NGINX at 2:00 AM after renewal 00 2 14,28 * * systemctl reload nginx

HTTP Security Headers Configuration

cd /etc/nginx/includes/
sudo nano http_headers.conf
# HTTP Security Headers Configuration # Referrer Policy - Choose one option #add_header Referrer-Policy "no-referrer"; add_header Referrer-Policy "strict-origin-when-cross-origin"; #add_header Referrer-Policy "unsafe-url"; # Prevent MIME-type sniffing add_header X-Content-Type-Options "nosniff"; # Clickjacking protection add_header X-Frame-Options "sameorigin"; # XSS protection add_header X-XSS-Protection "1; mode=block"; # Permissions Policy add_header Permissions-Policy 'accelerometer=(), camera=(), clipboard-read=(), clipboard-write=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), fullscreen=(self "https://www.youtube.com")';

Include Headers in Site Configuration

cd /etc/nginx/sites-available/
sudo nano example.com.conf

Add before the PHP processing location block:

include /etc/nginx/includes/http_headers.conf;
sudo nginx -t
sudo systemctl reload nginx

Browser Caching and Security Headers

Create a combined configuration for caching and security:

sudo nano /etc/nginx/includes/browser_caching_security_headers.conf
# Browser Caching Configuration expires 30d; etag on; if_modified_since exact; add_header Pragma "public"; add_header Cache-Control "public, no-transform"; # WordPress permalink support try_files $uri $uri/ /index.php?$args; # Include security headers include /etc/nginx/includes/http_headers.conf; # Disable access logs for static files access_log off;
sudo nginx -t
sudo systemctl reload nginx

Security Headers Explained

Header Purpose Value
Referrer-Policy Controls referrer information strict-origin-when-cross-origin
X-Content-Type-Options Prevents MIME sniffing nosniff
X-Frame-Options Prevents clickjacking sameorigin
X-XSS-Protection Enables XSS filter 1; mode=block
Permissions-Policy Controls browser features Custom permissions

6. WordPress Security Directives

Implementing WordPress-specific security directives protects your site from common attack vectors and unauthorized access attempts.

File Permissions Configuration

Standard Permissions (Development)

cd /var/www/example.com/
sudo chown -R username:username public_html/
sudo find /var/www/example.com/public_html/ -type d -exec chmod 770 {} \;
sudo find /var/www/example.com/public_html/ -type f -exec chmod 660 {} \;
sudo chmod 400 public_html/wp-config.php

Hardened Permissions (Production)

cd /var/www/example.com/
sudo chown -R username:username public_html/
sudo find /var/www/example.com/public_html/ -type d -exec chmod 550 {} \;
sudo find /var/www/example.com/public_html/ -type f -exec chmod 440 {} \;
sudo find /var/www/example.com/public_html/wp-content/ -type d -exec chmod 770 {} \;
sudo find /var/www/example.com/public_html/wp-content/ -type f -exec chmod 660 {} \;

WordPress Security Directives

cd /etc/nginx/includes/
sudo nano nginx_security_directives.conf
# WORDPRESS-SAFE NGINX 8G (based) FIREWALL Ruleset # Low false-positive risks # Updated December 2026 # Disable favicon logging location = /favicon.ico { access_log off; log_not_found off; } # Deny access to sensitive core and config files location = /wp-config.php { deny all; } location = /wp-admin/install.php { deny all; } location ~* ^/(readme|license|licence)\.(txt|html)$ { deny all; } location ~* \.ini$ { deny all; } # Harden WP core location ~* ^/wp-includes/[^/]+\.php$ { deny all; } location ~* ^/wp-includes/js/tinymce/langs/.+\.php$ { deny all; } location ~* ^/wp-includes/theme-compat/ { deny all; } # Prevent PHP execution in uploads, themes and plugin directories location ~* ^/wp-content/uploads/.*\.(php[1-8]?|pht|phtml?|phps)$ { deny all; } location ~* ^/wp-content/plugins/.*\.(php[1-8]?|pht|phtml?|phps)$ { deny all; } location ~* ^/wp-content/themes/.*\.(php[1-8]?|pht|phtml?|phps)$ { deny all; } # Protect upgrade and backup directories location ~* ^/wp-content/(upgrade|backup-.*)/.*\.(php[1-8]?|pht|phtml?|phps)$ { deny all; } # Block development and dependency files/dirs location ~* (composer\.(json|lock)|package\.json|yarn\.lock|/vendor/|/node_modules/) { deny all; } # Block dangerous or unused HTTP methods if ($request_method ~* ^(TRACE|DELETE|TRACK)$) { return 403; } # Block known vulnerability scanners if ($http_user_agent ~* (nikto|sqlmap|masscan|nmap|dirbuster|acunetix|openvas)) { return 444; }

Include Security Directives in Site Configuration

cd /etc/nginx/sites-available/
sudo nano example.com.conf

Add before the PHP processing location block:

include /etc/nginx/includes/nginx_security_directives.conf;
sudo nginx -t
sudo systemctl reload nginx

Allow PHP Execution for Specific Plugins

Some plugins require PHP execution in the plugins directory. Create specific exceptions:

Test PHP Execution Block

cd /var/www/example.com/
sudo nano public_html/wp-content/plugins/test556.php
<?php phpinfo(); ?>

Test in browser: https://example.com/wp-content/plugins/test556.php

Result: 403 Forbidden (PHP execution blocked)

Allow Specific Plugin PHP Execution

Add after the PHP processing location block:

location = /wp-content/plugins/test556.php { allow all; include snippets/fastcgi-php.conf; fastcgi_param HTTP_HOST $host; fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock; include /etc/nginx/includes/fastcgi_optimize.conf; }
sudo nginx -t
sudo systemctl reload nginx && sudo systemctl restart php8.3-fpm

Test again: PHP should now execute successfully.

Clean Up Test File

cd /var/www/example.com/public_html/wp-content/plugins/
sudo rm test556.php
Security Note: Only allow PHP execution for specific, trusted plugin files. Always use exact path matching with location =.

Additional WordPress Security

Add to your wp-config.php file to disable file modifications:

define('DISALLOW_FILE_MODS', true);
sudo systemctl reload php8.3-fpm

7. Rate Limiting

Rate limiting protects your server from brute-force attacks, DDoS attempts, and excessive resource consumption by limiting the number of requests from a single IP address.

Rate Limiting Flow

Client Request
Rate Limit Check (30 requests/minute)
Within Limit? → Process Request
Exceeded? → Return 444 (Connection Closed)

Step 1: Configure Rate Limiting Zone

cd /etc/nginx/
sudo nano nginx.conf

Add in the http block:

## # Rate Limiting limit_req_zone $binary_remote_addr zone=wp:10m rate=30r/m;

Step 2: Create Rate Limiting Configuration

cd /etc/nginx/includes/
sudo nano rate_limiting_example.com.conf
# Rate limit wp-login.php to prevent brute-force attacks location = /wp-login.php { limit_req zone=wp burst=20 nodelay; limit_req_status 444; include snippets/fastcgi-php.conf; fastcgi_param HTTP_HOST $host; fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock; include /etc/nginx/includes/fastcgi_optimize.conf; } # Rate limit XML-RPC to prevent DDoS attacks location = /xmlrpc.php { limit_req zone=wp burst=20 nodelay; limit_req_status 444; include snippets/fastcgi-php.conf; fastcgi_param HTTP_HOST $host; fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock; include /etc/nginx/includes/fastcgi_optimize.conf; }

Step 3: Include Rate Limiting in Site Configuration

cd /etc/nginx/sites-available/
sudo nano example.com.conf

Add in the server block:

# Rate Limiting Include include /etc/nginx/includes/rate_limiting_example.com.conf;
sudo nginx -t
sudo systemctl reload nginx

Rate Limiting Parameters Explained

Parameter Description Value
zone=wp Name of the rate limit zone 10m memory allocation
rate=30r/m Maximum request rate 30 requests per minute
burst=20 Allow burst of requests 20 additional requests
nodelay Process burst immediately No queueing delay
limit_req_status Status code for rejected requests 444 (close connection)
Recommendation: Monitor your logs after implementing rate limiting to ensure legitimate users are not being blocked. Adjust rates as needed for your specific traffic patterns.

8. Web Application Firewall (Ninja Firewall)

A Web Application Firewall (WAF) provides an additional security layer by intercepting and filtering HTTP/HTTPS requests before they reach your WordPress application. NinjaFirewall is a powerful, lightweight WAF specifically designed for WordPress.

Ninja Firewall Architecture

HTTP/HTTPS Request
NGINX Web Server
PHP-FPM
🛡️ Ninja Firewall (Hook/Scan/Filter)
Allow → WordPress Core
Deny → Block Request

Key Features of Ninja Firewall

Installation Steps

Step 1: Access WordPress Admin Dashboard

Navigate to your WordPress admin area:

https://example.com/wp-admin/

Step 2: Install Ninja Firewall Plugin

  1. Click on Plugins in the left sidebar
  2. Click Add New Plugin
  3. Search for "NinjaFirewall" in the search box
  4. Locate NinjaFirewall (WP Edition)
  5. Click Install Now
  6. Wait for installation to complete
Prerequisites: Before activating NinjaFirewall, ensure your file permissions are correctly set to allow the plugin to create and modify the .user.ini file.

Step 3: Verify File Permissions

Check for existing hidden files in document root:

cd /var/www/example.com/public_html/
ls -la

Ensure permissions are set correctly:

sudo find /var/www/example.com/public_html/ -type d -exec chmod 770 {} \;
sudo find /var/www/example.com/public_html/ -type f -exec chmod 660 {} \;

Step 4: Activate Ninja Firewall

  1. Return to WordPress admin dashboard
  2. Navigate to Plugins → Installed Plugins
  3. Locate NinjaFirewall (WP Edition)
  4. Click Activate

Step 5: Initial Configuration Wizard

After activation, NinjaFirewall will guide you through initial setup:

  1. Welcome Screen: Click "Got it" to proceed
  2. Enable Firewall: Firewall is enabled by default
  3. Select Mode: Choose Full WAF Mode
  4. HTTP Server: Select Nginx + CGI/FastCGI or PHP-FPM
  5. PHP Initialization File: Select .user.ini
  6. Protected Folders: Verify all directories are listed
  7. Enable Sandbox: Click to enable sandboxed environment
  8. Finish Installation: Complete setup wizard
Success: Ninja Firewall is now running in Full WAF Mode, providing comprehensive protection for your WordPress site.

Configuration Overview

Access Ninja Firewall Dashboard

Navigate to: WordPress Admin → NinjaFirewall → Dashboard

Main Configuration Areas

Section Purpose Recommendation
Firewall Options Core firewall settings Review before modifying
Firewall Policies Protection level configuration Start with Basic, increase gradually
Basic Policies Fundamental security rules Enable recommended settings
Intermediate Policies Enhanced protection rules Test on staging first
Advanced Policies Maximum security rules Use with caution
Live Log Real-time request monitoring Monitor after configuration changes
Event Notifications Alert configuration Set up email notifications

Important Considerations

Testing Protocol:
  • Always test configuration changes on a development or staging server first
  • Monitor live logs for false positives after making changes
  • Gradually increase security policies from Basic to Intermediate to Advanced
  • Document all configuration changes
  • Keep backup of working configurations

Documentation and Support

Access comprehensive documentation through the NinjaFirewall dashboard:

WordPress Admin → NinjaFirewall → Dashboard → Help and Configuration

The documentation covers:

Recommended Initial Settings

Start with Conservative Settings

  1. Operating Mode: Full WAF Mode
  2. Firewall Policies: Basic level
  3. Log Level: Medium (monitor for 1-2 weeks)
  4. Email Notifications: Enable for critical events
  5. IP Whitelist: Add your administrative IP addresses

After Stabilization Period (2-4 weeks)

  1. Review logs for false positives
  2. Adjust policies based on your site's specific needs
  3. Gradually increase to Intermediate policies
  4. Consider Advanced policies for high-security requirements
  5. Fine-tune notification thresholds
Best Practice: Ninja Firewall provides an excellent balance between security and performance. Regular monitoring and gradual policy adjustments will ensure optimal protection without interfering with legitimate site functionality.

9. Database Privileges

Implementing the principle of least privilege for database users enhances security by limiting potential damage from compromised credentials or SQL injection attacks.

Understanding Database Privileges

WordPress requires specific database operations for normal functionality. By restricting privileges to only necessary operations, you reduce the attack surface.

Database Security Model

WordPress Application
Database User (Limited Privileges)
MySQL/MariaDB Server
WordPress Database

Standard WordPress Database Privileges

Step 1: Revoke All Existing Privileges

REVOKE ALL PRIVILEGES ON site_db.* FROM 'site_user'@'hostname';

Step 2: Grant Essential Privileges

For normal WordPress operation, grant only these privileges:

GRANT SELECT, INSERT, UPDATE, DELETE ON site_db.* TO 'site_user'@'hostname';

Step 3: Apply Changes

FLUSH PRIVILEGES;

Additional Privileges for Plugin Installation

When installing plugins or themes that modify database structure, temporarily grant additional privileges:

GRANT CREATE, ALTER, INDEX ON site_db.* TO 'site_user'@'hostname'; FLUSH PRIVILEGES;
Security Recommendation: After completing plugin/theme installation, revoke these additional privileges and return to the minimal privilege set.

Database Privilege Reference

Privilege Purpose Required For
SELECT Read data from tables Standard operations ✓
INSERT Add new records Standard operations ✓
UPDATE Modify existing records Standard operations ✓
DELETE Remove records Standard operations ✓
CREATE Create new tables Plugin installation only
ALTER Modify table structure Plugin installation only
INDEX Create/modify indexes Plugin installation only
DROP Delete tables ❌ Not recommended

Complete Privilege Management Example

Initial Setup (Minimal Privileges)

-- Connect to MySQL mysql -u root -p -- Switch to WordPress database USE wordpress_db; -- Revoke all privileges REVOKE ALL PRIVILEGES ON wordpress_db.* FROM 'wp_user'@'localhost'; -- Grant minimal required privileges GRANT SELECT, INSERT, UPDATE, DELETE ON wordpress_db.* TO 'wp_user'@'localhost'; -- Apply changes FLUSH PRIVILEGES; -- Exit MySQL EXIT;

Temporary Extension for Plugin Installation

-- Grant additional privileges for installation GRANT CREATE, ALTER, INDEX ON wordpress_db.* TO 'wp_user'@'localhost'; FLUSH PRIVILEGES; -- After installation, revoke additional privileges REVOKE CREATE, ALTER, INDEX ON wordpress_db.* FROM 'wp_user'@'localhost'; FLUSH PRIVILEGES;

Verifying Current Privileges

Check what privileges are currently granted to a user:

SHOW GRANTS FOR 'wp_user'@'localhost';

Multiple Database Users Strategy

For enhanced security, consider using separate database users for different purposes:

User Type Privileges Use Case
wp_user SELECT, INSERT, UPDATE, DELETE Normal site operation
wp_admin SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX Plugin/theme installation
wp_backup SELECT Backup operations only
Configuration Tip: When using separate database users, configure wp-config.php to use the appropriate credentials based on the operation being performed. This can be automated through environment-specific configuration files.

Additional Security Measures

1. Regular Privilege Audits

Periodically review and audit database user privileges:

-- List all users and their privileges SELECT user, host FROM mysql.user; -- Check specific user privileges SHOW GRANTS FOR 'wp_user'@'localhost';

2. Connection Security

Ensure database connections are secure:

3. WordPress Configuration

Disable automatic database repairs in production:

// In wp-config.php define('WP_ALLOW_REPAIR', false);
Security Benefit: Implementing minimal database privileges significantly reduces the potential impact of SQL injection attacks and compromised database credentials, protecting your WordPress installation and data.