From fed01369733a86c6248926800e7d17e8938743cb Mon Sep 17 00:00:00 2001 From: root <root@static.106.81.4.46.clients.your-server.de> Date: Mon, 18 Sep 2017 16:50:02 +0200 Subject: [PATCH] add reverse based on xataz/reverse (temporary) --- reverse/.drone.yml | 21 ++ reverse/Dockerfile | 138 +++++++++++++ reverse/README.md | 116 +++++++++++ reverse/auto_upgrade.sh | 32 +++ reverse/docker-compose.yml | 48 +++++ reverse/rootfs/etc/s6.d/.s6-svscan/finish | 3 + reverse/rootfs/etc/s6.d/check_certs/run | 7 + reverse/rootfs/etc/s6.d/nginx/run | 3 + reverse/rootfs/nginx/conf.d/headers.conf | 2 + reverse/rootfs/nginx/conf.d/proxy.conf | 11 ++ reverse/rootfs/nginx/conf.d/ssl.conf | 10 + reverse/rootfs/nginx/conf/nginx.conf | 77 ++++++++ reverse/rootfs/nginx/path.d/template | 5 + reverse/rootfs/nginx/path.d/template_auth | 7 + reverse/rootfs/nginx/sites-enabled/template | 6 + .../rootfs/nginx/sites-enabled/template_ssl | 27 +++ reverse/rootfs/nginx/www/letsencrypt | 0 reverse/rootfs/usr/local/bin/check_certs | 64 ++++++ reverse/rootfs/usr/local/bin/startup | 182 ++++++++++++++++++ 19 files changed, 759 insertions(+) create mode 100644 reverse/.drone.yml create mode 100644 reverse/Dockerfile create mode 100644 reverse/README.md create mode 100755 reverse/auto_upgrade.sh create mode 100644 reverse/docker-compose.yml create mode 100644 reverse/rootfs/etc/s6.d/.s6-svscan/finish create mode 100644 reverse/rootfs/etc/s6.d/check_certs/run create mode 100644 reverse/rootfs/etc/s6.d/nginx/run create mode 100644 reverse/rootfs/nginx/conf.d/headers.conf create mode 100644 reverse/rootfs/nginx/conf.d/proxy.conf create mode 100644 reverse/rootfs/nginx/conf.d/ssl.conf create mode 100644 reverse/rootfs/nginx/conf/nginx.conf create mode 100644 reverse/rootfs/nginx/path.d/template create mode 100644 reverse/rootfs/nginx/path.d/template_auth create mode 100644 reverse/rootfs/nginx/sites-enabled/template create mode 100644 reverse/rootfs/nginx/sites-enabled/template_ssl create mode 100644 reverse/rootfs/nginx/www/letsencrypt create mode 100644 reverse/rootfs/usr/local/bin/check_certs create mode 100644 reverse/rootfs/usr/local/bin/startup diff --git a/reverse/.drone.yml b/reverse/.drone.yml new file mode 100644 index 0000000..cf74e8d --- /dev/null +++ b/reverse/.drone.yml @@ -0,0 +1,21 @@ +pipeline: + build: + image: xataz/docker-drone-plugin + repo: xataz/reverse-nginx + action: build + volumes: + - /var/run/docker.sock:/var/run/docker.sock + + push: + image: xataz/docker-drone-plugin + repo: xataz/reverse-nginx + action: push + environment: + - UID=1000 + - GID=991 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /home/xataz/.docker/config.json:/docker/.docker/config.json + when: + branch: master + event: [push, tag, deployment] \ No newline at end of file diff --git a/reverse/Dockerfile b/reverse/Dockerfile new file mode 100644 index 0000000..a92d0e1 --- /dev/null +++ b/reverse/Dockerfile @@ -0,0 +1,138 @@ +FROM alpine:3.6 + +ENV UID=991 GID=991 + +ARG NGINX_VERSION=1.13.5 +ARG OPENSSL_VERSION=1.1.0f +ARG GPG_NGINX="B0F4 2533 73F8 F6F5 10D4 2178 520A 9993 A1C0 52F8" +ARG BUILD_CORES + +ARG NGINX_MODULES=" \ + --with-http_ssl_module \ + --with-http_v2_module \ + --with-http_gzip_static_module \ + --with-http_stub_status_module \ + --with-file-aio \ + --with-threads \ + --with-pcre-jit \ + --without-http_ssi_module \ + --without-http_scgi_module \ + --without-http_uwsgi_module \ + --without-http_geo_module \ + --without-http_autoindex_module \ + --without-http_split_clients_module \ + --without-http_memcached_module \ + --without-http_empty_gif_module \ + --without-http_browser_module" + +ARG NGINX_3RD_PARTY_MODULES=" \ + --add-module=/tmp/headers-more-nginx-module \ + --add-module=/tmp/ngx_brotli" + +RUN NB_CORES=${BUILD_CORES-$(getconf _NPROCESSORS_CONF)} \ + +# Update system + && apk -U upgrade \ + +# Installing runtime dependencies + && apk add \ + ${BUILD_DEPS} \ + pcre \ + zlib \ + libgcc \ + libstdc++ \ + jemalloc \ + su-exec \ + s6 \ + libressl \ + bind-tools \ + +# Installing build dependencies + && apk add -t build-dependencies \ + build-base \ + linux-headers \ + ca-certificates \ + automake \ + autoconf \ + git \ + go \ + jemalloc-dev \ + tar \ + libtool \ + pcre-dev \ + zlib-dev \ + binutils \ + gnupg \ + cmake \ + go \ + +# Brotli + && cd /tmp && git clone https://github.com/bagder/libbrotli --depth=1 \ + && cd libbrotli && ./autogen.sh && ./configure && make -j ${NB_CORES} && make install \ + && cd /tmp && git clone https://github.com/google/ngx_brotli --depth=1 \ + && cd ngx_brotli && git submodule update --init \ + +# Headers More + && cd /tmp && git clone https://github.com/openresty/headers-more-nginx-module --depth=1 \ + +# OpenSSL + && OPENSSL_TARBALL="openssl-${OPENSSL_VERSION}.tar.gz" \ + && wget -q https://www.openssl.org/source/${OPENSSL_TARBALL} \ + && tar xzf ${OPENSSL_TARBALL} \ + +# Nginx tarball checking + && NGINX_TARBALL="nginx-${NGINX_VERSION}.tar.gz" \ + && wget -q https://nginx.org/download/${NGINX_TARBALL} \ + && echo "Verifying ${NGINX_TARBALL} using GPG..." \ + && wget -q https://nginx.org/download/${NGINX_TARBALL}.asc \ + && wget -q https://nginx.org/keys/mdounin.key \ + && gpg --import mdounin.key \ + && FINGERPRINT="$(LANG=C gpg --verify ${NGINX_TARBALL}.asc ${NGINX_TARBALL} 2>&1 \ + | sed -n "s#Primary key fingerprint: \(.*\)#\1#p")" \ + && if [ -z "${FINGERPRINT}" ]; then echo "Warning! Invalid GPG signature!" && exit 1; fi \ + && if [ "${FINGERPRINT}" != "${GPG_NGINX}" ]; then echo "Warning! Wrong GPG fingerprint!" && exit 1; fi \ + && echo "All seems good, now unpacking ${NGINX_TARBALL}..." \ + && tar xzf ${NGINX_TARBALL} && cd nginx-${NGINX_VERSION} \ + +# Nginx patch : dynamic TLS records + && wget -q https://raw.githubusercontent.com/cujanovic/nginx-dynamic-tls-records-patch/master/nginx__dynamic_tls_records_1.13.0%2B.patch -O dynamic_records.patch \ + && patch -p1 < dynamic_records.patch \ + +# Nginx compilation + && ./configure \ + --prefix=/nginx \ + --sbin-path=/usr/local/sbin/nginx \ + --with-cc-opt="-O3 -fPIE -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -Wno-deprecated-declarations -I ../boringssl/.openssl/include/" \ + --with-ld-opt="-lrt -ljemalloc -Wl,-Bsymbolic-functions -Wl,-z,relro -L ../boringssl/.openssl/lib" \ + --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 -m64 -march=native -mtune=native -O3 -fPIE -fstack-protector-strong -D_FORTIFY_SOURCE=2' \ + --with-openssl=/tmp/openssl-${OPENSSL_VERSION} \ + --http-log-path=/nginx/log/nginx_access.log \ + --error-log-path=/nginx/log/nginx/nginx_error.log \ + --pid-path=/nginx/run/nginx.pid \ + --lock-path=/nginx/run/nginx.lock \ + --user=reverse --group=reverse \ + ${NGINX_MODULES} \ + ${NGINX_3RD_PARTY_MODULES} \ + && make -j ${NB_CORES} && make install && make clean \ + && strip -s /usr/local/sbin/nginx \ + +# Lego + && mkdir -p /tmp/go/bin \ + && export GOPATH=/tmp/go \ + && export GOBIN=$GOPATH/bin \ + && git config --global http.https://gopkg.in.followRedirects true \ + && go get github.com/xenolf/lego \ + && mv /tmp/go/bin/lego /usr/local/bin/lego \ + +# Clean + && apk del build-dependencies \ + && rm -rf /tmp/* /var/cache/apk/* /root/.gnupg + +COPY rootfs / + +RUN chmod +x /usr/local/bin/startup /etc/s6.d/*/* + +EXPOSE 8000 8443 + +ENTRYPOINT ["/usr/local/bin/startup"] +CMD ["/bin/s6-svscan", "/etc/s6.d"] diff --git a/reverse/README.md b/reverse/README.md new file mode 100644 index 0000000..b2a23a2 --- /dev/null +++ b/reverse/README.md @@ -0,0 +1,116 @@ + + +# BETA VERSION ACTUALY !!!!! +[](https://drone.xataz.net/xataz/docker-reverse-nginx) +[](https://microbadger.com/images/xataz/reverse-nginx "Get your own image badge on microbadger.com") +[](https://microbadger.com/images/xataz/reverse-nginx "Get your own version badge on microbadger.com") + +> This image is build and push with [drone.io](https://github.com/drone/drone), a circle-ci like self-hosted. +> If you don't trust, you can build yourself. + +## Tag available +* latest, mainline, 1.13.5, 1.13 [(Dockerfile)](https://github.com/xataz/dockerfiles/blob/master/reverse-nginx/Dockerfile) + +## Features +* No ROOT process +* Automatic configuration generation +* Automatic certificate generation and renew with letsencrypt and without downtime (use lego) +* Latest nginx version +* ARG for custom build + +## Description +What is [Nginx](http://nginx.org)? + +nginx (engine x) is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP proxy server, originally written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex, Mail.Ru, VK, and Rambler. According to Netcraft, nginx served or proxied 24.29% busiest sites in December 2015. Here are some of the success stories: Netflix, Wordpress.com, FastMail.FM. + +Reverse-nginx generate for you the configuration of reverse proxy. Like traefik, it is based on the labels of containers, but it isn't dynamicly. + +## Build Image +### Build arguments +* NGINX_CONF : Nginx make configure options +* NGINX_VER : Nginx version +* ARG NGINX_GPG : GPG fingerprint (default : "B0F4253373F8F6F510D42178520A9993A1C052F8") +* ARG BUILD_CORES : Number of core use for make nginx (default : All cores) + +### Simply build +```shell +docker build -t xataz/reverse-nginx github.com/xataz/dockerfiles.git#master:reverse-nginx +``` +### Build other version +```shell +docker build -t xataz/reverse-nginx --build-arg NGINX_VER=1.9.5 github.com/xataz/dockerfiles.git#master:reverse-nginx +``` + +## Configuration +### Environments +* UID : Choose uid for launch nginx (default : 991) +* GID : Choose gid for launch nginx (default : 991) + +### Volumes +* /nginx/ssl : For certificate persistance +* /nginx/custom_sites : For create your own sites + +### Ports +* 8080 +* 8443 + +## Usage +### Environments +| Variable | Description | default | value | +| -------- | ----------- | ------- | ----- | +| UID | UID for launch nginx | 991 | Valid UID number | +| GID | GID for launch nginx | 991 | Valid GID number | +| EMAIL | email use for generate letsencrypt certificates | admin@mydomain.local | Valid address mail | + +### Labels +| Label Name | Description | default | value | +| ---------- | ----------- | ------- | ----- | +| reverse.frontend.domain | Domain Name for this service | mydomain.local | valid domain name | +| reverse.frontend.path | Domain path (warning, no rewrite url) | / | valid path, with / | +| reverse.frontend.auth | For auth basic | none | user:encryptpassword | +| reverse.frontend.ssltype | Choose ssl type | ec384 | rsa2048, rsa4096, rsa8192, ec256 or ec384 | +| reverse.frontend.domain\_max\_body\_size | Choose max size upload | 200M | Numeric value with unit (K,M,G,T) | +| reverse.frontend.ssl | Generate letsencrypt certificate | false | true or false | +| reverse.backend.port | Port use by container | 8080 | Valid port number | + +More labels soon !!! + +### Launch +#### First launch another container +For exemple, I launch lutim container : +```shell +$ docker run -d \ + --name lutim \ + --label reverse.frontend.domain=sub.domain.com \ + --label reverse.frontend.path=lutim \ + --label reverse.frontend.auth=USER:$(openssl passwd -crypt PASSWORD) \ + --label reverse.frontend.ssltype=ec256 \ + --label reverse.frontend.ssl = true \ + --label reverse.backend.port=8181 \ + -v /docker/config/lutim/data:/data \ + -v /docker/data/lutim:/lutim/files \ + -e UID=1001 \ + -e GID=1001 \ + -e WEBROOT=/lutim \ + -e SECRET=$(date +%s | md5sum | head -c 32) \ + -e CONTACT=contact@domain.com \ + -e MAX_FILE_SIZE=250000000 \ + xataz/lutim +``` + + +#### Launch reverse-nginx +```shell +docker run -d \ + -p 80:8080 \ + -p 443:8443 \ + --name reverse \ + -e EMAIL=me@mydomain.com \ + -v /var/run/docker.sock:/var/run/docker.sock \ + xataz/reverse-nginx +``` + +URI Access : https://sub.domain.com/lutim + + + diff --git a/reverse/auto_upgrade.sh b/reverse/auto_upgrade.sh new file mode 100755 index 0000000..200243e --- /dev/null +++ b/reverse/auto_upgrade.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +NGINX_MAINLINE_VERSION=$(grep "NGINX_VER=" Dockerfile | cut -d"=" -f2) +NEW_NGINX_MAINLINE_VERSION=$(curl http://nginx.org/en/download.html 2> /dev/null | sed 's|>|>\n|g' | grep '^<a href="/download/nginx-' | head -1 | sed 's|.*nginx-\(.*\).tar.gz.*|\1|') + +f_gen_tag() { + VERSION=$1 + + TAGS="latest mainline ${VERSION} $(echo ${VERSION} | cut -d'.' -f '1 2')" +} + +f_maj_dockerfile() { + BUILD_VER=$(date +%Y%m%d01) + + ## Edit dockerfile + sed -i 's/NGINX_VER=.*/NGINX_VER='$1'/; + s/tags=".*"/tags="'"${TAGS}"'"/; + s/build_ver=".*"/build_ver="'${BUILD_VER}'"/' Dockerfile +} + +f_maj_readme() { + TAGS=$(echo $TAGS | sed 's/ /, /g') + + sed -i 's#\* .*/Dockerfile)#\* '"${TAGS}"' \[(Dockerfile)\](https://github.com/xataz/dockerfiles/blob/master/reverse-nginx/Dockerfile)#' README.md +} + +if [ "${NGINX_MAINLINE_VERSION}" != "${NEW_NGINX_MAINLINE_VERSION}" ]; then + echo "Update nginx mainline to ${NEW_NGINX_MAINLINE_VERSION}" + f_gen_tag ${NEW_NGINX_MAINLINE_VERSION} "latest mainline" + f_maj_dockerfile ${NEW_NGINX_MAINLINE_VERSION} + f_maj_readme +fi \ No newline at end of file diff --git a/reverse/docker-compose.yml b/reverse/docker-compose.yml new file mode 100644 index 0000000..94828be --- /dev/null +++ b/reverse/docker-compose.yml @@ -0,0 +1,48 @@ +version: '2' + +networks: + default: + driver: bridge + +services: + lutim: + image: xataz/lutim + container_name: lutim + labels: + - reverse.frontend.domain=sub.docker.local + - reverse.frontend.path=lutim + - reverse.frontend.auth=USER:zkgudxk6qOT5g + - reverse.backend.port=8181 + environment: + - UID=1001 + - GID=1001 + - WEBROOT=/lutim + - SECRET=908de85a9809724481c8a360c90879da + - CONTACT=contact@domain.com + - MAX_FILE_SIZE=250000000 + + lufi: + image: xataz/lufi + container_name: lufi + labels: + - reverse.frontend.domain=sub.docker.local + - reverse.frontend.path=lufi + - reverse.frontend.auth=USER:zkgudxk6qOT5g + - reverse.backend.port=8080 + environment: + - UID=1001 + - GID=1001 + - WEBROOT=/lufi + + reverse: + image: xataz/reverse-nginx + container_name: reverse + ports: + - "80:8080" + - "443:8443" + volumes: + - /docker/nginx/ssl:/nginx/ssl + - /var/run/docker.sock:/var/run/docker.sock + depends_on: + - lufi + - lutim \ No newline at end of file diff --git a/reverse/rootfs/etc/s6.d/.s6-svscan/finish b/reverse/rootfs/etc/s6.d/.s6-svscan/finish new file mode 100644 index 0000000..92b94c4 --- /dev/null +++ b/reverse/rootfs/etc/s6.d/.s6-svscan/finish @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 0 \ No newline at end of file diff --git a/reverse/rootfs/etc/s6.d/check_certs/run b/reverse/rootfs/etc/s6.d/check_certs/run new file mode 100644 index 0000000..0c104f4 --- /dev/null +++ b/reverse/rootfs/etc/s6.d/check_certs/run @@ -0,0 +1,7 @@ +#!/bin/sh + +sleep 60 +while true; do + /usr/local/bin/check_certs + sleep 86400 +done \ No newline at end of file diff --git a/reverse/rootfs/etc/s6.d/nginx/run b/reverse/rootfs/etc/s6.d/nginx/run new file mode 100644 index 0000000..4766ddb --- /dev/null +++ b/reverse/rootfs/etc/s6.d/nginx/run @@ -0,0 +1,3 @@ +#!/bin/sh + +exec nginx \ No newline at end of file diff --git a/reverse/rootfs/nginx/conf.d/headers.conf b/reverse/rootfs/nginx/conf.d/headers.conf new file mode 100644 index 0000000..d19d961 --- /dev/null +++ b/reverse/rootfs/nginx/conf.d/headers.conf @@ -0,0 +1,2 @@ +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; \ No newline at end of file diff --git a/reverse/rootfs/nginx/conf.d/proxy.conf b/reverse/rootfs/nginx/conf.d/proxy.conf new file mode 100644 index 0000000..0d22aeb --- /dev/null +++ b/reverse/rootfs/nginx/conf.d/proxy.conf @@ -0,0 +1,11 @@ + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Remote-Port $remote_port; + proxy_redirect off; + proxy_set_header Proxy ""; + proxy_pass_header Server; diff --git a/reverse/rootfs/nginx/conf.d/ssl.conf b/reverse/rootfs/nginx/conf.d/ssl.conf new file mode 100644 index 0000000..08cc05b --- /dev/null +++ b/reverse/rootfs/nginx/conf.d/ssl.conf @@ -0,0 +1,10 @@ +ssl_protocols TLSv1.2; +ssl_ecdh_curve X25519:P-521:P-384; +ssl_ciphers EECDH+CHACHA20:EECDH+AESGCM; +ssl_prefer_server_ciphers on; + +ssl_session_cache shared:SSL:20m; +ssl_session_timeout 15m; +ssl_session_tickets off; + +add_header Strict-Transport-Security "max-age=31536000"; diff --git a/reverse/rootfs/nginx/conf/nginx.conf b/reverse/rootfs/nginx/conf/nginx.conf new file mode 100644 index 0000000..adb4425 --- /dev/null +++ b/reverse/rootfs/nginx/conf/nginx.conf @@ -0,0 +1,77 @@ +#user web; +worker_processes auto; +pid /nginx/run/nginx.pid; +daemon off; + +events { + worker_connections 2048; + use epoll; +} + +http { + include /nginx/conf/mime.types; + default_type application/octet-stream; + + access_log /nginx/log/nginx_access.log combined; + error_log /nginx/log/nginx_error.log error; + + aio threads; + aio_write on; + + more_set_headers 'secret'; + + sendfile on; + keepalive_timeout 15; + keepalive_disable msie6; + keepalive_requests 100; + tcp_nopush on; + tcp_nodelay off; + server_tokens off; + proxy_max_temp_file_size 20480m; + + gzip on; + gzip_comp_level 5; + gzip_min_length 512; + gzip_buffers 4 8k; + gzip_proxied any; + gzip_vary on; + gzip_disable "msie6"; + gzip_types + text/css + text/javascript + text/xml + text/plain + text/x-component + application/javascript + application/x-javascript + application/json + application/xml + application/rss+xml + application/vnd.ms-fontobject + font/truetype + font/opentype + image/svg+xml; + + brotli on; + brotli_static on; + brotli_buffers 16 8k; + brotli_comp_level 6; + brotli_types + text/css + text/javascript + text/xml + text/plain + text/x-component + application/javascript + application/x-javascript + application/json + application/xml + application/rss+xml + application/vnd.ms-fontobject + font/truetype + font/opentype + image/svg+xml; + + include /nginx/sites-enabled/*.conf; + include /nginx/custom_sites/*.conf; +} diff --git a/reverse/rootfs/nginx/path.d/template b/reverse/rootfs/nginx/path.d/template new file mode 100644 index 0000000..10b2600 --- /dev/null +++ b/reverse/rootfs/nginx/path.d/template @@ -0,0 +1,5 @@ + location <frontend_path> { + include /nginx/conf.d/proxy.conf; + client_max_body_size <frontend_domain_max_body_size>; + proxy_pass http://<backend_addr>:<backend_port>; + } \ No newline at end of file diff --git a/reverse/rootfs/nginx/path.d/template_auth b/reverse/rootfs/nginx/path.d/template_auth new file mode 100644 index 0000000..eea9bf7 --- /dev/null +++ b/reverse/rootfs/nginx/path.d/template_auth @@ -0,0 +1,7 @@ + location <frontend_path> { + include /nginx/conf.d/proxy.conf; + auth_basic "Who's this?"; + auth_basic_user_file "<auth_file>"; + client_max_body_size <frontend_domain_max_body_size>; + proxy_pass http://<backend_addr>:<backend_port>; + } \ No newline at end of file diff --git a/reverse/rootfs/nginx/sites-enabled/template b/reverse/rootfs/nginx/sites-enabled/template new file mode 100644 index 0000000..d82fd18 --- /dev/null +++ b/reverse/rootfs/nginx/sites-enabled/template @@ -0,0 +1,6 @@ +server { + listen 8080; + server_name <frontend_domain>; + include /nginx/conf.d/headers.conf; + include /nginx/path.d/<frontend_domain>/*.conf; +} \ No newline at end of file diff --git a/reverse/rootfs/nginx/sites-enabled/template_ssl b/reverse/rootfs/nginx/sites-enabled/template_ssl new file mode 100644 index 0000000..70a6fc5 --- /dev/null +++ b/reverse/rootfs/nginx/sites-enabled/template_ssl @@ -0,0 +1,27 @@ +server { + listen 8080; + server_name <frontend_domain>; + + rewrite ^ https://<frontend_domain>:443$request_uri? permanent; +} + + +server { + + listen 8443 ssl http2; + server_name <frontend_domain>; + index index.html index.php index.htm; + + ssl_certificate /nginx/ssl/certificates/<frontend_domain>.crt; + ssl_certificate_key /nginx/ssl/certificates/<frontend_domain>.key; + ssl_trusted_certificate /nginx/ssl/certificates/<frontend_domain>.chain.pem; + include /nginx/conf.d/ssl.conf; + include /nginx/conf.d/headers.conf; + + include /nginx/path.d/<frontend_domain>/*.conf; + + location ~ /\.well-known/acme-challenge { + root /nginx/www/<frontend_domain>; + allow all; + } +} diff --git a/reverse/rootfs/nginx/www/letsencrypt b/reverse/rootfs/nginx/www/letsencrypt new file mode 100644 index 0000000..e69de29 diff --git a/reverse/rootfs/usr/local/bin/check_certs b/reverse/rootfs/usr/local/bin/check_certs new file mode 100644 index 0000000..8054b3a --- /dev/null +++ b/reverse/rootfs/usr/local/bin/check_certs @@ -0,0 +1,64 @@ +#!/bin/sh + +## Variables +CSI="\033[" +CEND="${CSI}0m" +CRED="${CSI}1;31m" +CGREEN="${CSI}1;32m" +CYELLOW="${CSI}1;33m" +CBLUE="${CSI}1;34m" + +## Functions +f_log() { + LOG_TYPE=$1 + LOG_MESSAGE=$2 + + case "${LOG_TYPE}" in + "INF") + echo -e "${CBLUE}=INF= $(date +%Y/%m/%d-%H:%M:%S) ${LOG_MESSAGE}${CEND}" + ;; + "WRN") + echo -e "${CYELLOW}=WRN= $(date +%Y/%m/%d-%H:%M:%S) ${LOG_MESSAGE}${CEND}" + ;; + "ERR") + echo -e "${CRED}=ERR= $(date +%Y/%m/%d-%H:%M:%S) ${LOG_MESSAGE}${CEND}" + ;; + esac +} + +f_check_certs() { + LIST_DOMAINS=$(ls /nginx/ssl/certificates | grep .crt | grep -v issuer | sed 's|.crt||g') + RELOAD_NGINX=0 + + for domain in ${LIST_DOMAINS}; do + CERTFILE=/nginx/ssl/certificates/${domain}.cert.pem + KEYFILE=/nginx/ssl/certificates/${domain}.key + CHAINFILE=/nginx/ssl/certificates/${domain}.chain.pem + FULLCHAINFILE=/nginx/ssl/certificates/${domain}.crt + + mkdir -p /nginx/www/${domain} + openssl x509 -checkend 864000 -noout -in "${FULLCHAINFILE}" + if [ $? == 0 ]; then + f_log INF "Certificate for ${domain} is good for another 10 days!" + else + f_log INF "Generate New Certificate for ${domain}" + /usr/local/bin/lego -a -m ${EMAIL} -d ${domain} --path /nginx/ssl --webroot /nginx/www/${domain} renew + if [ $? == 0 ]; then + if [ -e ${FULLCHAINFILE} ]; then + head -$(grep -n "END CERTIFICATE" ${FULLCHAINFILE} | head -1 | cut -d: -f1) ${FULLCHAINFILE} > ${CERTFILE} + tail -$(($(wc -l ${FULLCHAINFILE} | awk '{print $1}')-$(grep -n "END CERTIFICATE" ${FULLCHAINFILE} | head -1 | cut -d: -f1))) ${FULLCHAINFILE} > ${CHAINFILE} + RELOAD_NGINX=1 + f_log INF "New Certificate for ${domain} generated" + fi + else + f_log ERR "New Certificate for ${domain} not generated" + fi + fi + done +} + +f_check_certs + +if [ ${RELOAD_NGINX} -eq 1 ]; then + nginx reload +fi diff --git a/reverse/rootfs/usr/local/bin/startup b/reverse/rootfs/usr/local/bin/startup new file mode 100644 index 0000000..57ad10b --- /dev/null +++ b/reverse/rootfs/usr/local/bin/startup @@ -0,0 +1,182 @@ +#!/bin/sh + +## Variables +CSI="\033[" +CEND="${CSI}0m" +CRED="${CSI}1;31m" +CGREEN="${CSI}1;32m" +CYELLOW="${CSI}1;33m" +CBLUE="${CSI}1;34m" + +## Functions +f_log() { + LOG_TYPE=$1 + LOG_MESSAGE=$2 + + case "${LOG_TYPE}" in + "INF") + echo -e "${CBLUE}=INF= $(date +%Y/%m/%d-%H:%M:%S) ${LOG_MESSAGE}${CEND}" + ;; + "SUC") + echo -e "${CGREEN}=SUC= $(date +%Y/%m/%d-%H:%M:%S) ${LOG_MESSAGE}${CEND}" + ;; + "WRN") + echo -e "${CYELLOW}=WRN= $(date +%Y/%m/%d-%H:%M:%S) ${LOG_MESSAGE}${CEND}" + ;; + "ERR") + echo -e "${CRED}=ERR= $(date +%Y/%m/%d-%H:%M:%S) ${LOG_MESSAGE}${CEND}" + ;; + esac +} + +f_gen_sites_enabled() { + if [ "${FRONTEND_SSL}" == "true" ]; then + template_sites=/nginx/sites-enabled/template_ssl + else + template_sites=/nginx/sites-enabled/template + fi + sed -e 's|<frontend_domain>|'${FRONTEND_DOMAIN}'|' ${template_sites} > /nginx/sites-enabled/${FRONTEND_DOMAIN}.conf +} + +f_gen_location() { + container_name=$1 + if [ ! -d /nginx/path.d/${FRONTEND_DOMAIN} ]; then + mkdir -p /nginx/path.d/${FRONTEND_DOMAIN} + fi + + if [ "${FRONTEND_PATH}" == "/" ]; then + path_file=/nginx/path.d/${FRONTEND_DOMAIN}/base.conf + auth_file=/nginx/auth/${FRONTEND_DOMAIN}/base.auth + else + path_file=/nginx/path.d/${FRONTEND_DOMAIN}/${FRONTEND_PATH}.conf + auth_file=/nginx/auth/${FRONTEND_DOMAIN}/${FRONTEND_PATH}.auth + fi + if [ ! -e ${path_file} ]; then + if [ "${FRONTEND_AUTH}" != "" ]; then + mkdir -p /nginx/auth/${FRONTEND_DOMAIN} + sed -e 's|<frontend_domain_max_body_size>|'${FRONTEND_MAX_BODY_SIZE}'|' \ + -e 's|<backend_addr>|'${container_name}'|' \ + -e 's|<backend_port>|'${BACKEND_PORT}'|' \ + -e 's|<frontend_domain>|'${FRONTEND_DOMAIN}'|' \ + -e 's|<frontend_path>|'${FRONTEND_PATH}'|' \ + -e 's|<auth_file>|'${auth_file}'|' /nginx/path.d/template_auth > ${path_file} + echo "${FRONTEND_AUTH}" > ${auth_file} + else + sed -e 's|<frontend_domain_max_body_size>|'${FRONTEND_MAX_BODY_SIZE}'|' \ + -e 's|<backend_addr>|'${container_name}'|' \ + -e 's|<backend_port>|'${BACKEND_PORT}'|' \ + -e 's|<frontend_path>|'${FRONTEND_PATH}'|' /nginx/path.d/template > ${path_file} + fi + fi +} + +f_gen_certs() { + container_name=$1 + if [ "${FRONTEND_SSL}" == "true" ]; then + CERTFILE=/nginx/ssl/certificates/${FRONTEND_DOMAIN}.cert.pem + KEYFILE=/nginx/ssl/certificates/${FRONTEND_DOMAIN}.key + CHAINFILE=/nginx/ssl/certificates/${FRONTEND_DOMAIN}.chain.pem + FULLCHAINFILE=/nginx/ssl/certificates/${FRONTEND_DOMAIN}.crt + if [ ! -e ${CERTFILE} ] || [ ! -e ${KEYFILE} ] || [ ! -e ${CHAINFILE} ] || [ ! -e ${FULLCHAINFILE} ]; then + mkdir -p /nginx/www/${FRONTEND_DOMAIN} + /usr/local/bin/lego -a -m ${EMAIL} -d ${FRONTEND_DOMAIN} --path /nginx/ssl --http :8080 --tls :8443 -k ${FRONTEND_SSLTYPE} run + if [ $? == 0 ]; then + head -$(grep -n "END CERTIFICATE" ${FULLCHAINFILE} | head -1 | cut -d: -f1) ${FULLCHAINFILE} > ${CERTFILE} + tail -$(($(wc -l ${FULLCHAINFILE} | awk '{print $1}')-$(grep -n "END CERTIFICATE" ${FULLCHAINFILE} | head -1 | cut -d: -f1))) ${FULLCHAINFILE} > ${CHAINFILE} + chown -R ${UID}:${GID} /nginx/ssl/ + fi + [[ $? == 0 ]] && f_log INF "New Certificate for ${FRONTEND_DOMAIN} generated" || f_log ERR "New Certificate for ${FRONTEND_DOMAIN} not generated" + fi + fi +} + + + +f_make_conf() { + + FRONTEND_DOMAIN=mydomain.local + FRONTEND_MAX_BODY_SIZE=200M + FRONTEND_SSLTYPE=ec384 + BACKEND_PORT=8080 + FRONTEND_PATH="/" + FRONTEND_SSL=false + FRONTEND_AUTH="" + + container_name=$1 + IFS=$'\n' + if [ "${CONTAINER_LABELS}" != "" ]; then + for label in ${CONTAINER_LABELS}; do + case "$(echo ${label} | awk '{print $1}')" in + "reverse.frontend.domain") + FRONTEND_DOMAIN="" + FRONTEND_DOMAIN="$(echo ${label} | awk '{print $2}')" + ;; + "reverse.frontend.path") + FRONTEND_PATH="$(echo ${label} | awk '{print $2}')" + ;; + "reverse.frontend.auth") + FRONTEND_AUTH="$(echo ${label} | awk '{print $2}')" + ;; + "reverse.frontend.ssltype") + FRONTEND_SSLTYPE="$(echo ${label} | awk '{print $2}')" + ;; + "reverse.frontend.domain_max_body_size") + FRONTEND_MAX_BODY_SIZE="$(echo ${label} | awk '{print $2}')" + ;; + "reverse.frontend.ssl") + FRONTEND_SSL="$(echo ${label} | awk '{print $2}')" + ;; + "reverse.backend.port") + BACKEND_PORT="$(echo ${label} | awk '{print $2}')" + ;; + esac + done + f_log INF "Generate files for ${FRONTEND_DOMAIN}, with path=${FRONTEND_PATH}, auth=${FRONTEND_AUTH}, ssl_type=${FRONTEND_SSLTYPE}, ssl=${FRONTEND_SSL} and port=${BACKEND_PORT}" + f_gen_location ${container_name} + f_gen_sites_enabled + f_gen_certs ${container_name} + fi +} + + +# Check /var/run/docker.sock +f_log INF "Check if /var/run/docker.sock exist ..." +ls /var/run/docker.sock > /dev/null 2>&1 +if [ $? == 0 ]; then + f_log INF "/var/run/docker.sock exist ..." +else + f_log ERR "/var/run/docker.sock don't exist ..." + exit 1 +fi + + +f_log INF "Start reverse configuration ..." + +# Prepare container +f_log INF "Create user 'reverse'" +addgroup -g ${GID} reverse && adduser -H -s /bin/sh -D -G reverse -u ${UID} reverse +f_log INF "Create folder" +mkdir -p /nginx/sites-enabled /nginx /nginx/log /nginx/run /nginx/sites-enabled /nginx/ssl /nginx/ssl/selfsigned/dhparam + + +# Generate file +for container in $(curl --unix-socket /var/run/docker.sock http://localhost/containers/json 2> /dev/null | jq '.[].Names' | sed 's|.*"/\(.*\)"$|\1|;/\[/d;/\]/d'); do + CONTAINER_LABELS=$(curl --unix-socket /var/run/docker.sock http://localhost/containers/${container}/json 2> /dev/null | jq '.Config.Labels' | grep -E "reverse\." | sed 's|.*"\(.*\)": "\(.*\)".*$|\1 \2|') + f_make_conf ${container} +done + +f_log INF "Apply permissions" +chown -R reverse:reverse /nginx /etc/s6.d +chmod +x /usr/local/bin/check_certs +find /etc/s6.d -name run -exec chmod +x {} \; +find /etc/s6.d -name finish -exec chmod +x {} \; + +f_log SUC "End reverse configuration" + + +## run s6 +if [ $# -gt 0 ]; then + exec su-exec reverse:reverse "$@" +else + exec su-exec reverse:reverse /bin/s6-svscan /etc/s6.d +fi