Sign inSign up

ai4dtdottech/waf-nginx-certbot

By ai4dtdottech

•Updated about 2 months ago

基於 nginx,保留 nginx-certbot 啟動與憑證更新,整合 ModSecurity 與 OWASP CRS。

Image
Security
Web servers
0

1.3K

ai4dtdottech/waf-nginx-certbot repository overview

⁠ai4dtdottech/waf-nginx-certbot

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.

⁠Tags

TagAppNginxOWASP CRSPolicy
1.2.1-nginx1.31.2-crs4.27.01.2.11.31.24.27.0Immutable
1.2.11.2.11.31.24.27.0Immutable
1.2, 1, latestLatest compatible/stableVariesVariesFloating
docker pull ai4dtdottech/waf-nginx-certbot:1.2.1-nginx1.31.2-crs4.27.0

⁠Features

  • Nginx 1.31.2 with dynamic ModSecurity module
  • OWASP CRS v4.27.0 pre-installed at /usr/share/owasp-modsecurity-crs
  • Certbot auto-issue and renewal via /scripts/entrypoint.sh
  • On-demand certificate discovery via /scripts/manual_issue_cert.sh, backed by the shared /scripts/issue_cert.sh flow, without restarting Nginx
  • Coexisting HTTP-01 and provider-based DNS-01 certificate jobs
  • GoDaddy v3 DNS API adapter with authoritative DNS propagation checks
  • First-start mount validation and default config bootstrap
  • Runtime ModSecurity config via bind mount (/etc/nginx/modsecurity)
  • Custom rule exceptions without modifying official CRS files

⁠Quick Start

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.

⁠Environment Variables

VariableRequiredDescription
CERTBOT_EMAILYesEmail for Let's Encrypt registration and expiry notices
WAF_BOOTSTRAP_CHOWNNoOptional owner for first-start generated files, for example 1000:1000
CERTBOT_INTERVAL_SECONDSNoSuccessful certificate cycle interval; default 604810
CERTBOT_RETRY_INTERVAL_SECONDSNoRetry interval after any failed job; default 3600

⁠Volumes

Host pathContainer pathDescription
conf.d//etc/nginx/conf.dRuntime generated Nginx configs and .nokey state
user.conf.d//etc/nginx/user.conf.dYour Nginx server block templates
modsecurity//etc/nginx/modsecurityModSecurity config and custom rule exceptions
stream.d//etc/nginx/stream.dOptional stream (TCP/UDP) configs
cert//etc/certOptional DNS Provider credentials; writable for first-start initialization
/var/www/html/var/www/htmlACME HTTP-01 challenge webroot
/etc/letsencrypt/etc/letsencryptCertificate storage (persist across restarts)

⁠Nginx Configuration

⁠Enable WAF on HTTPS server
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity_includes.conf;
⁠HTTP server with ACME challenge (before HTTPS redirect)
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/.

⁠DNS-01 Wildcard Certificates

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.

⁠ModSecurity Runtime Config

Mount a modsecurity/ directory containing at minimum:

  • modsecurity.conf
  • modsecurity_includes.conf
  • unicode.mapping
  • exclude/*-before.conf / exclude/*-after.conf for custom rule adjustments

When 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

⁠Build

docker compose -f docker-compose.build.yml build

Build arguments:

ArgumentDefaultDescription
NGINX_VERSION1.31.2Nginx base version
CRS_VERSIONv4.27.0OWASP CRS git tag
MAKE_JOBSnprocParallel compile jobs
APP_VERSION1.2.1Application semantic version for OCI metadata
VCS_REFunknownSource revision for OCI metadata
BUILD_DATE1970-01-01T00:00:00ZRFC 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.

⁠Source & Full Documentation

Tag summary

Content type

Image

Digest

sha256:93a493dda…

Size

978.4 MB

Last updated

about 2 months ago

docker pull ai4dtdottech/waf-nginx-certbot