Deploy an edge WAF with the edge-waf template
Coming from another cloud?
▸AWS·WAF
This Quake AI feature maps to AWS’s WAF.
Deploy an edge WAF with the edge-waf template
Stand up a SafeLine L7 web application firewall on one Quake AI instance using the validated OpenTofu template edge-waf. You apply the template, launch a private backend on the same subnet, configure the protected site in the SafeLine dashboard, enable managed rules in blocking mode, confirm an injection probe is blocked, and lock the backend security group to the WAF.
The WAF holds the only public floating IP. The backend stays on the private subnet with no address on the internet. You operate both instances yourself; this is a regional L7 WAF you run, not a CDN or volumetric DDoS scrubber.
Monthly cost estimate
Pricing calculator ↗Sized as a custom package on shared vCPU.
Partial estimate: Monthly total for the required template above. Use the configurator below to add optional pieces and see the total update.
What each resource is for
Waf
s1a.small · 2 shared vCPU, 2 GiB RAM, 0.5 Gbps
s1a.small
s1a.small · 2 shared vCPU, 2 GiB RAM, 0.5 Gbps
Compute shown per role at custom-package rates ($29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM). The headline above is the billed total: the cheaper of a named plan and the custom package, plus add-ons.
Included in baseline
s1a.small
2 shared vCPU, 2 GiB RAM, 0.5 Gbps
s1a.small
2 shared vCPU, 2 GiB RAM, 0.5 Gbps
Compute + RAM rate basis
4 vCPU + 4 GiB RAM at $29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM (regular). Totals apply the flat −$5/mo package promotion.
Block storage (40 GiB)
40 GiB at $0.08/GiB/mo
Public IP (included)
1 included with the custom package
Package promotional discount
Flat −$5.00/mo on the custom package (same promotion as named plans).
Included at no charge
These line items are zero on Quake AI. Many other providers meter them separately.
Data transfer (inbound and outbound)
Unlimited data transfer on every plan; Quake AI does not meter per-GB egress.
AWS, GCP, and Azure meter outbound transfer per GB. DigitalOcean and Hetzner include an allowance on compute plans, then charge overage.
Learn morePrivate networking
Private networks, subnets, Neutron routers, and security groups are included with the plan.
VPC objects are usually free to create elsewhere, but NAT gateways bill hourly plus per-GB processed. Quake AI uses router SNAT with no separate NAT line item.
Control-plane API requests
OpenStack API calls for provisioning and management are included.
Some managed services on other clouds meter API calls or charge for premium control-plane features.
Pricing data last validated: . For current rates, check quake.ai/pricing.
Prerequisites#
You need:
- OpenTofu 1.6.0 or later (or Terraform 1.6.0 or later) installed locally.
- Your OpenStack credentials sourced into the shell (
source openrc.sh). See the OpenStack CLI guide. - An SSH keypair that already exists in your project. Record its name for the
key_namevariable. - A copy of the
edge-waftemplate directory from the template reference page. - A domain you can point at the WAF floating IP when you enable TLS on the protected site (optional for the HTTP verification steps below).
Step 1: Apply the WAF template#
Copy the template's example variables file and set key_name. Keep the default upstream_host and upstream_port unless you plan a different private address:
cp terraform.tfvars.example terraform.tfvarskey_name = "YOUR_KEY_NAME"
upstream_host = "10.42.0.10"
upstream_port = 8080Initialize, preview, and apply:
tofu init
tofu plan
tofu applyOpenTofu provisions a private network, router, security group, data volume, WAF instance, and floating IP. cloud-init installs Docker, downloads the official SafeLine compose bundle, generates a Postgres password on first boot, and starts SafeLine.
Record the outputs:
tofu output floating_ip
tofu output private_ip
tofu output waf_url
tofu output dashboard_hintWait three to five minutes for cloud-init and SafeLine to finish before you open the dashboard.
Step 2: Launch a private backend on the WAF network#
The template creates network edge-waf-net and subnet edge-waf-subnet (names follow the default app_name). Launch a small backend instance on that subnet at the fixed address 10.42.0.10 with no floating IP.
- Create a security group for the backend:
openstack security group create app-backend-sg \
--description "Private app backend; ingress from WAF only after step 7"Allow SSH from your workstation while you configure the backend (tighten or remove this rule after setup):
openstack security group rule create \
--protocol tcp --dst-port 22 --remote-ip YOUR_IP/32 app-backend-sg- Create a port with the fixed private IP:
SUBNET_ID=$(openstack subnet list -f value -c ID -c Name | awk '/edge-waf-subnet/ {print $1}')
openstack port create \
--network edge-waf-net \
--fixed-ip subnet=$SUBNET_ID,ip-address=10.42.0.10 \
--security-group app-backend-sg \
app-backend-port- Write a short cloud-init file that serves a test page on port 8080:
cat > backend-cloud-init.yaml <<'EOF'
#cloud-config
package_update: true
packages:
- nginx
runcmd:
- |
echo 'backend ok' > /var/www/html/index.html
printf '%s\n' 'server {' ' listen 8080;' ' root /var/www/html;' '}' > /etc/nginx/sites-available/default
systemctl restart nginx
EOF- Launch the backend instance on the port:
openstack server create \
--flavor s1a.small \
--image Ubuntu-24.04 \
--key-name YOUR_KEY_NAME \
--port app-backend-port \
--user-data backend-cloud-init.yaml \
app-backendWait until the instance reports ACTIVE, then confirm the backend answers on the private subnet from the WAF host:
ssh ubuntu@YOUR_FLOATING_IP 'curl -s http://10.42.0.10:8080/'The response body should include backend ok.
Step 3: Retrieve the SafeLine admin credentials#
SafeLine does not ship admin credentials in the repository. SSH to the WAF instance and reset the one-time admin password:
ssh ubuntu@YOUR_FLOATING_IP 'docker exec safeline-mgt resetadmin'Record the username and password the command prints.
Step 4: Open the management dashboard#
Port 9443 is not open in the WAF security group. Reach the dashboard through an SSH tunnel from your workstation:
ssh -L 9443:127.0.0.1:9443 ubuntu@YOUR_FLOATING_IPIn a browser on the same workstation, open https://127.0.0.1:9443/ and sign in with the credentials from step 3. Accept the self-signed certificate warning for the local tunnel.
Step 5: Configure the protected site and upstream#
In the SafeLine dashboard, add a protected site that forwards to your private backend:
- Go to Websites (or Applications) and select Add website.
- Set the site address to your WAF floating IP for now (for example
http://YOUR_FLOATING_IP), or to your domain when you already pointed DNS at the floating IP. - Set the upstream origin to
http://10.42.0.10:8080(the private backend from step 2). - Save the site and wait until SafeLine reports it healthy.
From your workstation, request the WAF floating IP over HTTP:
curl -s http://YOUR_FLOATING_IP/The response should show backend ok. Traffic flows client to WAF floating IP to SafeLine to the private backend.
If SafeLine returns 502, the protected site may still be propagating or the backend is not ready. Retry after a minute. SSH to the WAF host and run docker compose -f /data/safeline/compose.yaml ps to confirm SafeLine containers are up.
Step 6: Enable managed rules in blocking mode#
In the SafeLine dashboard for the site you created:
- Open Protection (or Security policy) for the site.
- Enable the Semantic analysis or Managed rules bundle (the built-in attack-signature set SafeLine ships for community edition).
- Set the action to Block (not detect-only or log-only).
Save the policy. SafeLine now returns HTTP 403 for requests that match the managed rule set.
Step 7: Trigger a blocked attack request#
Send a simple SQL injection probe through the WAF:
curl -s -o /dev/null -w "%{http_code}\n" \
"http://YOUR_FLOATING_IP/?id=1%27%20OR%20%271%27%3D%271"The status code should be 403. A clean request should still pass:
curl -s http://YOUR_FLOATING_IP/The response body should still include backend ok.
Step 8: Lock the backend security group to the WAF#
Restrict the backend so it accepts application traffic only from the WAF security group edge-waf-sg. Remove any rule that opens the application port to 0.0.0.0/0 if you added one during testing.
openstack security group rule create \
--protocol tcp \
--dst-port 8080 \
--remote-group edge-waf-sg \
app-backend-sgList the backend rules and confirm port 8080 allows only the WAF group:
openstack security group rule list app-backend-sg -f tableThe backend has no floating IP, so it is not reachable directly from the internet. Only the WAF can forward traffic to it on the private subnet.
Verify clean traffic still passes through the WAF:
curl -s http://YOUR_FLOATING_IP/The response should still show backend ok.
Step 9: Confirm the origin cannot be reached directly#
The backend never had a public address. After step 8, even a host on your project network cannot reach the application port unless its traffic originates from the WAF security group. If you temporarily attached a floating IP to the backend during testing, remove it before you treat the deployment as complete.
For TLS on the protected site, point your domain's DNS A record at YOUR_FLOATING_IP and enable HTTPS in the SafeLine dashboard for the site. Follow How to point a domain at a Quake AI resource. For certificate background, see How to issue and auto-renew a TLS certificate with Let's Encrypt.
What you built#
- Applied the
edge-waftemplate to provision a private network, WAF security group, data volume, SafeLine host, and floating IP - Launched a private backend on the same subnet at
10.42.0.10with no public address - Configured a protected site in the SafeLine dashboard with managed rules in blocking mode
- Confirmed attack traffic is blocked with a 403 on an injection probe while clean traffic passes
- Locked the backend security group so application traffic accepts only the WAF as its source
Scope of this deployment#
This WAF runs in one region on a VM you operate. It inspects HTTP semantics for injection, cross-site scripting, and related L7 attack patterns. It is not a CDN and it does not absorb L3/L4 volumetric DDoS traffic. Quake AI has no anycast, no global PoPs, and no first-party CDN. For geographic distribution and edge absorption, front the origin with a third-party CDN. For the broader WAF decision (CDN-layer vs self-managed), see front with a WAF.
The walkthrough adds a second small instance for the backend; that VM is not part of the OpenTofu template. Size the WAF with the template defaults; scale the backend independently for your application.
Next steps#
- Edge WAF template: parameters, ports, and resource map
- Front with a WAF: CDN-layer vs self-managed patterns
- Front with a CDN: cache static assets and absorb edge traffic geographically
- Edge reverse proxy template: TLS termination without a dedicated WAF engine
- Security hardening checklist: audit security groups and floating IP usage
Clean up#
When you no longer need the deployment, destroy the OpenTofu stack and delete the backend resources you created in step 2:
tofu destroy
openstack server delete app-backend
openstack port delete app-backend-port
openstack security group delete app-backend-sgRemove any DNS A record you pointed at the WAF floating IP.
See Also
Terraform and OpenTofu on Quake AI
Prerequisite
Networks
Prerequisite
Authoring IaC templates for Quake AI
Shares: Volumes, Security Groups
Deploy an API gateway with the api-gateway template
Shares: Volumes, Security Groups
Deploy a regional edge cache with the edge-cache template
Shares: Volumes, Security Groups