Web Application Firewall built with Kemal framework
kemal-waf supports HTTPS with your own certs, self-signed (dev only), per-domain (SNI), or Let’s Encrypt.
For a single domain or wildcard certificate:
waf:
server:
https_enabled: true
https_port: 3443
tls:
cert_file: /path/to/cert.pem
key_file: /path/to/key.pem
For testing and development:
waf:
server:
https_enabled: true
https_port: 3443
tls:
auto_generate: true
auto_cert_dir: config/certs
⚠️ Warning: Self-signed certificates are for testing/development only. Do not use in production!
For multi-domain deployments, each domain can have its own certificate:
waf:
server:
https_enabled: true
https_port: 3443
domains:
"example.com":
default_upstream: "http://localhost:8080"
cert_file: /etc/letsencrypt/live/example.com/fullchain.pem
key_file: /etc/letsencrypt/live/example.com/privkey.pem
"api.example.com":
default_upstream: "http://localhost:8081"
cert_file: /etc/letsencrypt/live/api.example.com/fullchain.pem
key_file: /etc/letsencrypt/live/api.example.com/privkey.pem
Kemal WAF can automatically obtain and renew Let’s Encrypt certificates:
waf:
server:
https_enabled: true
http_enabled: true # Required for HTTP-01 challenge
http_port: 80 # Must be accessible on port 80
https_port: 443
domains:
"example.com":
default_upstream: "http://localhost:8080"
letsencrypt_enabled: true
letsencrypt_email: admin@example.com
"api.example.com":
default_upstream: "http://localhost:8081"
letsencrypt_enabled: true
letsencrypt_email: admin@example.com
Requirements for Let’s Encrypt:
brew install certbot or apt-get install certbot)Environment Variables for Let’s Encrypt:
LETSENCRYPT_STAGING=true - Use staging environment for testing (avoids rate limits)Certificate Priority:
cert_file / key_file (highest priority)letsencrypt_enabled: trueYou can enable both HTTP and HTTPS simultaneously:
waf:
server:
http_enabled: true
http_port: 3030
https_enabled: true
https_port: 3443
tls:
auto_generate: true
When using Let’s Encrypt, certificates are automatically renewed 30 days before expiry. The renewal process runs in the background every 12 hours.
HTTP/2.0 support is planned but not yet implemented. The configuration option http2_enabled is available in the config file for future use. Currently, the WAF uses HTTP/1.1.
For persistent certificate storage:
# Create volume for certificates
docker volume create waf-certs
# Run with certificate volume
docker run -d \
--name kemal-waf \
-p 443:3443 \
-v waf-certs:/app/config/certs \
kursadaltan/kemalwaf:latest
Ensure certificate files have correct permissions:
chmod 600 /path/to/key.pem
chmod 644 /path/to/cert.pem
# Test HTTPS connection
curl -k https://localhost:3443/
# Test with certificate validation
curl https://example.com/ --cacert /path/to/ca-cert.pem
# Check certificate details
openssl s_client -connect example.com:443 -servername example.com
If you see “certificate file not found” errors:
If you hit Let’s Encrypt rate limits:
LETSENCRYPT_STAGING=true for testingIf SNI is not working: