{"slug":"htaccess-directives-wordpress","title":".htaccess Directives for WordPress","tags":["htaccess","apache","security","caching","redirects"],"agent_summary":"Production-ready .htaccess directives for WordPress: standard rewrite rules, security hardening, browser caching, GZIP compression, HTTPS forcing, and PHP limits on shared hosting.","trigger_phrases":["htaccess wordpress","wordpress htaccess rewrite","wordpress security htaccess","block xmlrpc","force https htaccess","htaccess caching wordpress","htaccess gzip"],"runnable":true,"markdown":"\nThe `.htaccess` file at the WordPress root controls rewrites, security, caching, and redirects. Every production site needs a hardened `.htaccess`.\n\n## Standard WordPress Rewrite Rules\n\n```apache\n# BEGIN WordPress\n<IfModule mod_rewrite.c>\nRewriteEngine On\nRewriteBase /\nRewriteRule ^index\\.php$ - [L]\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule . /index.php [L]\n</IfModule>\n# END WordPress\n```\n\n## Security Hardening\n\n```apache\n# Block wp-config.php access\n<files wp-config.php>\norder allow,deny\ndeny from all\n</files>\n\n# Block xmlrpc.php (if not using Jetpack or remote publishing)\n<Files xmlrpc.php>\norder deny,allow\ndeny from all\n</Files>\n\n# Disable directory browsing\nOptions -Indexes\n\n# Block sensitive file types\n<FilesMatch \"\\.(htaccess|htpasswd|ini|log|sh|sql|bak)$\">\nOrder Allow,Deny\nDeny from all\n</FilesMatch>\n\n# Block script injection via query string\nOptions +FollowSymLinks\nRewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]\nRewriteCond %{QUERY_STRING} GLOBALS(=|\\[|\\%[0-9A-Z]{0,2}) [OR]\nRewriteCond %{QUERY_STRING} _REQUEST(=|\\[|\\%[0-9A-Z]{0,2})\nRewriteRule ^(.*)$ index.php [F,L]\n```\n\n## Browser Caching\n\n```apache\n<IfModule mod_expires.c>\nExpiresActive On\nExpiresByType image/jpg \"access plus 1 year\"\nExpiresByType image/jpeg \"access plus 1 year\"\nExpiresByType image/png \"access plus 1 year\"\nExpiresByType image/webp \"access plus 1 year\"\nExpiresByType text/css \"access plus 1 month\"\nExpiresByType application/javascript \"access plus 1 month\"\n</IfModule>\n```\n\n## GZIP Compression\n\n```apache\n<IfModule mod_deflate.c>\nAddOutputFilterByType DEFLATE text/plain text/html text/xml text/css\nAddOutputFilterByType DEFLATE application/xml application/xhtml+xml application/rss+xml\nAddOutputFilterByType DEFLATE application/javascript application/x-javascript\n</IfModule>\n```\n\n## Force HTTPS\n\n```apache\nRewriteEngine On\nRewriteCond %{HTTPS} off\nRewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]\n```\n\n## PHP Limits (Shared Hosting)\n\n```apache\nphp_value memory_limit 256M\nphp_value max_execution_time 300\nphp_value upload_max_filesize 64M\nphp_value post_max_size 64M\n```\n","html":"<p>The <code>.htaccess</code> file at the WordPress root controls rewrites, security, caching, and redirects. Every production site needs a hardened <code>.htaccess</code>.</p>\n<h2>Standard WordPress Rewrite Rules</h2>\n<pre><code class=\"language-apache\"># BEGIN WordPress\n&#x3C;IfModule mod_rewrite.c>\nRewriteEngine On\nRewriteBase /\nRewriteRule ^index\\.php$ - [L]\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule . /index.php [L]\n&#x3C;/IfModule>\n# END WordPress\n</code></pre>\n<h2>Security Hardening</h2>\n<pre><code class=\"language-apache\"># Block wp-config.php access\n&#x3C;files wp-config.php>\norder allow,deny\ndeny from all\n&#x3C;/files>\n\n# Block xmlrpc.php (if not using Jetpack or remote publishing)\n&#x3C;Files xmlrpc.php>\norder deny,allow\ndeny from all\n&#x3C;/Files>\n\n# Disable directory browsing\nOptions -Indexes\n\n# Block sensitive file types\n&#x3C;FilesMatch \"\\.(htaccess|htpasswd|ini|log|sh|sql|bak)$\">\nOrder Allow,Deny\nDeny from all\n&#x3C;/FilesMatch>\n\n# Block script injection via query string\nOptions +FollowSymLinks\nRewriteCond %{QUERY_STRING} (&#x3C;|%3C).*script.*(>|%3E) [NC,OR]\nRewriteCond %{QUERY_STRING} GLOBALS(=|\\[|\\%[0-9A-Z]{0,2}) [OR]\nRewriteCond %{QUERY_STRING} _REQUEST(=|\\[|\\%[0-9A-Z]{0,2})\nRewriteRule ^(.*)$ index.php [F,L]\n</code></pre>\n<h2>Browser Caching</h2>\n<pre><code class=\"language-apache\">&#x3C;IfModule mod_expires.c>\nExpiresActive On\nExpiresByType image/jpg \"access plus 1 year\"\nExpiresByType image/jpeg \"access plus 1 year\"\nExpiresByType image/png \"access plus 1 year\"\nExpiresByType image/webp \"access plus 1 year\"\nExpiresByType text/css \"access plus 1 month\"\nExpiresByType application/javascript \"access plus 1 month\"\n&#x3C;/IfModule>\n</code></pre>\n<h2>GZIP Compression</h2>\n<pre><code class=\"language-apache\">&#x3C;IfModule mod_deflate.c>\nAddOutputFilterByType DEFLATE text/plain text/html text/xml text/css\nAddOutputFilterByType DEFLATE application/xml application/xhtml+xml application/rss+xml\nAddOutputFilterByType DEFLATE application/javascript application/x-javascript\n&#x3C;/IfModule>\n</code></pre>\n<h2>Force HTTPS</h2>\n<pre><code class=\"language-apache\">RewriteEngine On\nRewriteCond %{HTTPS} off\nRewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]\n</code></pre>\n<h2>PHP Limits (Shared Hosting)</h2>\n<pre><code class=\"language-apache\">php_value memory_limit 256M\nphp_value max_execution_time 300\nphp_value upload_max_filesize 64M\nphp_value post_max_size 64M\n</code></pre>\n"}