DEV Community

禾

Posted on

How I Added a Self-Hosted WAF to My Docker Stack in 15 Minutes

Docker makes deploying applications incredibly easy. Protecting them is another story.

I recently added a self-hosted Web Application Firewall (WAF) to one of my Docker-based applications—not because I was under a targeted attack, but because I was tired of the constant stream of bots, vulnerability scanners, and automated probes hitting my server.

In this article, I'll walk through how I deployed SafeLine WAF in about 15 minutes, without changing a single line of application code.


I run several small web applications on a single VPS.

Nothing enterprise-grade—just Docker, Nginx, and a few personal projects.

A while back, I started paying closer attention to my access logs. They were full of automated requests targeting /wp-admin, SQL injection payloads hidden in query strings, and brute-force attempts against endpoints that didn't even exist.

The moment your server is exposed to the Internet, it's already being scanned.

I wanted a lightweight WAF that could sit in front of my existing reverse proxy without forcing me to rewrite applications or change my deployment workflow.

After trying a few options, I settled on SafeLine WAF. It's open source, Docker-based, and surprisingly straightforward to deploy.

My Deployment Architecture

Before:

Internet
    │
    ▼
Nginx
    │
    ▼
Docker Applications
Enter fullscreen mode Exit fullscreen mode

After:

Internet
    │
    ▼
SafeLine WAF
    │
    ▼
Nginx
    │
    ▼
Docker Applications
Enter fullscreen mode Exit fullscreen mode

SafeLine acts as a reverse proxy, inspecting every incoming request before forwarding it to Nginx.

Prerequisites

  • Ubuntu 20.04+
  • Docker & Docker Compose
  • Nginx / Traefik / Caddy
  • 2 GB RAM and 2 CPU cores

Step 1: Install

bash -c "$(curl -fsSLk https://waf.chaitin.com/release/latest/setup.sh)"
Enter fullscreen mode Exit fullscreen mode

Verify:

docker ps | grep safeline
Enter fullscreen mode Exit fullscreen mode

Step 2: Access the Dashboard

https://<your-server-ip>:9443
Enter fullscreen mode Exit fullscreen mode

Change the generated admin password after your first login.

Step 3: Route Traffic

Move Nginx to another port (e.g. 8080) and configure SafeLine:

Setting Example
Domain your-domain.com
Upstream http://127.0.0.1:8080
TLS Optional

Traffic becomes:

Internet
    │
    ▼
SafeLine
    │
    ▼
Nginx
    │
    ▼
Application
Enter fullscreen mode Exit fullscreen mode

What I Found Most Useful

Anti-Bot Protection

Suspicious clients are challenged before reaching the application.

Centralized Rate Limiting

Different endpoints can have different rate limits from one place.

Better Visibility

The dashboard makes SQL injection attempts, XSS probes, brute-force attacks and automated scans immediately visible.

When I Wouldn't Use It

  • Already behind a managed cloud WAF
  • Very limited server resources
  • Entirely serverless
  • Don't want another service to maintain

Final Thoughts

SafeLine gave me application-layer protection without changing my applications.

More importantly, it gave me visibility into what my server experiences every day.

Want to Explore SafeLine?

How are you protecting your Docker applications today?

Top comments (0)