commit 9d757bbee5782f1ea50e5f0f8e9432bba7f6265f Author: Daniel Wolf Date: Wed May 2 14:35:49 2018 -0400 initial commit diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..dc520cc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.git +LICENSE.md +README.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f358e2f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,76 @@ +FROM nephatrine/base-alpine:latest +LABEL maintainer="Daniel Wolf " + +RUN echo "====== PREPARE BASIC UTILITIES ======" \ + && apk --update upgrade \ + && apk add certbot geoip libgd libxslt pcre \ + && mkdir -p /var/cache/nginx \ + \ + && echo "====== PREPARE BUILD TOOLS ======" \ + && apk add --virtual .build-nginx gcc gd-dev geoip-dev git libatomic_ops-dev libc-dev libressl-dev libxml2-dev libxslt-dev linux-headers make pcre-dev zlib-dev \ + \ + && echo "====== COMPILE NGINX ======" \ + && cd /usr/src \ + && git clone https://github.com/nginx/nginx.git && cd nginx \ + && ./auto/configure \ + --prefix=/var/www \ + --sbin-path=/usr/sbin/nginx \ + --modules-path=/usr/lib/nginx/modules \ + --conf-path=/etc/nginx/nginx.conf \ + --error-log-path=/var/log/nginx/error.log \ + --pid-path=/var/run/nginx.pid \ + --lock-path=/var/run/nginx.lock \ + --user=guardian \ + --group=users \ + --with-threads \ + --with-file-aio \ + --with-http_ssl_module \ + --with-http_v2_module \ + --with-http_realip_module \ + --with-http_addition_module \ + --with-http_xslt_module=dynamic \ + --with-http_image_filter_module=dynamic \ + --with-http_geoip_module=dynamic \ + --with-http_sub_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_mp4_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_auth_request_module \ + --with-http_random_index_module \ + --with-http_secure_link_module \ + --with-http_degradation_module \ + --with-http_slice_module \ + --with-http_stub_status_module \ + --http-log-path=/var/log/nginx/access.log \ + --http-client-body-temp-path=/var/cache/nginx/client_body \ + --http-proxy-temp-path=/var/cache/nginx/proxy \ + --http-fastcgi-temp-path=/var/cache/nginx/fastcgi \ + --http-uwsgi-temp-path=/var/cache/nginx/uwsgi \ + --http-scgi-temp-path=/var/cache/nginx/scgi \ + --with-mail=dynamic \ + --with-mail_ssl_module \ + --with-stream=dynamic \ + --with-stream_ssl_module \ + --with-stream_realip_module \ + --with-stream_geoip_module=dynamic \ + --with-stream_ssl_preread_module \ + --with-compat \ + --with-pcre \ + --with-pcre-jit \ + --with-libatomic \ + && make -j4 && make install \ + && strip /usr/sbin/nginx \ + && strip /usr/lib/nginx/modules/*.so \ + \ + && echo "====== CLEANUP ======" \ + && cd /usr/src \ + && apk del --purge .build-nginx \ + && rm -rf \ + /tmp/* \ + /usr/src/* \ + /var/cache/apk/* + +EXPOSE 80 443 +COPY override / \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..a92e39a --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,13 @@ +Copyright © 2018 Daniel Wolf <> + +**Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies.** + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0496de9 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +[GitHub](https://github.com/nephatrine/docker-nginx-ssl) | +[DockerHub](https://hub.docker.com/r/nephatrine/nginx-ssl/) | +[unRAID](https://github.com/nephatrine/unraid-docker-templates) + +# NGINX+SSL (Certbot/LetsEncrypt) Docker + +This docker is intended to be used as a forwarding proxy to access other dockers. You can certainly +serve static content, but tools like PHP or MySQL are not included. + +Certbot is installed and can request SSL certificats from LetsEncrypt on your behalf assuming you +have entered the appropriate values. DNS challenges are not supported until I can come up with a +good way to automate it. Unfortunately, that means wildcard certificates cannot be requested at +this time. + +## Settings + +- **DNSADDR:** DNS IPs (space-delimited) +- **PUID:** Volume Owner UID +- **PGID:** Volume Owner GID +- **SSLEMAIL:** LetsEncrypt Email Address +- **SSLDOMAINS:** LetsEncrypt (Sub)domains (comma-delimited) +- **TZ:** Time Zone + +## Mount Points + +- **/mnt/config:** Configuration Volume \ No newline at end of file diff --git a/override/etc/cont-init.d/20-nginx b/override/etc/cont-init.d/20-nginx new file mode 100644 index 0000000..ffd6769 --- /dev/null +++ b/override/etc/cont-init.d/20-nginx @@ -0,0 +1,39 @@ +#!/usr/bin/with-contenv bash + +DNSADDR=${DNSADDR:-"8.8.8.8 8.8.4.4"} +SSLPRIMARY=`echo $SSLDOMAINS | tr ',' ' ' | awk '{print $1}'` + +if [[ ! -f /mnt/config/etc/mime.types ]]; then + s6-setuidgid guardian cp /etc/nginx/mime.types /mnt/config/etc/mime.types +fi + +if [[ ! -f /mnt/config/etc/nginx.conf ]]; then + sed -e "s/8.8.8.8 8.8.4.4/${DNSADDR}/g" /etc/nginx/nginx.conf | s6-setuidgid guardian tee /mnt/config/etc/nginx.conf +fi + +if [[ ! -d /mnt/config/etc/nginx.d ]]; then + s6-setuidgid guardian mkdir -p /mnt/config/etc/nginx.d + if [[ ! -z "${SSLPRIMARY}" ]]; then + sed -e "s/REPLACE_WITH_DOMAIN_NAME/${SSLPRIMARY}/g" /etc/nginx/nginx.d/default.conf | sed -e 's/#SSL://g' | sed -e 's/#NOSSL:/#/g' | s6-setuidgid guardian tee /mnt/config/www/default/default.conf + else + sed -e 's/#NOSSL://g' /etc/nginx/nginx.d/default.conf | sed -e 's/#SSL:/#/g' | s6-setuidgid guardian tee /mnt/config/www/default/default.conf + fi + s6-setuidgid guardian cp -n /etc/nginx/nginx.d/* /mnt/config/etc/nginx.d/ +fi + +if [[ ! -d /mnt/config/log ]]; then + s6-setuidgid guardian mkdir -p /mnt/config/log +fi + +if [[ ! -d /mnt/config/ssl ]]; then + s6-setuidgid guardian mkdir -p /mnt/config/ssl +fi + +if [[ ! -f /mnt/config/ssl/dhparam.pem ]]; then + s6-setuidgid guardian openssl dhparam -out /mnt/config/ssl/dhparam.pem 4096 +fi + +if [[ ! -d /mnt/config/www ]]; then + s6-setuidgid guardian mkdir -p /mnt/config/www/default + s6-setuidgid guardian cp -n /var/www/html/* /mnt/config/www/default/ +fi \ No newline at end of file diff --git a/override/etc/cont-init.d/21-certbot b/override/etc/cont-init.d/21-certbot new file mode 100644 index 0000000..c76b31d --- /dev/null +++ b/override/etc/cont-init.d/21-certbot @@ -0,0 +1,31 @@ +#!/usr/bin/with-contenv bash + +if [[ ! -d /mnt/config/ssl/live ]]; then + s6-setuidgid guardian mkdir -p /mnt/config/ssl/live +fi + +if [[ ! -f /mnt/config/etc/domains-configured ]]; then + echo "" > /mnt/config/etc/domains-configured +fi + +echo "$SSLDOMAINS" > /mnt/config/etc/domains-requested +CURDOMAINS=`head -1 /mnt/config/etc/domains-configured` + +if [[ "x$SSLDOMAINS" != "x$CURDOMAINS" ]]; then + if [[ $(ls /mnt/config/ssl/live | wc -l) -gt 0 ]]; then + ls /mnt/config/ssl/live | xargs -n1 -I{} certbot revoke -n --config-dir /mnt/config/ssl --logs-dir /mnt/config/log --max-log-backups 0 --cert-path "/mnt/config/ssl/live/{}/fullchain.pem" --reason superseded --work-dir /tmp/certbot + ls /mnt/config/ssl/live | xargs -n1 -I{} certbot delete -n --config-dir /mnt/config/ssl --logs-dir /mnt/config/log --max-log-backups 0 --cert-name "{}" --work-dir /tmp/certbot + rm -rf /mnt/config/etc/domains-configured + fi +fi + +if [[ $(ls /mnt/config/ssl/live | wc -l) -eq 0 ]]; then + if [[ ! -z "$SSLDOMAINS" && $SSLEMAIL == *@* ]]; then + certbot certonly -n --agree-tos --rsa-key-size 4096 --keep --config-dir /mnt/config/ssl --logs-dir /mnt/config/log --max-log-backups 0 --email "$SSLEMAIL" --standalone -d "$SSLDOMAINS" --work-dir /tmp/certbot + if [[ $(ls /mnt/config/ssl/live | wc -l) -gt 0 ]]; then + cp /mnt/config/etc/domains-requested /mnt/config/etc/domains-configured + fi + fi +else + certbot renew -n --agree-tos --rsa-key-size 4096 --config-dir /mnt/config/ssl --logs-dir /mnt/config/log --max-log-backups 0 --work-dir /tmp/certbot +fi \ No newline at end of file diff --git a/override/etc/fix-attrs.d/20-config-ssl b/override/etc/fix-attrs.d/20-config-ssl new file mode 100644 index 0000000..c48117c --- /dev/null +++ b/override/etc/fix-attrs.d/20-config-ssl @@ -0,0 +1 @@ +/mnt/config/ssl true guardian:users,1000:100 0600 0700 \ No newline at end of file diff --git a/override/etc/logrotate.d/letsencrypt b/override/etc/logrotate.d/letsencrypt new file mode 100644 index 0000000..c1792f5 --- /dev/null +++ b/override/etc/logrotate.d/letsencrypt @@ -0,0 +1,4 @@ +/mnt/config/log/letsencrypt.log { + missingok + notifempty +} \ No newline at end of file diff --git a/override/etc/logrotate.d/nginx b/override/etc/logrotate.d/nginx new file mode 100644 index 0000000..5e782a2 --- /dev/null +++ b/override/etc/logrotate.d/nginx @@ -0,0 +1,4 @@ +/mnt/config/log/nginx-access.log /mnt/config/log/nginx-error.log { + missingok + notifempty +} \ No newline at end of file diff --git a/override/etc/nginx/nginx.conf b/override/etc/nginx/nginx.conf new file mode 100644 index 0000000..b9eea17 --- /dev/null +++ b/override/etc/nginx/nginx.conf @@ -0,0 +1,84 @@ +user guardian; + +daemon off; +error_log /mnt/config/log/nginx-error.log warn; +worker_processes 4; +worker_rlimit_nofile 8192; + +events { + multi_accept on; + use epoll; + worker_connections 4096; +} + +http { + # ngx_http_core_module + + include mime.types; + + client_body_buffer_size 128k; + client_body_timeout 12s; + client_header_timeout 12s; + client_max_body_size 10m; + default_type application/octet-stream; + keepalive_requests 9001; + keepalive_timeout 65s; + open_file_cache max=1000 inactive=20s; + open_file_cache_errors on; + open_file_cache_min_uses 2; + open_file_cache_valid 30s; + resolver 8.8.8.8 8.8.4.4 valid=300s; + resolver_timeout 5s; + sendfile on; + server_tokens off; + tcp_nodelay on; + tcp_nopush on; + types_hash_max_size 2048; + + # ngx_http_charset_module + + charset utf-8; + + # ngx_http_gzip_module + + gzip on; + gzip_comp_level 4; + gzip_min_length 256; + gzip_proxied no-cache no-store private expired auth; + gzip_types text/css text/mathml text/plain text/xml image/svg+xml application/atom+xml application/javascript application/json application/rss+xml application/xhtml+xml application/xspf+xml; + gzip_vary on; + + # ngx_http_headers_module + + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; + add_header X-Content-Type-Options nosniff; + add_header X-Frame-Options SAMEORIGIN; + add_header X-Robots-Tag noarchive; + add_header X-XSS-Protection "1; mode=block"; + + # ngx_http_index_module + + index index.html; + + # ngx_http_log_module + + access_log /mnt/config/log/nginx-access.log; + + # ngx_http_ssl_module + # https://cipherli.st/ + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_dhparam /mnt/config/ssl/dhparam.pem; + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; + ssl_ecdh_curve secp384r1; + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + ssl_stapling on; + ssl_stapling_verify on; + + # Other Stuff + + include nginx.d/*.conf; +} \ No newline at end of file diff --git a/override/etc/nginx/nginx.d/default.conf b/override/etc/nginx/nginx.d/default.conf new file mode 100644 index 0000000..e2384a2 --- /dev/null +++ b/override/etc/nginx/nginx.d/default.conf @@ -0,0 +1,21 @@ +#SSL:server { +#SSL: listen 80 default_server; +#SSL: server_name _; +#SSL: return 301 https://$server_name$request_uri; +#SSL:} + +server { + #NOSSL:listen 80 default_server; + #SSL:listen 443 http2 ssl; + #SSL:ssl_certificate /mnt/config/ssl/live/REPLACE_WITH_DOMAIN_NAME/fullchain.pem; + #SSL:ssl_certificate_key /mnt/config/ssl/live/REPLACE_WITH_DOMAIN_NAME/privkey.pem; + #SSL:ssl_trusted_certificate /mnt/config/ssl/live/REPLACE_WITH_DOMAIN_NAME/chain.pem; + + server_name _; + root /mnt/config/www/default; + autoindex off; + + location ~ /\. { + deny all; + } +} \ No newline at end of file diff --git a/override/etc/services.d/20-nginx/run b/override/etc/services.d/20-nginx/run new file mode 100644 index 0000000..ff0976a --- /dev/null +++ b/override/etc/services.d/20-nginx/run @@ -0,0 +1,2 @@ +#!/usr/bin/with-contenv sh +exec nginx -c /mnt/config/etc/nginx.conf; \ No newline at end of file