Configuration files are your WordPress site's first line of defense. Proper configuration of wp-config.php, .htaccess, and other files can prevent up to 80% of typical attacks. This guide covers all aspects of securing WordPress through configuration files: from basic settings to advanced security techniques.
Why Configuration Files Are Critical for Security
Configuration files contain critical information and control site behavior at the server level. They execute before WordPress loads, enabling attack blocking at the earliest stage.
Core security files:
wp-config.php — WordPress main configuration file. Contains database credentials, secret keys, security settings.
.htaccess — Apache web server configuration file. Manages file access, redirects, directory protection.
php.ini or .user.ini — PHP settings for the site. Restrict PHP code execution, manage file uploads.
wp-config.php: Hardening the Main Configuration File
The wp-config.php file is the heart of WordPress security. It stores database access credentials and critical settings.
Moving wp-config.php Outside Web Root
First step — move wp-config.php one level above web root:
Current structure:
/public_html/
├── wp-config.php
├── wp-content/
└── wp-includes/
Secure structure:
/home/username/
├── wp-config.php
└── public_html/
├── wp-content/
└── wp-includes/
Move the file:
mv /home/username/public_html/wp-config.php /home/username/
WordPress automatically finds wp-config.php one level above web root.
Changing Database Table Prefix
Standard wp_ prefix makes your database predictable to attackers.
Open wp-config.php:
nano /home/username/wp-config.php
Find the table prefix line:
$table_prefix = 'wp_';
Change to unique prefix:
$table_prefix = 'x7k9m_';
Important: this only works for fresh installations. For existing sites, use Change Table Prefix plugin or modify manually via SQL.
Changing prefix via SQL for existing site:
RENAME TABLE wp_commentmeta TO x7k9m_commentmeta;
RENAME TABLE wp_comments TO x7k9m_comments;
RENAME TABLE wp_links TO x7k9m_links;
RENAME TABLE wp_options TO x7k9m_options;
RENAME TABLE wp_postmeta TO x7k9m_postmeta;
RENAME TABLE wp_posts TO x7k9m_posts;
RENAME TABLE wp_terms TO x7k9m_terms;
RENAME TABLE wp_termmeta TO x7k9m_termmeta;
RENAME TABLE wp_term_relationships TO x7k9m_term_relationships;
RENAME TABLE wp_term_taxonomy TO x7k9m_term_taxonomy;
RENAME TABLE wp_usermeta TO x7k9m_usermeta;
RENAME TABLE wp_users TO x7k9m_users;
Update user metadаta:
UPDATE x7k9m_usermeta SET meta_key = REPLACE(meta_key, 'wp_', 'x7k9m_');
UPDATE x7k9m_options SET option_name = REPLACE(option_name, 'wp_', 'x7k9m_') WHERE option_name LIKE 'wp_%';
Disabling File Editor in Admin Panel
Built-in file editor is a major security hole. If attacker gains admin access, they can edit PHP files.
Add to wp-config.php before "That's all, stop editing!" line:
define('DISALLOW_FILE_EDIT', true);
This disables theme and plugin editors in admin.
For complete plugin/theme installation/update blocking:
define('DISALLOW_FILE_MODS', true);
Warning: DISALLOW_FILE_MODS also disables plugin and theme installation. Use only if updates are done via SSH.
Limiting Post Revisions
WordPress saves every post revision, bloating the database.
Limit revision count:
define('WP_POST_REVISIONS', 3);
Or disable revisions completely:
define('WP_POST_REVISIONS', false);
Disabling Autosave
Autosave creates temporary post copies every 60 seconds.
Increase interval to 300 seconds:
define('AUTOSAVE_INTERVAL', 300);
Changing PHP Memory Limit
Increase memory limit for WordPress:
define('WP_MEMORY_LIMIT', '256M');
Set separate limit for admin panel:
define('WP_MAX_MEMORY_LIMIT', '512M');
Disabling Debug Mode in Production
Ensure debugging is disabled on live site:
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
define('WP_DEBUG_LOG', false);
For development, enable logging without screen display:
define('WP_DEBUG', true);
define('WP_DEBUG_DISPLAY', false);
define('WP_DEBUG_LOG', true);
Logs save to /wp-content/debug.log.
Forcing SSL for Admin Area
Force WordPress to use HTTPS for admin login:
define('FORCE_SSL_ADMIN', true);
This protects credentials from interception.
Changing Admin URL via wp-config.php
While complete admin URL change requires a plugin, you can modify some paths:
define('WP_SITEURL', 'https://example.com');
define('WP_HOME', 'https://example.com');
Enabling Database Recovery Mode
For automatic database repair during failures:
define('WP_AUTO_UPDATE_CORE', true);
define('AUTOMATIC_UPDATER_DISABLED', false);
Secret Keys and Salts
WordPress uses secret keys for cookie and password encryption.
Generate new keys at https://api.wordpress.org/secret-key/1.1/salt/
Replace standard keys in wp-config.php:
define('AUTH_KEY', 'generated key');
define('SECURE_AUTH_KEY', 'generated key');
define('LOGGED_IN_KEY', 'generated key');
define('NONCE_KEY', 'generated key');
define('AUTH_SALT', 'generated key');
define('SECURE_AUTH_SALT', 'generated key');
define('LOGGED_IN_SALT', 'generated key');
define('NONCE_SALT', 'generated key');
Change keys every 3-6 months for additional security.
Restricting wp-config.php Access
Set strict access permissions:
chmod 600 /home/username/wp-config.php
This allows read and write only for file owner.
Complete wp-config.php for Maximum Security
Here's a fully secured wp-config.php example:
<?php
define('DB_NAME', 'database_name');
define('DB_USER', 'database_user');
define('DB_PASSWORD', 'strong_password_here');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', '');
$table_prefix = 'x7k9m_';
define('AUTH_KEY', 'your_unique_key_here');
define('SECURE_AUTH_KEY', 'your_unique_key_here');
define('LOGGED_IN_KEY', 'your_unique_key_here');
define('NONCE_KEY', 'your_unique_key_here');
define('AUTH_SALT', 'your_unique_key_here');
define('SECURE_AUTH_SALT', 'your_unique_key_here');
define('LOGGED_IN_SALT', 'your_unique_key_here');
define('NONCE_SALT', 'your_unique_key_here');
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
define('WP_DEBUG_LOG', false);
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', false);
define('FORCE_SSL_ADMIN', true);
define('WP_POST_REVISIONS', 3);
define('AUTOSAVE_INTERVAL', 300);
define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');
define('WP_AUTO_UPDATE_CORE', 'minor');
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
require_once ABSPATH . 'wp-settings.php';
.htaccess: Server-Level Protection
The .htaccess file controls Apache behavior at directory level. It's a powerful tool for blocking attacks.
Checking .htaccess Existence
Check if .htaccess exists in site root:
ls -la /home/username/public_html/.htaccess
If file doesn't exist, create it:
touch /home/username/public_html/.htaccess
Basic .htaccess Structure for WordPress
WordPress creates basic .htaccess for permalinks:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Make all additions BEFORE or AFTER the WordPress block.
Protecting wp-config.php via .htaccess
Deny access to wp-config.php:
<files wp-config.php>
order allow,deny
deny from all
</files>
Protecting .htaccess from Viewing
Deny access to .htaccess itself:
<files .htaccess>
order allow,deny
deny from all
</files>
Blocking wp-includes Access
The wp-includes directory should not be directly accessible:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>
Preventing PHP Execution in Uploads Directory
Uploads folder should not execute PHP code:
<Directory "/home/username/public_html/wp-content/uploads">
<Files *.php>
deny from all
</Files>
</Directory>
Or via separate .htaccess in /wp-content/uploads/:
<Files *.php>
deny from all
</Files>
Disabling Directory Listing
Prevent file listing in directories:
Options -Indexes
Protection Against Injection and XSS Attacks
Block suspicious requests:
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
</IfModule>
Blocking SQL Injections
Protection against popular SQL injection patterns:
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC,OR]
RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC,OR]
RewriteCond %{QUERY_STRING} (\.\./|\.\.) [OR]
RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
RewriteCond %{QUERY_STRING} http\: [NC,OR]
RewriteCond %{QUERY_STRING} https\: [NC,OR]
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)(union|select|insert|drop|delete|update|replace|cast|declare|convert)(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} \.\./\.\./\.\./
RewriteRule ^(.*)$ - [F,L]
</IfModule>
Limiting Upload File Size
Set file size limit:
LimitRequestBody 10240000
This limits uploads to 10MB.
Blocking Access by User-Agent
Block known malicious bots:
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^(.*)(HTTrack|wget|curl|libwww|python)(.*)$ [NC]
RewriteRule ^(.*)$ - [F,L]
</IfModule>
Warning: this blocks legitimate services like uptime monitoring. Use carefully.
Protection Against Image Hotlinking
Prevent image embedding on external sites:
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?google.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [NC,F,L]
Replace example.com with your domain.
Forcing HTTPS Usage
Redirect all HTTP requests to HTTPS:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
Protecting wp-login.php from Brute Force
Limit login page access by IP:
<Files wp-login.php>
Order Deny,Allow
Deny from all
Allow from 203.0.113.50
Allow from 198.51.100.25
</Files>
Replace IP addresses with yours.
Or limit request rate using mod_evasive (requires server installation).
Blocking xmlrpc.php Access
XML-RPC is often used for brute-force attacks:
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>
Caching Static Content
Speed up site via caching headers:
<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 image/webp "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/jаvascript "access plus 1 month"
ExpiresByType application/jаvascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresDefault "access plus 7 days"
</IfModule>
GZIP Content Compression
Enable compression for faster loading:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/jаvascript
AddOutputFilterByType DEFLATE application/x-jаvascript
</IfModule>
Complete .htaccess for Maximum Security
Here's comprehensive .htaccess with maximum protection:
# WordPress Security
# Protect configuration files
<files wp-config.php>
order allow,deny
deny from all
</files>
<files .htaccess>
order allow,deny
deny from all
</files>
<files readme.html>
order allow,deny
deny from all
</files>
<files license.txt>
order allow,deny
deny from all
</files>
# Disable directory listing
Options -Indexes
# Protect wp-includes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>
# Block xmlrpc.php
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>
# Limit upload size
LimitRequestBody 10240000
# Protection against SQL injection and XSS
<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} ^(.*)(union|select|insert|drop|delete|update)(.*)$ [NC]
RewriteRule ^(.*)$ index.php [F,L]
</IfModule>
# Force HTTPS
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# Hotlink protection
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [NC,F,L]
# 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/jаvascript "access plus 1 month"
ExpiresDefault "access plus 7 days"
</IfModule>
# GZIP compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/jаvascript
</IfModule>
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
php.ini and .user.ini: PHP Configuration
PHP settings affect code execution security.
Creating .user.ini for WordPress
On PHP-FPM servers, create .user.ini in site root:
nano /home/username/public_html/.user.ini
Disabling Dangerous PHP Functions
Prohibit dangerous function execution:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
Warning: some plugins may use these functions. Test after applying.
Limiting File Uploads
Set upload file limits:
upload_max_filesize = 10M
post_max_size = 10M
max_execution_time = 300
max_input_time = 300
memory_limit = 256M
Disabling Error Display
Hide PHP errors from visitors:
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /home/username/logs/php_errors.log
Restricting Filesystem Access
Limit PHP access to site directory only:
open_basedir = /home/username/public_html:/tmp
Disabling Remote Files
Prohibit remote file loading:
allow_url_fopen = Off
allow_url_include = Off
Warning: some plugins (e.g., import) may require allow_url_fopen = On.
Enabling Secure Cookie Mode
Protect cookies from XSS:
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_only_cookies = 1
Complete .user.ini for Security
upload_max_filesize = 10M
post_max_size = 10M
max_execution_time = 300
max_input_time = 300
memory_limit = 256M
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /home/username/logs/php_errors.log
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
allow_url_fopen = Off
allow_url_include = Off
open_basedir = /home/username/public_html:/tmp
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_only_cookies = 1
expose_php = Off
robots.txt: Managing Indexing
The robots.txt file doesn't directly protect but hides administrative areas from search engines.
Creating robots.txt
Create file in site root:
nano /home/username/public_html/robots.txt
Basic robots.txt Configuration for WordPress
User-agent: *
Disallow: /wp-admin/
Disallow: /wp-includes/
Disallow: /wp-content/plugins/
Disallow: /wp-content/themes/
Disallow: /wp-content/cache/
Disallow: /wp-login.php
Disallow: /xmlrpc.php
Allow: /wp-admin/admin-ajax.php
Sitemap: https://example.com/sitemap.xml
Replace example.com with your domain.
wp-content/uploads/.htaccess: Protecting Uploads
Separate .htaccess in uploads directory blocks PHP execution.
Create file:
nano /home/username/public_html/wp-content/uploads/.htaccess
Add content:
<Files *.php>
deny from all
</Files>
<FilesMatch "\.(php|php3|php4|php5|phtml)$">
Order Deny,Allow
Deny from all
</FilesMatch>
Apply changes:
chmod 644 /home/username/public_html/wp-content/uploads/.htaccess
wp-admin/.htaccess: Protecting Admin Panel
Additional wp-admin directory protection.
Create file:
nano /home/username/public_html/wp-admin/.htaccess
Restrict access by IP:
Order Deny,Allow
Deny from all
Allow from 203.0.113.50
Allow from 198.51.100.25
Or password protect (HTTP Basic Auth):
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /home/username/.htpasswd
Require valid-user
Create password file:
htpasswd -c /home/username/.htpasswd admin_username
Enter password when prompted.
index.php: Protection Stubs
Empty index.php files prevent directory listing.
Create stub:
echo "<?php // Silence is golden" > /home/username/public_html/wp-content/index.php
Copy to critical directories:
cp /home/username/public_html/wp-content/index.php /home/username/public_html/wp-content/plugins/
cp /home/username/public_html/wp-content/index.php /home/username/public_html/wp-content/themes/
cp /home/username/public_html/wp-content/index.php /home/username/public_html/wp-content/uploads/
File and Directory Permissions
Proper permissions are the foundation of security.
Recommended Permissions
Set permissions for all files:
find /home/username/public_html/ -type f -exec chmod 644 {} \;
Set permissions for all directories:
find /home/username/public_html/ -type d -exec chmod 755 {} \;
Special permissions for wp-config.php:
chmod 600 /home/username/wp-config.php
Permissions for .htaccess:
chmod 644 /home/username/public_html/.htaccess
File Ownership
Set correct owner (replace username with yours):
chown -R username:username /home/username/public_html/
For PHP-FPM servers, owner should match PHP-FPM user.
Checking Permissions
Check critical file permissions:
ls -la /home/username/public_html/ | grep -E "wp-config|\.htaccess"
Monitoring Configuration File Changes
Track unauthorized file modifications.
Creating Checksums
Save checksums of important files:
md5sum /home/username/wp-config.php > /home/username/checksums.txt
md5sum /home/username/public_html/.htaccess >> /home/username/checksums.txt
md5sum /home/username/public_html/wp-admin/.htaccess >> /home/username/checksums.txt
Periodically verify:
md5sum -c /home/username/checksums.txt
Automating Checks via Cron
Create check script:
nano /home/username/check_files.sh
Script content:
#!/bin/bash
CHECKSUM_FILE="/home/username/checksums.txt"
ALERT_EMAIL="admin@example.com"
if ! md5sum -c $CHECKSUM_FILE > /dev/null 2>&1; then
echo "ALERT: Configuration files have been modified!" | mail -s "WordPress Security Alert" $ALERT_EMAIL
fi
Make script executable:
chmod +x /home/username/check_files.sh
Add to cron for daily checks:
crontab -e
Add line:
0 3 * * * /home/username/check_files.sh
Script runs daily at 3:00 AM.
Backing Up Configuration Files
Always maintain backups before changes.
Creating Backups
Copy important files:
cp /home/username/wp-config.php /home/username/backups/wp-config.php.backup
cp /home/username/public_html/.htaccess /home/username/backups/.htaccess.backup
With date in filename:
cp /home/username/wp-config.php /home/username/backups/wp-config.php.$(date +%Y%m%d)
cp /home/username/public_html/.htaccess /home/username/backups/.htaccess.$(date +%Y%m%d)
Automated Backup
Create backup script:
nano /home/username/backup_configs.sh
Content:
#!/bin/bash
BACKUP_DIR="/home/username/backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
cp /home/username/wp-config.php $BACKUP_DIR/wp-config.php.$DATE
cp /home/username/public_html/.htaccess $BACKUP_DIR/.htaccess.$DATE
cp /home/username/public_html/.user.ini $BACKUP_DIR/.user.ini.$DATE
find $BACKUP_DIR -type f -mtime +30 -delete
echo "Backup completed: $DATE"
Make executable:
chmod +x /home/username/backup_configs.sh
Add to cron for weekly backup:
crontab -e
Add:
0 2 * * 0 /home/username/backup_configs.sh
Testing Security Configuration
After applying settings, test the site.
Checking Protected File Access
Try opening in browser:
https://example.com/wp-config.php
https://example.com/.htaccess
https://example.com/readme.html
https://example.com/wp-content/uploads/test.php
All should return 403 Forbidden error.
Checking HTTPS Redirect
Open HTTP version of site:
http://example.com
Should automatically redirect to HTTPS.
Checking Access Permissions
Check critical file permissions:
ls -l /home/username/wp-config.php
ls -l /home/username/public_html/.htaccess
wp-config.php should have 600 permissions, .htaccess — 644.
Checking Site Functionality
Ensure site works:
- Homepage loads
- Can login to admin
- Image uploads work
- Forms submit
If something broke, rollback recent changes from backup.
Troubleshooting
Problem: Internal Server Error 500
Cause: error in .htaccess.
Solution:
Rename .htaccess:
mv /home/username/public_html/.htaccess /home/username/public_html/.htaccess.bak
Check if site works. If yes — error in .htaccess.
Add rules gradually, checking after each.
Problem: Images Won't Load
Cause: too strict permissions or PHP blocking in uploads.
Solution:
Check uploads directory permissions:
ls -ld /home/username/public_html/wp-content/uploads/
Should be 755. Fix:
chmod 755 /home/username/public_html/wp-content/uploads/
Check .htaccess in uploads — ensure only PHP is blocked, not images.
Problem: Admin Panel Not Working
Cause: IP blocking or HTTP Basic Auth.
Solution:
Check .htaccess in wp-admin:
cat /home/username/public_html/wp-admin/.htaccess
If IP restriction exists, add your IP to Allow from.
Or temporarily disable protection:
mv /home/username/public_html/wp-admin/.htaccess /home/username/public_html/wp-admin/.htaccess.bak
Problem: Plugins Won't Install
Cause: DISALLOW_FILE_MODS enabled.
Solution:
Comment out in wp-config.php:
// define('DISALLOW_FILE_MODS', true);
Or install plugins via SSH:
cd /home/username/public_html/wp-content/plugins/
wget https://downloads.wordpress.org/plugin/plugin-name.zip
unzip plugin-name.zip
rm plugin-name.zip
Configuration File Security Checklist
Go through this list to verify protection:
wp-config.php:
- File moved outside public_html
- Access permissions 600
- Unique database table prefix
- DISALLOW_FILE_EDIT enabled
- Secret keys updated
- FORCE_SSL_ADMIN enabled
- WP_DEBUG disabled in production
.htaccess:
- wp-config.php protected
- .htaccess protected
- wp-includes blocked
- Directory listing disabled
- xmlrpc.php blocked
- SQL injection protection
- Forced HTTPS
- Caching configured
.user.ini:
- display_errors = Off
- Dangerous functions disabled
- Upload limits set
- open_basedir configured
Permissions:
- Files: 644
- Directories: 755
- wp-config.php: 600
Additional:
- robots.txt created
- index.php stubs in critical directories
- Backups configured
- Change monitoring enabled
Conclusion
WordPress security through configuration files is the first and most important line of defense. Proper configuration of wp-config.php, .htaccess, and other configuration files blocks most automated attacks and complicates life for potential attackers.
Key principles:
Defense in depth. Combine multiple protection layers — at PHP, web server, and filesystem levels.
Regular updates. Change secret keys every 3-6 months, update security rules.
Monitoring. Track configuration file changes, check logs.
Backup. Always maintain current backups before making changes.
Testing. After each change, verify site functionality.
Invest time in properly configuring configuration files once — and sleep peacefully knowing your WordPress site is protected at the fundamental level.