How to Rate Limit Requests to WordPress Using Traefik
By Tony Mackay ·
This tutorial shows you how to setup rate limiting using Traefik so you can prevent excessive traffic from hitting your WordPress site.
In my last post, I wrote how to deploy a WordPress blog with Docker and Docker Compose. The Compose configuration used Traefik as a proxy to the WordPress container and I mentioned one of the reasons for using Traefik, is so you can rate limit requests to WordPress.
Rate limiting helps keep your website running efficiently and it can help prevent DDoS attacks from taking your website down. Let’s take a look at how to implement rate limiting with Traefik.
Before we begin
Follow the steps in this tutorial so that you can deploy WordPress using Docker Compose. Once you have completed the steps, you should have a docker-compose.yml file that looks like this:
version: '3'
services:
traefik:
image: traefik:v2.3.6
restart: always
command:
- --accesslog
- --api.insecure=true
- --providers.docker
- --providers.docker.exposedbydefault=false
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 80:80
- 443:443
- 8080:8080
wordpress:
image: wordpress:php7.4-apache
depends_on:
- mysql
restart: always
environment:
- WORDPRESS_DB_HOST=mysql
- WORDPRESS_DB_USER=root
- WORDPRESS_DB_NAME=wordpress
- WORDPRESS_DB_PASSWORD=password
expose:
- 80
labels:
- traefik.enable=true
- traefik.http.routers.wordpress.rule=Host(`wordpressdemo.net`)
mysql:
image: mysql:8.0.22
restart: always
environment:
- MYSQL_DATABASE=wordpress
- MYSQL_ROOT_PASSWORD=password
Now let’s change it to enable rate limiting.
Enable Rate Limiting
Traefik has a RateLimit middleware which we can configure by adding labels to the wordpress
service in our Compose file.
Open docker-compose.yml
and add the following labels.
- traefik.http.middlewares.wordpress-ratelimit.ratelimit.average=10
- traefik.http.middlewares.wordpress-ratelimit.ratelimit.burst=10
- traefik.http.middlewares.wordpress-ratelimit.ratelimit.period=1
You will need to experiment with the average
, burst
and period
values to see what works best for your website. To get an understanding of what each value does, you can read the Traefik RateLimit documentation.
In the example above, Traefik is configured to limit the amount of requests to 10 per second. Bear in mind, multiple requests can come from the same IP address that are genuine, so you might want to increase this amount.
Once we have defined the RateLimit middleware settings, we need to apply them to a route. You can do this by adding the following label:
- traefik.http.routers.wordpress.middlewares=wordpress-ratelimit@docker
This will apply the wordpress-ratelimit
to the wordpress
route when we start the containers in the next step.
Start Containers
Let’s check to see if the rate limiting configuration has been applied by starting our containers and opening the Traefik web UI.
Run:
docker-compose up
Open a browser and go to: http://wordpressdemo.net:8080/dashboard/#/http/routers/wordpress@docker

As you can see from the screenshot above, rate limiting is enabled on the route that handles all traffic to the domain wordpressdemo.net
.
Test Rate Limit
Using a load testing utility we can test to see if any requests get rate limited. The following command uses hey to run 11 concurrent requests:
hey -n 11 -c 11 http://wordpressdemo.net/
As you can see from the output below, 10 requests make it through and 1 fails with a status code of 429.
Summary:
Total: 3.1476 secs
Slowest: 3.1458 secs
Fastest: 0.2099 secs
Average: 2.6106 secs
Requests/sec: 3.4947
Total data: 17 bytes
Size/request: 1 bytes
Response time histogram:
0.210 [1] |■■■■■
0.503 [0] |
0.797 [0] |
1.091 [0] |
1.384 [0] |
1.678 [0] |
1.971 [0] |
2.265 [0] |
2.559 [0] |
2.852 [8] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
3.146 [2] |■■■■■■■■■■
Latency distribution:
10% in 2.7707 secs
25% in 2.7718 secs
50% in 2.7848 secs
75% in 3.1440 secs
90% in 3.1458 secs
0% in 0.0000 secs
0% in 0.0000 secs
Details (average, fastest, slowest):
DNS+dialup: 0.1106 secs, 0.2099 secs, 3.1458 secs
DNS-lookup: 0.0033 secs, 0.0030 secs, 0.0035 secs
req write: 0.0003 secs, 0.0000 secs, 0.0024 secs
resp wait: 1.3690 secs, 0.0951 secs, 2.1073 secs
resp read: 0.0013 secs, 0.0004 secs, 0.0024 secs
Status code distribution:
[200] 10 responses
[429] 1 responses
Aggressively Rate Limit Login Page
Another thing you might want to do is create another rate limit rule and apply it to a route that makes POST requests to wp-login.php
. This rule could be made more aggressive to help prevent brute force hacking attempts. For example, you could make it 5 requests per minute with a config like the following:
- traefik.http.routers.wordpress-login.rule=Host(`wordpressdemo.net`) && PathPrefix(`/wp-login.php`) && Method(`POST`)
- traefik.http.middlewares.wordpress-login-ratelimit.ratelimit.average=5
- traefik.http.middlewares.wordpress-login-ratelimit.ratelimit.burst=1
- traefik.http.middlewares.wordpress-login-ratelimit.ratelimit.period=1m
- traefik.http.routers.wordpress-login.middlewares=wordpress-login-ratelimit@docker
Don’t DoS Legit Traffic
If your site is running behind a load balancer or a proxy service like Cloudflare, the rate limit rules above might block all requests because all traffic will be seen as coming from a single IP address. This can be solved by using the depth
parameter to make Traefik look in the X-Forwarded-For
header for the visitors real IP address.
Conclusion
Traefik has a lot of middleware that allow you to configure the proxy in different ways. This tutorial showed you how to use the rate limiter to reduce load on the back end. This helps prevent DDoS attacks from taking down your site or brute force login attempts. We demonstrated this with an example that protects a WordPress site running in a Docker container launched with Compose.
Read Next
- The Best Books to Learn Virtualization, Linux and Automation
- Recommended Tools and Software for System Administrators
- Deploy a WordPress Blog with Docker Compose and Traefik
- Using Traefik to Route HTTP Requests to Multiple Docker Microservices
Tony is the founder and editor of GraspingTech, a blog that helps developers and business owners deploy modern web applications to the cloud. He has written over one hundred tutorials which have been read by more than a million people. Some of the topics he covers are Linux, Virtualization, DevOps and web development.