├── Dockerfile ├── LICENSE ├── README.md ├── certbot.default.sh ├── docker-entrypoint.sh └── hooks └── build /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | MAINTAINER Troy Kelly 4 | 5 | ENV VERSION=1.20.0 6 | ENV OPENSSL_VERSION=1.1.1k 7 | ENV LIBPNG_VERSION=1.6.37 8 | ENV LUAJIT_VERSION=2.0.5 9 | ENV NGXDEVELKIT_VERSION=0.3.1 10 | ENV NGXLUA_VERSION=0.10.19 11 | ENV MODSECURITY=3 12 | ENV OWASPCRS_VERSION=3.3.0 13 | ENV PYTHON_VERSION=3.9.0 14 | 15 | # Build-time metadata as defined at http://label-schema.org 16 | ARG BUILD_DATE 17 | ARG VCS_REF 18 | ARG VERSION 19 | ARG OPENSSL_VERSION 20 | ARG LIBPNG_VERSION 21 | ARG LUAJIT_VERSION 22 | ARG MODSECURITY 23 | ARG OWASPCRS_VERSION 24 | ARG PYTHON_VERSION 25 | LABEL org.label-schema.build-date=$BUILD_DATE \ 26 | org.label-schema.name="NGINX with ModSecurity, Certbot and lua support" \ 27 | org.label-schema.description="Provides nginx ${VERSION} with ModSecurity v${MODSECURITY} (OWASP ModSecurity Core Rule Set CRS ${OWASPCRS_VERSION}) and lua (LuaJIT v${LUAJIT_VERSION}) support for certbot --nginx. Built with OpenSSL v${OPENSSL_VERSION} and LibPNG v${LIBPNG_VERSION}. Using Python ${PYTHON_VERSION} for Let's Encrypt Certbot" \ 28 | org.label-schema.url="https://really.ai/about/opensource" \ 29 | org.label-schema.vcs-ref=$VCS_REF \ 30 | org.label-schema.vcs-url="https://github.com/reallyreally/docker-nginx-modsecurity" \ 31 | org.label-schema.vendor="Really Really, Inc." \ 32 | org.label-schema.version=v$VERSION \ 33 | org.label-schema.schema-version="1.0" 34 | 35 | RUN build_pkgs="alpine-sdk apr-dev apr-util-dev autoconf automake binutils-gold curl curl-dev g++ gcc geoip-dev git gnupg icu-dev libcurl libffi-dev libjpeg-turbo-dev libstdc++ libtool libxml2-dev linux-headers lmdb-dev m4 make openssh-client pcre-dev pcre2-dev perl pkgconf wget yajl-dev zlib-dev" && \ 36 | runtime_pkgs="ca-certificates pcre apr-util libjpeg-turbo icu icu-libs yajl lua geoip libxml2 lua5.3-maxminddb libffi" && \ 37 | apk add --update --no-cache ${build_pkgs} ${runtime_pkgs} && \ 38 | mkdir -p /src /var/log/nginx /run/nginx /var/cache/nginx && \ 39 | addgroup nginx && \ 40 | adduser -s /usr/sbin/nologin -G nginx -D nginx && \ 41 | cd /src && \ 42 | git clone --depth 1 -b v${MODSECURITY}/master --single-branch https://github.com/SpiderLabs/ModSecurity && \ 43 | git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git && \ 44 | echo "Fetching OpenSSL Source" && \ 45 | wget -qO - https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz | tar xzf - -C /src && \ 46 | echo "Fetching Nginx Source" && \ 47 | wget -qO - http://nginx.org/download/nginx-${VERSION}.tar.gz | tar xzf - -C /src && \ 48 | echo "Fetching LibPNG Source" && \ 49 | wget -qO - http://prdownloads.sourceforge.net/libpng/libpng-${LIBPNG_VERSION}.tar.gz | tar xzf - -C /src && \ 50 | echo "Fetching LUA Jit Source" && \ 51 | wget -qO - http://luajit.org/download/LuaJIT-${LUAJIT_VERSION}.tar.gz | tar xzf - -C /src && \ 52 | echo "Fetching NGX Devel Kit Source" && \ 53 | wget -qO - https://github.com/vision5/ngx_devel_kit/archive/refs/tags/v${NGXDEVELKIT_VERSION}.tar.gz | tar xzf - -C /src && \ 54 | echo "Fetching LUA Nginx Source" && \ 55 | wget -qO - https://github.com/openresty/lua-nginx-module/archive/v${NGXLUA_VERSION}.tar.gz | tar xzf - -C /src && \ 56 | echo "Fetching OWASP Source" && \ 57 | wget -qO - https://github.com/coreruleset/coreruleset/archive/refs/tags/v${OWASPCRS_VERSION}.tar.gz | tar xzf - -C /src && \ 58 | echo "Fetching Pyton Source" && \ 59 | wget -qO - https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz | tar xzf - -C /src && \ 60 | echo "Fetching ModSecurity Source" && \ 61 | wget -qO /src/modsecurity.conf https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v${MODSECURITY}/master/modsecurity.conf-recommended 62 | 63 | RUN cd /src/openssl-${OPENSSL_VERSION} && \ 64 | ./config no-async -Wl,--enable-new-dtags,-rpath,'$(LIBRPATH)' && \ 65 | make -j$(nproc) depend && \ 66 | make -j$(nproc) && \ 67 | make -j$(nproc) install 68 | 69 | RUN cd /src/Python-${PYTHON_VERSION} && \ 70 | ./configure --build=$CBUILD --host=$CHOST --prefix=/usr --with-openssl=/src/openssl-${OPENSSL_VERSION} --enable-shared && \ 71 | make -j$(nproc) && \ 72 | make -j$(nproc) install && \ 73 | python3 -m ensurepip && \ 74 | pip3 install --upgrade pip setuptools && \ 75 | if [ ! -e /usr/bin/pip ]; then ln -s pip3 /usr/bin/pip ; fi && \ 76 | if [[ ! -e /usr/bin/python ]]; then ln -sf /usr/bin/python3 /usr/bin/python; fi && \ 77 | cd /src/LuaJIT-${LUAJIT_VERSION} && \ 78 | make -j$(nproc) && \ 79 | make -j$(nproc) install && \ 80 | cd /src/libpng-${LIBPNG_VERSION} && \ 81 | ./configure --build=$CBUILD --host=$CHOST --prefix=/usr --enable-shared --with-libpng-compat && \ 82 | make -j$(nproc) install V=0 83 | 84 | RUN cd /src/ModSecurity && \ 85 | git submodule init && \ 86 | git submodule update && \ 87 | ./build.sh && \ 88 | ./configure && \ 89 | make -j$(nproc) && \ 90 | make install 91 | 92 | RUN cd /src/nginx-${VERSION} && \ 93 | ./configure \ 94 | --prefix=/etc/nginx \ 95 | --sbin-path=/usr/sbin/nginx \ 96 | --conf-path=/etc/nginx/nginx.conf \ 97 | --error-log-path=/var/log/nginx/error.log \ 98 | --http-log-path=/var/log/nginx/access.log \ 99 | --pid-path=/var/run/nginx.pid \ 100 | --lock-path=/var/run/nginx.lock \ 101 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 102 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 103 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 104 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 105 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 106 | --user=nginx \ 107 | --group=nginx \ 108 | --with-http_ssl_module \ 109 | --with-http_realip_module \ 110 | --with-http_addition_module \ 111 | --with-http_sub_module \ 112 | --with-http_dav_module \ 113 | --with-http_flv_module \ 114 | --with-http_mp4_module \ 115 | --with-http_gunzip_module \ 116 | --with-http_gzip_static_module \ 117 | --with-http_random_index_module \ 118 | --with-http_secure_link_module \ 119 | --with-http_stub_status_module \ 120 | --with-http_auth_request_module \ 121 | --without-http_autoindex_module \ 122 | --without-http_ssi_module \ 123 | --with-threads \ 124 | --with-stream \ 125 | --with-stream_ssl_module \ 126 | --with-mail \ 127 | --with-mail_ssl_module \ 128 | --with-file-aio \ 129 | --with-http_v2_module \ 130 | --with-cc-opt="-fPIC -I /usr/include/apr-1" \ 131 | --with-ld-opt="-luuid -lapr-1 -laprutil-1 -licudata -licuuc -lpng16 -lturbojpeg -ljpeg" \ 132 | --with-openssl-opt="no-async enable-ec_nistp_64_gcc_128 no-shared no-ssl2 no-ssl3 no-comp no-idea no-weak-ssl-ciphers -DOPENSSL_NO_HEARTBEATS -O3 -fPIE -fstack-protector-strong -D_FORTIFY_SOURCE=2" \ 133 | --with-ipv6 \ 134 | --with-pcre-jit \ 135 | --with-openssl=/src/openssl-${OPENSSL_VERSION} \ 136 | --add-module=/src/ngx_devel_kit-${NGXDEVELKIT_VERSION} \ 137 | --add-module=/src/lua-nginx-module-${NGXLUA_VERSION} \ 138 | --add-dynamic-module=/src/ModSecurity-nginx && \ 139 | make -j$(nproc) && \ 140 | make -j$(nproc) install && \ 141 | make -j$(nproc) modules && \ 142 | cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules && \ 143 | sed -i 's!#user nobody!user nginx nginx!g' /etc/nginx/nginx.conf && \ 144 | sed -i "s!^ # another virtual host!include /etc/nginx/conf.d/*.conf;\n # another virtual host!g" /etc/nginx/nginx.conf && \ 145 | sed -i "s!^ #gzip on;! #gzip on;\n server_names_hash_max_size 6144;\n server_names_hash_bucket_size 128;\n\nmodsecurity on;\nmodsecurity_rules_file /etc/nginx/modsec/modsec_includes.conf;\n!g" /etc/nginx/nginx.conf && \ 146 | sed -i "s!^ #error_page 404 /404.html;! include /etc/nginx/insert.d/*.conf;\n\n #error_page 404 /404.html;!g" /etc/nginx/nginx.conf && \ 147 | sed -i 's!events {!load_module modules/ngx_http_modsecurity_module.so;\n\nevents {!g' /etc/nginx/nginx.conf && \ 148 | sed -i "s!^ server_name localhost;! server_name localhost;\n\n #include /etc/nginx/modsec/modsec_on.conf;!g" /etc/nginx/nginx.conf && \ 149 | sed -i "s!^ index index.html index.htm;! index index.html index.htm;\n #include /etc/nginx/modsec/modsec_rules.conf;!g" /etc/nginx/nginx.conf && \ 150 | cd ~ && \ 151 | git clone https://github.com/certbot/certbot && \ 152 | cd certbot && \ 153 | CFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" /usr/bin/pip install -r ./readthedocs.org.requirements.txt && \ 154 | CFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" /usr/bin/pip install --no-cache-dir \ 155 | --editable ./acme \ 156 | --editable ./certbot-dns-cloudxns \ 157 | --editable ./certbot-dns-digitalocean \ 158 | --editable ./certbot-dns-dnsimple \ 159 | --editable ./certbot-dns-dnsmadeeasy \ 160 | --editable ./certbot-dns-gehirn \ 161 | --editable ./certbot-dns-google \ 162 | --editable ./certbot-dns-linode \ 163 | --editable ./certbot-dns-luadns \ 164 | --editable ./certbot-dns-nsone \ 165 | --editable ./certbot-dns-ovh \ 166 | --editable ./certbot-dns-rfc2136 \ 167 | --editable ./certbot-dns-route53 \ 168 | --editable ./certbot-dns-sakuracloud \ 169 | --editable ./certbot-nginx \ 170 | --editable ./ && \ 171 | CFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" /usr/bin/pip install dns-lexicon && \ 172 | /usr/bin/certbot --version && \ 173 | mkdir -p /etc/nginx/modsec/conf.d && \ 174 | echo -e "# Example placeholder\n" > /etc/nginx/modsec/conf.d/example.conf && \ 175 | echo -e "# Include the recommended configuration\nInclude /etc/nginx/modsec/modsecurity.conf\n# User generated\nInclude /etc/nginx/modsec/conf.d/*.conf\n\n# OWASP CRS v${MODSECURITY} rules\nInclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/crs-setup.conf\nInclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/*.conf\n" > /etc/nginx/modsec/main.conf && \ 176 | echo -e "# For inclusion and centralized control\nmodsecurity on;\n" > /etc/nginx/modsec/modsec_on.conf && \ 177 | echo -e "# For inclusion and centralized control\nmodsecurity_rules_file /etc/nginx/modsec/modsec_includes.conf;\n" > /etc/nginx/modsec/modsec_rules.conf && \ 178 | echo -e "# For inclusion and centralized control\ninclude /etc/nginx/modsec/modsecurity.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/crs-setup.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-901-INITIALIZATION.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-905-COMMON-EXCEPTIONS.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-910-IP-REPUTATION.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-911-METHOD-ENFORCEMENT.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-912-DOS-PROTECTION.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-913-SCANNER-DETECTION.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-921-PROTOCOL-ATTACK.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-949-BLOCKING-EVALUATION.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-950-DATA-LEAKAGES.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-959-BLOCKING-EVALUATION.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-980-CORRELATION.conf\ninclude /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf\n" > /etc/nginx/modsec/modsec_includes.conf && \ 179 | mv /src/modsecurity.conf /etc/nginx/modsec && \ 180 | sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/g' /etc/nginx/modsec/modsecurity.conf && \ 181 | sed -i 's!SecAuditLog /var/log/modsec_audit.log!SecAuditLog /var/log/nginx/modsec_audit.log!g' /etc/nginx/modsec/modsecurity.conf && \ 182 | mv /src/owasp-modsecurity-crs-${OWASPCRS_VERSION} /usr/local/ && \ 183 | mv /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf && \ 184 | mv /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf && \ 185 | cp /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/crs-setup.conf.example /usr/local/owasp-modsecurity-crs-${OWASPCRS_VERSION}/crs-setup.conf && \ 186 | curl https://raw.githubusercontent.com/SpiderLabs/ModSecurity/49495f1925a14f74f93cb0ef01172e5abc3e4c55/unicode.mapping -o /etc/nginx/modsec/unicode.mapping 187 | RUN apk del ${build_pkgs} && \ 188 | apk add ${runtime_pkgs} && \ 189 | apk add gcc make perl && \ 190 | cd /src/openssl-${OPENSSL_VERSION} && \ 191 | make -j$(nproc) install && \ 192 | if [ -f /usr/bin/openssl ]; then rm -f /usr/bin/openssl; fi && \ 193 | if [ -f /usr/local/ssl/bin/openssl ]; then ln -s /usr/local/ssl/bin/openssl /usr/bin/; fi && \ 194 | if [ -f /usr/local/bin/openssl ]; then ln -s /usr/local/bin/openssl /usr/bin/; fi && \ 195 | cd ~ && \ 196 | apk del perl gcc make && \ 197 | rm -Rf /src && \ 198 | rm -Rf ~/.cache && \ 199 | echo -e "#!/usr/bin/env sh\n\nif [ -f "/usr/bin/certbot" ]; then\n /usr/bin/certbot renew\nfi\n" > /etc/periodic/daily/certrenew && \ 200 | chmod 755 /etc/periodic/daily/certrenew && \ 201 | chown -R nginx:nginx /run/nginx /var/log/nginx /var/cache/nginx /etc/nginx && \ 202 | echo -e "\n\n** /etc/nginx/nginx.conf\n" && \ 203 | cat /etc/nginx/nginx.conf && \ 204 | echo -e "\n\n** /etc/nginx/modsec/conf.d/example.conf\n" && \ 205 | cat /etc/nginx/modsec/conf.d/example.conf && \ 206 | echo -e "\n\n** /etc/nginx/modsec/main.conf\n" && \ 207 | cat /etc/nginx/modsec/main.conf && \ 208 | echo -e "\n\n** /etc/nginx/modsec/modsecurity.conf\n" && \ 209 | cat /etc/nginx/modsec/modsecurity.conf && \ 210 | echo -e "\n\n** /etc/nginx/modsec/modsec_on.conf\n" && \ 211 | cat /etc/nginx/modsec/modsec_on.conf && \ 212 | echo -e "\n\n** /etc/nginx/modsec/modsec_rules.conf\n" && \ 213 | cat /etc/nginx/modsec/modsec_rules.conf && \ 214 | echo -e "\n\n** /etc/nginx/modsec/modsec_includes.conf\n" && \ 215 | cat /etc/nginx/modsec/modsec_includes.conf && \ 216 | echo -e "\n\n** /etc/periodic/daily/certrenew\n" && \ 217 | cat /etc/periodic/daily/certrenew 218 | 219 | EXPOSE 80 443 220 | 221 | COPY docker-entrypoint.sh /usr/local/bin/ 222 | COPY certbot.default.sh /usr/local/sbin/ 223 | 224 | ENTRYPOINT ["docker-entrypoint.sh"] 225 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # really/nginx-modsecurity 2 | Docker container providing [nginx](https://www.nginx.com) with [modsecurity] (https://www.modsecurity.org), [lua](https://www.nginx.com/resources/wiki/modules/lua/) and certbot for [Let's Encrypt](https://letsencrypt.org) SSL certificates 3 | 4 | [![](https://images.microbadger.com/badges/image/really/nginx-modsecurity.svg)](https://microbadger.com/images/really/nginx-modsecurity "Get your own image badge on microbadger.com") [![GitHub issues](https://img.shields.io/github/issues/reallyreally/docker-nginx-modsecurity.svg?style=flat-square)](https://github.com/reallyreally/docker-nginx-modsecurity/issues) [![GitHub license](https://img.shields.io/github/license/reallyreally/docker-nginx-modsecurity.svg?style=flat-square)](https://github.com/reallyreally/docker-nginx-modsecurity/blob/master/LICENSE) [![Docker Pulls](https://img.shields.io/docker/pulls/really/nginx-modsecurity.svg?style=flat-square)](https://github.com/reallyreally/docker-nginx-modsecurity/) 5 | 6 | Launch nginx using the default config: 7 | ``` 8 | docker run --name nginx-modsecurity \ 9 | --restart=always \ 10 | --net=host \ 11 | -v /data/nginx/conf.d:/etc/nginx/conf.d:rw \ 12 | -v /data/letsencrypt:/etc/letsencrypt:rw \ 13 | -p 80:80 -p 443:443 -d \ 14 | really/nginx-modsecurity 15 | ``` 16 | 17 | ModSecurity 18 | ----------- 19 | Pre-configured with rules from OWASP CRS on my default. 20 | If you want to disable it for a particular location simply set it to off 21 | ``` 22 | server 23 | { 24 | listen 80; 25 | listen [::]:80; 26 | listen [::]:443 ssl http2; 27 | listen 443 ssl http2; 28 | 29 | server_name insecure.example.com; 30 | 31 | set $upstream "http://10.0.0.1:9000"; 32 | 33 | include /etc/nginx/defaults/https.conf; 34 | include /etc/nginx/defaults/resolver.conf; 35 | 36 | location / 37 | { 38 | include /etc/nginx/defaults/proxy.conf; 39 | proxy_pass $upstream; 40 | modsecurity off; 41 | } 42 | 43 | include /etc/nginx/defaults/error-page.conf; 44 | 45 | ssl_certificate /etc/letsencrypt/live/insecure.example.com/fullchain.pem; # managed by Certbot 46 | ssl_certificate_key /etc/letsencrypt/live/insecure.example.com/privkey.pem; # managed by Certbot 47 | 48 | ssl_trusted_certificate /etc/letsencrypt/live/insecure.example.com/chain.pem; # managed by Certbot 49 | ssl_stapling on; # managed by Certbot 50 | ssl_stapling_verify on; # managed by Certbot 51 | 52 | } 53 | ``` 54 | 55 | Certbot 56 | ------- 57 | Easily add SSL security to your nginx hosts with certbot. 58 | `docker exec -it nginx-modsecurity /bin/sh` will bring up a prompt at which time you can `certbot` to your hearts content. 59 | 60 | _or_ 61 | 62 | `docker exec -it nginx-modsecurity certbot --no-redirect --must-staple -d example.com` 63 | 64 | It even auto-renew's for you every day! 65 | -------------------------------------------------------------------------------- /certbot.default.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | 4 | set -euf -o pipefail 5 | 6 | # ************** USAGE ************** 7 | # 8 | # This is an example hook that can be used with Certbot. 9 | # 10 | # Example usage (with certbot-auto and this hook file saved in /root/): 11 | # 12 | # sudo ./certbot-auto -d example.org -d www.example.org -a manual -i nginx --preferred-challenges dns \ 13 | # --manual-auth-hook "/root/certbot.default.sh auth" --manual-cleanup-hook "/root/certbot.default.sh cleanup" 14 | # 15 | # This hook requires configuration, continue reading. 16 | # 17 | # ************** CONFIGURATION ************** 18 | # 19 | # Please configure PROVIDER and PROVIDER_CREDENTIALS. 20 | # 21 | # PROVIDER: 22 | # Set this to whatever DNS host your domain is using: 23 | # 24 | # route53 cloudflare cloudns cloudxns digitalocean 25 | # dnsimple dnsmadeeasy dnspark dnspod easydns gandi 26 | # glesys godaddy linode luadns memset namecheap namesilo 27 | # nsone ovh pointhq powerdns rackspace rage4 softlayer 28 | # transip vultr yandex zonomi 29 | # 30 | # The full list is in Lexicon's README. 31 | # Defaults to Cloudflare. 32 | # 33 | PROVIDER=${DNS_PROVIDER} 34 | # 35 | # PROVIDER_CREDENTIALS: 36 | # Lexicon needs to know how to authenticate to your DNS Host. 37 | # This will vary from DNS host to host. 38 | # To figure out which flags to use, you can look at the Lexicon help. 39 | # For example, for help with Cloudflare: 40 | # 41 | # lexicon cloudflare -h 42 | # 43 | #PROVIDER_CREDENTIALS=("--auth-username=${DNS_USERNAME}" "--auth-token=${DNS_TOKEN}") 44 | # 45 | # PROVIDER_UPDATE_DELAY: 46 | # How many seconds to wait after updating your DNS records. This may be required, 47 | # depending on how slow your DNS host is to begin serving new DNS records after updating 48 | # them via the API. 30 seconds is a safe default, but some providers can be very slow 49 | # (e.g. Linode). 50 | # 51 | # Defaults to 30 seconds. 52 | # 53 | PROVIDER_UPDATE_DELAY=30 54 | 55 | # To be invoked via Certbot's --manual-auth-hook 56 | function auth { 57 | lexicon "${PROVIDER}" --auth-username="${DNS_USERNAME}" --auth-token="${DNS_TOKEN}" \ 58 | create "${CERTBOT_DOMAIN}" TXT --name "_acme-challenge.${CERTBOT_DOMAIN}" --content "${CERTBOT_VALIDATION}" 59 | echo "[Lexicon] Added _acme-challenge.${CERTBOT_DOMAIN}" 60 | sleep "${PROVIDER_UPDATE_DELAY}" 61 | } 62 | 63 | # To be invoked via Certbot's --manual-cleanup-hook 64 | function cleanup { 65 | lexicon "${PROVIDER}" --auth-username="${DNS_USERNAME}" --auth-token="${DNS_TOKEN}" \ 66 | delete "${CERTBOT_DOMAIN}" TXT --name "_acme-challenge.${CERTBOT_DOMAIN}" --content "${CERTBOT_VALIDATION}" 67 | echo "[Lexicon] Deleted _acme-challenge.${CERTBOT_DOMAIN}" 68 | } 69 | 70 | HANDLER=$1; shift; 71 | if [ -n "$(type -t $HANDLER)" ] && [ "$(type -t $HANDLER)" = function ]; then 72 | $HANDLER "$@" 73 | fi 74 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if [ ! -f "/etc/ssl/dhparam.pem" ]; then 4 | /usr/bin/openssl dhparam -out /etc/ssl/dhparam.pem 2048 5 | echo "Done" 6 | fi 7 | 8 | if [ -f "/usr/sbin/crond" ]; then 9 | crond -b -S -l 2 10 | fi 11 | 12 | if [ -f "/usr/sbin/nginx" ]; then 13 | /usr/sbin/nginx -g "daemon off;" "$@" 14 | else 15 | echo "There is no NGINX application installed" 16 | "$@" 17 | fi 18 | -------------------------------------------------------------------------------- /hooks/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # $IMAGE_NAME var is injected into the build so the tag is correct. 4 | docker build --build-arg VCS_REF=`git rev-parse --short HEAD` \ 5 | --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ 6 | -t $IMAGE_NAME . 7 | --------------------------------------------------------------------------------