WordPress Security
Secure your WordPress site by taking it offline while using PhantomWP as a headless CMS.
WordPress Security
When using PhantomWP with WordPress as a headless CMS, you have the option to completely block public access to your WordPress installation. This protects against:
- Bots and scrapers accessing your content
- Vulnerabilities in WordPress plugins or themes
- Direct access to potentially malicious PHP files
- Brute force attacks on wp-login.php
This is completely optional. PhantomWP works fine with a public WordPress site. Only set this up if you want maximum security.
How It Works
PhantomWP uses a secret header (X-PhantomWP-Secret) for all requests to your WordPress REST API. By configuring your server to block requests without this header, you effectively take your WordPress site offline while still allowing PhantomWP to access your content.
X-PhantomWP-Secret header?→ALLOW ✓Setup Steps
Step 1: Get Your Secret Key
- Open your project in PhantomWP IDE
- Click the WordPress icon (or go to WordPress Settings)
- Connect to your WordPress site
- Expand the Security section
- Copy your secret key (starts with
pwp_)
Step 2: Configure Your Browser (For Admin Access)
To access your WordPress admin panel (/wp-admin) after blocking public access, you need to add the secret header to your browser.
Install ModHeader Extension:
Configure ModHeader:
- Click the ModHeader icon in your browser
- Add a new header:
- Name:
X-PhantomWP-Secret - Value: Your secret key (e.g.,
pwp_a1b2c3d4...)
- Name:
- (Optional) Add a filter to only apply to your WordPress domain
Now you can browse your WordPress site normally—including wp-admin—and the header will be automatically added.
Step 3: Block Requests Without the Header
Choose one of the following options based on your hosting setup:
Option A: Cloudflare Worker (Recommended)
If your site uses Cloudflare, this is the most secure option. Requests are blocked at the edge before they ever reach your server.
Create a new Worker:
- Go to your Cloudflare dashboard
- Navigate to Workers & Pages → Create Worker
- Paste this code:
export default {
async fetch(request, env, ctx) {
const secret = request.headers.get('X-PhantomWP-Secret');
const expectedSecret = 'YOUR_SECRET_KEY'; // Replace with your key
if (secret !== expectedSecret) {
return new Response('Forbidden', {
status: 403,
headers: { 'Content-Type': 'text/plain' }
});
}
// Forward the request to your origin
return fetch(request);
}
}- Deploy the Worker
- Go to your domain settings and add a Route that maps your WordPress domain to this Worker
Option B: Cloudflare Access (Zero Trust)
For enterprise-level security, use Cloudflare Access:
- Go to Zero Trust → Access → Applications
- Create a new Self-hosted application
- Add your WordPress domain
- Create a policy:
- Policy name: PhantomWP Access
- Action: Bypass
- Include: Service Token (create one for PhantomWP)
- Configure PhantomWP to use the Service Token
This approach also lets you add additional authentication methods (email, Google, etc.) for admin access.
Option C: nginx Configuration
Add this to your nginx server block:
# Block requests without the secret header
set $block_request 1;
# Allow requests with valid secret
if ($http_x_phantomwp_secret = "YOUR_SECRET_KEY") {
set $block_request 0;
}
# Return 403 for blocked requests
if ($block_request) {
return 403;
}Full example with WordPress:
server {
listen 80;
server_name your-wordpress-site.com;
root /var/www/wordpress;
# Security: Block requests without secret header
set $block_request 1;
if ($http_x_phantomwp_secret = "YOUR_SECRET_KEY") {
set $block_request 0;
}
if ($block_request) {
return 403;
}
# Standard WordPress configuration
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}After editing, reload nginx:
sudo nginx -t && sudo systemctl reload nginxOption D: Apache .htaccess
Add this to your WordPress .htaccess file (at the beginning, before the WordPress rules):
# PhantomWP Security - Block requests without secret header
RewriteEngine On
RewriteCond %{HTTP:X-PhantomWP-Secret} !^YOUR_SECRET_KEY$
RewriteRule ^ - [F]Full .htaccess example:
# PhantomWP Security
RewriteEngine On
RewriteCond %{HTTP:X-PhantomWP-Secret} !^YOUR_SECRET_KEY$
RewriteRule ^ - [F]
# 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 WordPressVerifying Your Setup
After configuring your server, test that blocking is working:
Without header (should be blocked):
curl -I https://your-wordpress-site.com
# Expected: HTTP 403 ForbiddenWith header (should work):
curl -I -H "X-PhantomWP-Secret: YOUR_SECRET_KEY" https://your-wordpress-site.com
# Expected: HTTP 200 OKTroubleshooting
I'm locked out of wp-admin
- Make sure ModHeader is installed and enabled
- Verify the header name is exactly
X-PhantomWP-Secret(case-sensitive) - Check that your secret key matches exactly (no extra spaces)
- Try disabling other browser extensions that might interfere
PhantomWP can't connect to WordPress
- Verify your WordPress URL is correct in PhantomWP settings
- Make sure you saved the configuration (secret is generated on save)
- Check your server logs for any errors
I want to allow some paths without the header
Modify your server config to exclude certain paths. For example, in nginx:
# Allow health checks without secret
location /health {
return 200 'OK';
}
# Block everything else without secret
location / {
set $block_request 1;
if ($http_x_phantomwp_secret = "YOUR_SECRET_KEY") {
set $block_request 0;
}
if ($block_request) {
return 403;
}
# ... rest of config
}Rotating Your Secret Key
If you need to change your secret key:
- Generate a new key in PhantomWP WordPress Settings
- Update your server configuration with the new key
- Update ModHeader in your browser with the new key
- Test that everything works before removing the old key
Always test the new key before removing the old one from your server config. You can temporarily allow both keys during migration.
Security Best Practices
- Use HTTPS - Always use HTTPS for your WordPress site to prevent header interception
- Keep WordPress updated - Even with this protection, keep WordPress and plugins updated
- Use strong passwords - Your WordPress admin password should still be strong
- Regular backups - Maintain regular backups of your WordPress database and files
- Monitor access logs - Periodically check your server logs for suspicious activity