基於 nginx,保留 nginx-certbot 啟動與憑證更新,整合 ModSecurity 與 OWASP CRS。
1.3K
Nginx reverse proxy image with ModSecurity v3, OWASP CRS, and automatic Let's Encrypt certificate management.
The bundled /scripts keep the nginx/certbot flow from the MIT-licensed staticfloat/docker-nginx-certbot project, with local startup checks and ModSecurity defaults added. The image no longer depends on the staticfloat image at build time.
| Tag | App | Nginx | OWASP CRS | Policy |
|---|---|---|---|---|
1.2.1-nginx1.31.2-crs4.27.0 | 1.2.1 | 1.31.2 | 4.27.0 | Immutable |
1.2.1 | 1.2.1 | 1.31.2 | 4.27.0 | Immutable |
1.2, 1, latest | Latest compatible/stable | Varies | Varies | Floating |
docker pull ai4dtdottech/waf-nginx-certbot:1.2.1-nginx1.31.2-crs4.27.0
1.31.2 with dynamic ModSecurity modulev4.27.0 pre-installed at /usr/share/owasp-modsecurity-crs/scripts/entrypoint.sh/scripts/manual_issue_cert.sh, backed by the shared /scripts/issue_cert.sh flow, without restarting Nginx/etc/nginx/modsecurity)docker run -d \
--name waf-nginx-certbot \
--restart always \
-p 80:80 \
-p 443:443 \
-e [email protected] \
-v /path/to/conf.d:/etc/nginx/conf.d \
-v /path/to/user.conf.d:/etc/nginx/user.conf.d \
-v /path/to/stream.d:/etc/nginx/stream.d \
-v /path/to/modsecurity:/etc/nginx/modsecurity \
-v /path/to/cert:/etc/cert \
-v /var/www/html:/var/www/html \
-v /etc/letsencrypt:/etc/letsencrypt \
ai4dtdottech/waf-nginx-certbot:1.2.1-nginx1.31.2-crs4.27.0
Prepare conf.d, user.conf.d, stream.d, and modsecurity host directories before starting. In this repository, modsecurity/ is only a runtime mount placeholder; the committed defaults live in build/defaults/modsecurity/ and are copied into an empty mount on first start. If user.conf.d, stream.d, or modsecurity are empty on first start, the entrypoint writes safe defaults and examples. If a required mount is missing, the container stops and explains the missing mount in docker logs waf-nginx-certbot.
The entrypoint ensures that user.conf.d/wildcard exists, even when the parent
user.conf.d mount already contains configuration files. An empty wildcard
directory is seeded with the bundled example; existing files under that directory
are never overwritten. Without the /etc/cert mount, startup
logs warn that automatic wildcard SSL certificate requests are disabled and
show the required ./cert:/etc/cert volume mapping. When the mount exists but
dns-credentials.ini does not, a blank file is generated with mode 0600;
existing credentials are never overwritten.
| Variable | Required | Description |
|---|---|---|
CERTBOT_EMAIL | Yes | Email for Let's Encrypt registration and expiry notices |
WAF_BOOTSTRAP_CHOWN | No | Optional owner for first-start generated files, for example 1000:1000 |
CERTBOT_INTERVAL_SECONDS | No | Successful certificate cycle interval; default 604810 |
CERTBOT_RETRY_INTERVAL_SECONDS | No | Retry interval after any failed job; default 3600 |
| Host path | Container path | Description |
|---|---|---|
conf.d/ | /etc/nginx/conf.d | Runtime generated Nginx configs and .nokey state |
user.conf.d/ | /etc/nginx/user.conf.d | Your Nginx server block templates |
modsecurity/ | /etc/nginx/modsecurity | ModSecurity config and custom rule exceptions |
stream.d/ | /etc/nginx/stream.d | Optional stream (TCP/UDP) configs |
cert/ | /etc/cert | Optional DNS Provider credentials; writable for first-start initialization |
/var/www/html | /var/www/html | ACME HTTP-01 challenge webroot |
/etc/letsencrypt | /etc/letsencrypt | Certificate storage (persist across restarts) |
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity_includes.conf;
server {
listen 80;
server_name example.com;
include /etc/nginx/acme-challenge-location.conf;
location / {
return 301 https://$host$request_uri;
}
}
Include acme-challenge-location.conf on every HTTP server that redirects to HTTPS, so certificate renewal can reach /.well-known/acme-challenge/.
Root-level user.conf.d/*.conf files keep using HTTP-01. Put wildcard Nginx
configs in user.conf.d/wildcard/*.conf; the manager derives the lineage and
SANs from ssl_certificate_key and server_name, then detects the DNS zone and
Provider from SOA/NS records. Configure credentials once:
[godaddy]
pat = <GoDaddy PAT>
[cloudflare]
api_token =
On first start, the entrypoint generates this as cert/dns-credentials.ini
with mode 0600. Fill in the credentials, then copy the wildcard example into
user.conf.d/wildcard/ with a .conf suffix.
Nginx starts before certificate processing. HTTP-01 jobs run and reload first;
DNS-01 jobs then run one at a time and reload immediately after each success.
A DNS API or propagation failure never delays Nginx startup or a completed
HTTP-01 certificate. Empty credentials disable that Provider. GoDaddy is the
only installed adapter in this release; recognized future Providers are logged
as adapter not implemented.
After adding or changing a config under user.conf.d/, discover and issue its
certificate immediately without restarting the container:
docker compose exec waf-nginx-certbot /scripts/manual_issue_cert.sh
The command stages and validates generated configs before publishing them, then
uses a graceful Nginx reload after successful issuance. It scans every configured
domain, skips recently checked certificates, returns 1 on processing failure,
and returns 75 when another manual or scheduled issue run owns the shared lock.
Mount a modsecurity/ directory containing at minimum:
modsecurity.confmodsecurity_includes.confunicode.mappingexclude/*-before.conf / exclude/*-after.conf for custom rule adjustmentsWhen the mounted modsecurity/ directory is empty, the entrypoint generates these files from the defaults embedded in the image (build/defaults/modsecurity/ in this repo). When it is not empty, files are not overwritten; missing required files cause startup to fail with a clear log message.
Do not edit files under /usr/share/owasp-modsecurity-crs/rules directly. Use exclude/ files instead:
SecRuleRemoveById 942100
SecRuleUpdateTargetById 942100 "!ARGS:payload"
After changes, reload Nginx:
docker exec waf-nginx-certbot nginx -s reload
docker compose -f docker-compose.build.yml build
Build arguments:
| Argument | Default | Description |
|---|---|---|
NGINX_VERSION | 1.31.2 | Nginx base version |
CRS_VERSION | v4.27.0 | OWASP CRS git tag |
MAKE_JOBS | nproc | Parallel compile jobs |
APP_VERSION | 1.2.1 | Application semantic version for OCI metadata |
VCS_REF | unknown | Source revision for OCI metadata |
BUILD_DATE | 1970-01-01T00:00:00Z | RFC 3339 build time for OCI metadata |
The repository release.ps1 reads VERSION, builds the canonical immutable
tag once, and creates 1.2.1, 1.2, 1, and latest aliases. It pushes only
when invoked with -Push. Publishing requires a clean Git working tree; after
all Docker tags succeed, it creates and pushes annotated Git tag v1.2.1 to
the WAF-Nginx-Certbot remote. The legacy component-only tag is never updated.
Use ./sync-version.ps1 1.2.1 from the repository root to bump the application
version. It updates VERSION and all release-facing references together.
Content type
Image
Digest
sha256:93a493dda…
Size
978.4 MB
Last updated
about 2 months ago
docker pull ai4dtdottech/waf-nginx-certbot