How to Protect WordPress Admin with Nginx

Overview Add double-layer protection to WordPress admin using Nginx Basic Auth: Layer 1: Nginx Basic Auth (browser popup) Layer 2: WordPress username/password login Prerequisites Nginx installed on server apache2-utils package installed (for password generation) WordPress admin access Step-by-Step Guide Step 1: Install Password Tool # Ubuntu/Debian sudo apt install apache2-utils # CentOS/RHEL sudo yum install httpd-tools […]


Overview

Add double-layer protection to WordPress admin using Nginx Basic Auth:

  1. Layer 1: Nginx Basic Auth (browser popup)
  2. Layer 2: WordPress username/password login

Prerequisites

  • Nginx installed on server
  • apache2-utils package installed (for password generation)
  • WordPress admin access

Step-by-Step Guide

Step 1: Install Password Tool

# Ubuntu/Debian
sudo apt install apache2-utils

# CentOS/RHEL
sudo yum install httpd-tools

Step 2: Generate Basic Auth Password

# Create password file (use -c flag for first time)
sudo htpasswd -c /etc/nginx/.htpasswd_wordpress admin

# Enter your password twice
New password:
Re-type new password:
Adding password for user admin

Password file details:

  • Path: /etc/nginx/.htpasswd_wordpress
  • Format: username:encrypted_password
  • Add new user: htpasswd /etc/nginx/.htpasswd_wordpress username

Step 3: Configure Nginx

Edit your site configuration (LNMP path):

nano /usr/local/nginx/conf/vhost/your-domain.conf

Add/modify these settings:

server {
listen 80;
listen [::]:80;
server_name wordpress.yourdomain.com;
root /home/wwwroot/wordpress.yourdomain.com;
index index.php index.html;

# Admin directory protection
location /wp-admin/ {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd_wordpress;
try_files $uri $uri/ /index.php?$args;
}

# Login page protection
location ~ ^/wp-login\.php {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd_wordpress;
include enable-php-pathinfo.conf;
}
}

Step 4: Test and Reload

# Test configuration
nginx -t

# Reload Nginx (LNMP)
lnmp nginx reload

# Or standard way
systemctl reload nginx

Step 5: Test Access

  1. Visit: https://wordpress.yourdomain.com/wp-admin/
  2. Browser shows login popup
  3. Enter admin and password from Step 2
  4. WordPress login page appears
  5. Enter WordPress admin credentials

Password Management

Change Password

# Regenerate password
htpasswd -c -b /etc/nginx/.htpasswd_wordpress admin your-new-password

# Reload config
nginx -t && lnmp nginx reload

Add New User

htpasswd /etc/nginx/.htpasswd_wordpress username

View Password File

cat /etc/nginx/.htpasswd_wordpress

FAQ

Q: Forgot password?

A: Cannot decrypt. Reset with: htpasswd -c -b /etc/nginx/.htpasswd_wordpress admin new-password

Q: 502 Bad Gateway error?

A: Check PHP-FPM: systemctl status php-fpm, verify socket path.

Q: Mobile needs authentication?

A: Yes, Basic Auth is HTTP standard, all clients show login popup.

Complete Configuration Example

server {
listen 80;
listen [::]:80;
server_name wordpress.yourdomain.com;
root /home/wwwroot/wordpress.yourdomain.com;
index index.php index.html;

# Cloudflare real IP (optional)
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 199.27.128.0/21;
real_ip_header CF-Connecting-IP;

# Frontend redirects to Vercel
location / {
if ($uri !~ ^/wp-admin/) {
return 302 https://yourdomain.com/blog$uri;
}
try_files $uri $uri/ /index.php?$args;
}

# Admin Basic Auth protection
location /wp-admin/ {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd_wordpress;
try_files $uri $uri/ /index.php?$args;
}

# Login page Basic Auth protection
location ~ ^/wp-login\.php {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd_wordpress;
include enable-php-pathinfo.conf;
}

# API endpoint
location /wp-json/ {
try_files $uri $uri/ /index.php?$args;
}

# PHP processing
location ~ \.php$ {
include enable-php-pathinfo.conf;
}

# Block sensitive files
location = /wp-config.php {
deny all;
}
location ~ /\.(?!well-known).* {
deny all;
}
}

Security Recommendations

  1. Strong password: At least 16 characters, mix of upper/lowercase, numbers, special chars
  2. Regular rotation: Change every 3-6 months
  3. IP restrictions: If you have fixed IP, limit access source
  4. Backup password filecp /etc/nginx/.htpasswd_wordpress /backup/path/
  5. Monitor access logs: Check Nginx logs for suspicious activity

Use Cases

  • ✅ Internal server exposed via Cloudflare Tunnel
  • ✅ Don’t want to expose WordPress frontend
  • ✅ Need to protect admin login
  • ✅ Multiple admins need separate accounts

Important Notes

  • Basic Auth credentials sent with every request, use with HTTPS
  • Cloudflare Tunnel encrypts traffic
  • Keep password file secure, don’t commit to version control