UUSEC WAF on Ubuntu 24.04 on Azure User Guide
Overview
UUSEC WAF (uuWAF) is an open source, self hosted Web Application Firewall and reverse proxy that protects web applications from attacks and exploits. Rather than relying only on lists of regular expression signatures, it combines a semantic detection engine that parses each request the way the target application would, machine learning anomaly detection and runtime application self protection, so it recognises the intent behind SQL injection, cross site scripting, command injection and path traversal while letting legitimate traffic through. You place a protected site in front of your upstream server, point its domain at the WAF, and every request is inspected before it reaches your application, with attacks answered by an interception page and clean traffic marked with a Server: uuWAF header. The cloudimg image installs UUSEC WAF 7.2.5 as the official Safe3/uusec-waf Docker Compose stack and runs it as a systemd service, so a working management console and WAF are online within minutes of launch.
What is included:
- UUSEC WAF 7.2.5 (BSD-2-Clause) deployed from the official
Safe3/uusec-wafDocker Compose stack, pinned to theuusec/waf:7.2.5image so the appliance never silently upgrades - Docker Engine (Docker CE) and the Docker Compose plugin, installed from the official Docker package repository
- The uuWAF Compose stack (two containers):
uuwaf(the OpenResty/Nginx+Lua WAF engine and the Go management backend, binding the reverse proxy ports 80 and 443 and the management console on HTTPS port 4443) andwafdb(MySQL 5.7, the management database, reachable only on the loopback interface and the internal container network) - A per-VM
adminconsole password: UUSEC WAF ships upstream with the shared defaultadmin/#Passw0rd, and the cloudimg image rotates that default away on first boot and proves the default is rejected - Two systemd units:
uusec-waf.service(a oneshot wrapper arounddocker compose up -d) anduusec-waf-firstboot.service - 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key, and a VNet and subnet. Standard_B2s (2 vCPU / 4 GB RAM) is the recommended size. NSG inbound rules: allow 22/tcp from your management CIDR for SSH, 4443/tcp from the CIDR that needs the UUSEC WAF management console, and 80/tcp and 443/tcp from the internet for the web traffic you want the WAF to protect (uuWAF's reverse proxy binds ports 80 and 443 for the sites you add).
Step 1: Connect over SSH
Replace <vm-ip> with the public IP of your VM. The default login user is azureuser.
ssh azureuser@<vm-ip>
Step 2: Confirm the services are active
sudo systemctl is-active docker uusec-waf
docker --version
docker compose version
You should see active printed twice, the Docker Engine version, and the Docker Compose v2 plugin version.

Step 3: Confirm the UUSEC WAF containers are running
cd /opt/waf && sudo docker compose -f docker-compose.yml --env-file .env ps
You should see the two uuWAF containers — uuwaf (the WAF engine and console) and wafdb (the MySQL database, reported healthy) — in the Up / running state.
Step 4: Confirm the management console is healthy
The management console is served over HTTPS on port 4443. It uses a self signed certificate, so curl is called with -k. A 200 confirms the console is up.
curl -ks -o /dev/null -w "%{http_code}\n" https://localhost:4443/
Step 5: Read the per-VM admin credentials
UUSEC WAF ships upstream with a shared default console login (admin / #Passw0rd). The cloudimg image rotates that default away on the first boot of every instance and writes the unique admin password to a root only file. The default no longer works.
sudo cat /root/uusec-waf-credentials.txt
This file lists uusec-waf.url (where to sign in), uusec-waf.admin.user (admin) and uusec-waf.admin.pass. Store the password somewhere safe.

Step 6: Sign in to the UUSEC WAF console
Browse to https://<vm-ip>:4443/ in your browser. Because the console uses a self signed certificate, your browser warns once — accept it to continue. You then reach the sign in page, where you log in with the username admin and the uusec-waf.admin.pass from Step 5. Leave the OTP field empty unless you later enable dynamic (one time) passwords.

After signing in you land on the dashboard, which summarises total visits, blocked attacks, live request metrics, the geographic origin of attack sources and the current system resource usage.

For extra security, UUSEC WAF recommends creating a new administrator with a hard to guess name, deleting the default admin, and enabling dynamic passwords — all from the console.
Step 7: Protect your first web application
To put UUSEC WAF in front of a web application, open Site Security (Sites) in the console and choose Add Site. Give it the domain (or a match all host), and the upstream address of your origin server (for example 127.0.0.1:8080 or 10.0.0.4:3000) with its scheme. The WAF reverse proxy on ports 80 and 443 then routes requests for that domain to your origin, inspecting every request first. Finally, point the domain's DNS A record at the VM's public IP.

Step 8: How UUSEC WAF blocks attacks
Once a site is protected, UUSEC WAF passes clean traffic straight through to your origin and intercepts attacks. A benign request returns your application's normal response with a Server: uuWAF header; an obvious SQL injection or cross site scripting probe is answered with an HTTP 403 interception page instead of ever reaching your origin.

The visitor who sends the malicious request sees UUSEC WAF's interception page, with the rule id that matched. The blocked event is also logged and surfaced in the console.

Secure by default
The management console requires authentication, the MySQL database is bound to the loopback interface and the internal container network only (it is never published on a public interface), and anonymous API calls are rejected. You can confirm which ports are exposed on the host and that the console is healthy at any time.
sudo ss -tlnp | grep -E ':80|:443|:4443|:6612' || true
You will see the WAF proxy on 80 and 443 and the console on 4443 on all interfaces, while MySQL on 6612 is bound to 127.0.0.1 only — the database is not reachable from the network.

Step 9: Manage the stack
The whole stack is managed by the uusec-waf.service systemd unit, which wraps docker compose under /opt/waf.
sudo systemctl restart uusec-waf.service
sudo systemctl status uusec-waf.service --no-pager
To inspect the logs for a specific service:
cd /opt/waf && sudo docker compose -f docker-compose.yml --env-file .env logs --tail 50 uuwaf
Enabling HTTPS on your own domain
The management console already serves HTTPS on port 4443 with a self signed certificate. For the sites you protect, add your own TLS certificate under Certificates in the console and bind it to the site, or let UUSEC WAF apply for and auto renew a free Let's Encrypt certificate, so the WAF terminates HTTPS for your application on port 443. Add 443/tcp to your NSG inbound rules.
First-boot security model
On the first boot of each VM, uusec-waf-firstboot.service runs once and:
- Regenerates the MySQL password and initialises the database clean, so no build time database or secret ships in the image
- Rotates the upstream default
adminpassword (#Passw0rd) to a fresh, strong, per-VM value and writes it to/root/uusec-waf-credentials.txt(root only, mode 0600), then proves the default is rejected - Records a sentinel so the stack only starts once the credential has been rotated
No shared or default login and no preexisting protected site ship in the image. The management console is protected by this per-VM credential the moment it comes up.
Support
24/7 technical support is included. Contact cloudimg at support@cloudimg.co.uk for help with deployment, protecting your applications, the semantic detection engine and custom rules, machine learning and RASP defence, bot and CC attack protection, TLS certificates and custom domains, and the UUSEC WAF API.
UUSEC WAF and uuWAF are names of the open source project by Safe3 (github.com/Safe3/uusec-waf), used here nominatively to identify the software this image packages. MySQL is a trademark of Oracle Corporation. Docker is a trademark of Docker, Inc. All other product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.