Add a layer of protection between your static HTML frontend and the WordPress API as backend. This will ensure no direct calls can be made against WordPress and gives you control over what kind of requests you allow.
In our previous article “Unleash the WordPress REST API” I showed you how I was able to separate WordPress with a simple HTML frontend.
As I am making AJAX calls directly to my WordPress installation, I still am vulnerable for attacks and my architecture was not able to scale properly. To mitigate this I add a load-balancing reverse proxy and application gateway in the mix using Nginx.
Configure the proxy
Here’s my Nginx configuration nginx.conf
to offload the WordPress service from the static HTML frontend.
events {
}
http {
upstream api {
server wordpress:80;
}
client_max_body_size 20m;
proxy_cache_path /etc/nginx/cache keys_zone=wp:500m max_size=1000m;
server {
proxy_cache wp;
proxy_cache_key $request_method$request_uri;
proxy_cache_min_uses 1;
proxy_cache_methods GET;
proxy_cache_valid 200 1y;
location /api {
if ($request_method != GET) {
return 405;
}
proxy_pass http://api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
rewrite ^/api(.*)$ /wp-json$1 break;
}
}
}
I create an endpoint /api
that will be the gatekeeper for connecting with WordPress. If the request is not a GET
request, it will be rejected. And only requests for /api
will be rewritten to /wp-json
on the WordPress backend REST API. All else is ignored.
Add the service for Docker
So in my docker-compose.yml
I have added a new nginx service and separate the networks for the WordPress backend with the database and the proxy with the WordPress instance.
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
networks:
- db-net
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
networks:
- db-net
- wp-net
nginx:
depends_on:
- wordpress
image: nginx:latest
volumes:
- ./conf/nginx.conf:/etc/nginx/nginx.conf
ports:
- 8001:80
restart: always
networks:
- wp-net
volumes:
db_data: {}
networks:
wp-net:
db-net:
Modify the URI in the static HTML page
In the static HTML file we created earlier, I need to change var backendUri = "http://localhost:8000/wp-json";
into var backendUri = "http://localhost:8001/api";
to access the WordPress instance through the proxy.

In my next article I will start serving the HTML page from an Nginx container because now I’m just loading the file straight from my filesystem running a local webserver.