diff --git a/Dockerfile b/Dockerfile index 867d100..10de92d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,7 @@ RUN libpython="${PYTHON_SITE_PACKAGES%/*}" ; \ ## Python cache warmup RUN j2cfg-single /usr/local/lib/j2cfg/test.j2 /tmp/test ; \ - cat /tmp/test ; echo ; \ + cat /tmp/test ; echo ; echo ; \ rm -f /tmp/test ## Python cache adjustments @@ -99,13 +99,9 @@ RUN apt-install.sh angie ; \ if [ "${NGX_DEBUG}" = 0 ] ; then \ rm -fv "$n-debug" ; \ mv -fv "$n-nodebug" "$n" ; \ - ln -fsv "${n##*/}" "$n-nodebug" ; \ - ln -fsv /bin/false "$n-debug" ; \ else \ rm -fv "$n-nodebug" ; \ mv -fv "$n-debug" "$n" ; \ - ln -fsv "${n##*/}" "$n-debug" ; \ - ln -fsv /bin/false "$n-nodebug" ; \ fi ## preserve snippets from Angie config directory @@ -142,7 +138,7 @@ RUN install -d -o angie -g angie -m 03777 /angie /run/angie ; \ ln -sv /run/angie/lock lock ; \ ln -sv ${ANGIE_MODULES_DIR} modules.dist ; \ ## hyper-modular paths: - data='conf j2cfg mod modules site snip static' ; \ + data='autoconf conf j2cfg mod modules site snip static' ; \ vardata='cache lib log' ; \ for n in ${data} ; do \ for d in "$n" "$n.dist" ; do \ @@ -153,6 +149,17 @@ RUN install -d -o angie -g angie -m 03777 /angie /run/angie ; \ ln -sv "/run/angie/$n" "$n.d" ; \ done +## future quirk for angie-module-modsecurity >:) +RUN n='modsecurity' ; \ + d="/etc/angie/$n" ; \ + ln -sv "/run/angie/$n" "$d.d" ; \ + dpkg-divert --divert "$d.dist" --rename "$d" ; \ + for p in modsecurity.conf unicode.mapping ; do \ + dpkg-divert --divert "$d.dist/$p" --rename "$d/$p" ; \ + done ; \ + p='rules.conf' ; \ + dpkg-divert --divert "$d.dist/$p.dist" --rename "$d/$p" + VOLUME [ "/run/angie" ] COPY /angie/ /etc/angie/ diff --git a/angie/angie.conf b/angie/angie.conf index 9303fb3..9513111 100644 --- a/angie/angie.conf +++ b/angie/angie.conf @@ -10,10 +10,10 @@ include load/mod-core-*.conf; include run/mod-*.conf; events { - include conf.d/core_ev-*.conf; + include autoconf.d/core_ev-*.conf; include load/core_ev-*.conf; } -include conf.d/core-*.conf; +include autoconf.d/core-*.conf; include load/core-*.conf; # ctx-http.conf diff --git a/angie/conf.dist/core-error-log.conf b/angie/autoconf.dist/core-error-log.conf similarity index 100% rename from angie/conf.dist/core-error-log.conf rename to angie/autoconf.dist/core-error-log.conf diff --git a/angie/conf.dist/core-lock-file.conf b/angie/autoconf.dist/core-lock-file.conf similarity index 100% rename from angie/conf.dist/core-lock-file.conf rename to angie/autoconf.dist/core-lock-file.conf diff --git a/angie/conf.dist/core-pcre-jit.conf b/angie/autoconf.dist/core-pcre-jit.conf similarity index 100% rename from angie/conf.dist/core-pcre-jit.conf rename to angie/autoconf.dist/core-pcre-jit.conf diff --git a/angie/conf.dist/core-user.conf.in b/angie/autoconf.dist/core-user.conf.in similarity index 100% rename from angie/conf.dist/core-user.conf.in rename to angie/autoconf.dist/core-user.conf.in diff --git a/angie/conf.dist/core-worker-env.conf.j2 b/angie/autoconf.dist/core-worker-env.conf.j2 similarity index 72% rename from angie/conf.dist/core-worker-env.conf.j2 rename to angie/autoconf.dist/core-worker-env.conf.j2 index fddbd30..bb8f0e7 100644 --- a/angie/conf.dist/core-worker-env.conf.j2 +++ b/angie/autoconf.dist/core-worker-env.conf.j2 @@ -1,15 +1,19 @@ {#- prologue -#} {#- NB: "TZ" is always provided by Angie itself -#} -{%- set s_vars = ['MALLOC_ARENA_MAX', 'GLIBC_TUNABLES', 'MALLOC_CONF'] -%} {%- set c_env = ( j2cfg.core_worker_env or [] ) | any_to_env_dict -%} {%- set c_vars = c_env | dict_keys -%} -{%- set c_vars_preserve = c_env | dict_empty_keys -%} +{%- set c_vars_passthrough = c_env | dict_empty_keys -%} {%- set c_vars_override = c_env | dict_non_empty_keys -%} -{%- set vars_preserve = ( c_vars_preserve + s_vars ) | uniq | sort -%} +{%- set vars_passthrough = (env_passthrough + c_vars_passthrough) | uniq | list_intersect(env | dict_keys) -%} {#- main part -#} ## preserve -{%- for k in vars_preserve %} +{%- for k in env_preserve %} +env {{ k }}; +{%- endfor %} + +## passthrough +{%- for k in vars_passthrough %} env {{ k }}; {%- endfor %} diff --git a/angie/autoconf.dist/core-worker.conf.j2 b/angie/autoconf.dist/core-worker.conf.j2 new file mode 100644 index 0000000..76554c0 --- /dev/null +++ b/angie/autoconf.dist/core-worker.conf.j2 @@ -0,0 +1,10 @@ +worker_processes {{ env.NGX_WORKER_PROCESSES }}; +{%- if env.NGX_WORKER_CPU_AFFINITY %} +worker_cpu_affinity {{ env.NGX_WORKER_CPU_AFFINITY }}; +{%- endif %} +{%- if env.NGX_WORKER_PRIORITY %} +worker_priority {{ env.NGX_WORKER_PRIORITY }}; +{%- endif %} +{%- if env.NGX_WORKER_RLIMIT_NOFILE %} +worker_rlimit_nofile {{ env.NGX_WORKER_RLIMIT_NOFILE }}; +{%- endif %} \ No newline at end of file diff --git a/angie/autoconf.dist/core_ev-worker.conf.j2 b/angie/autoconf.dist/core_ev-worker.conf.j2 new file mode 100644 index 0000000..4a61641 --- /dev/null +++ b/angie/autoconf.dist/core_ev-worker.conf.j2 @@ -0,0 +1,7 @@ +worker_connections {{ env.NGX_WORKER_CONNECTIONS }}; +{%- if env.NGX_WORKER_AIO_REQUESTS %} +worker_aio_requests {{ env.NGX_WORKER_AIO_REQUESTS }}; +{%- endif %} +{%- if env.NGX_WORKER_PRIORITY %} +worker_priority {{ env.NGX_WORKER_PRIORITY }}; +{%- endif %} \ No newline at end of file diff --git a/angie/conf.dist/http-access-log.conf b/angie/autoconf.dist/http-access-log.conf similarity index 100% rename from angie/conf.dist/http-access-log.conf rename to angie/autoconf.dist/http-access-log.conf diff --git a/angie/conf.dist/http-buffers.conf b/angie/autoconf.dist/http-buffers.conf similarity index 100% rename from angie/conf.dist/http-buffers.conf rename to angie/autoconf.dist/http-buffers.conf diff --git a/angie/autoconf.dist/http-max-ranges.conf.j2 b/angie/autoconf.dist/http-max-ranges.conf.j2 new file mode 100644 index 0000000..64b25de --- /dev/null +++ b/angie/autoconf.dist/http-max-ranges.conf.j2 @@ -0,0 +1,3 @@ +{%- if env.NGX_HTTP_MAX_RANGES %} +max_ranges {{ env.NGX_HTTP_MAX_RANGES }}; +{%- endif %} \ No newline at end of file diff --git a/angie/conf.dist/http-mime-types.conf b/angie/autoconf.dist/http-mime-types.conf similarity index 100% rename from angie/conf.dist/http-mime-types.conf rename to angie/autoconf.dist/http-mime-types.conf diff --git a/angie/autoconf.dist/http-webroot.conf.in b/angie/autoconf.dist/http-webroot.conf.in new file mode 100644 index 0000000..51fb841 --- /dev/null +++ b/angie/autoconf.dist/http-webroot.conf.in @@ -0,0 +1 @@ +root ${NGX_HTTP_WEBROOT}; \ No newline at end of file diff --git a/angie/snip.dist/brotli/buffers.conf b/angie/conf.dist/brotli/buffers.conf similarity index 100% rename from angie/snip.dist/brotli/buffers.conf rename to angie/conf.dist/brotli/buffers.conf diff --git a/angie/conf.dist/brotli/types.conf.j2 b/angie/conf.dist/brotli/types.conf.j2 new file mode 100644 index 0000000..e6c87d1 --- /dev/null +++ b/angie/conf.dist/brotli/types.conf.j2 @@ -0,0 +1,9 @@ +{%- set mime_types = j2cfg.brotli_compress_types or j2cfg.compress_types or [] -%} +{%- set mime_types = mime_types | any_to_str_list | uniq_str_list -%} +{%- if mime_types -%} +brotli_types +{%- for t in mime_types %} + {{ t }} +{%- endfor %} +; +{%- endif -%} \ No newline at end of file diff --git a/angie/snip.dist/core-quic-bpf.conf b/angie/conf.dist/core-quic-bpf.conf similarity index 100% rename from angie/snip.dist/core-quic-bpf.conf rename to angie/conf.dist/core-quic-bpf.conf diff --git a/angie/conf.dist/core-worker.conf.in b/angie/conf.dist/core-worker.conf.in deleted file mode 100644 index a2f6a1d..0000000 --- a/angie/conf.dist/core-worker.conf.in +++ /dev/null @@ -1,3 +0,0 @@ -worker_processes ${NGX_WORKER_PROCESSES}; -worker_priority ${NGX_WORKER_PRIORITY}; -worker_rlimit_nofile ${NGX_WORKER_RLIMIT_NOFILE}; \ No newline at end of file diff --git a/angie/snip.dist/core_ev-accept-mutex-delay.conf b/angie/conf.dist/core_ev-accept-mutex-delay.conf similarity index 100% rename from angie/snip.dist/core_ev-accept-mutex-delay.conf rename to angie/conf.dist/core_ev-accept-mutex-delay.conf diff --git a/angie/snip.dist/core_ev-accept-mutex.conf b/angie/conf.dist/core_ev-accept-mutex.conf similarity index 100% rename from angie/snip.dist/core_ev-accept-mutex.conf rename to angie/conf.dist/core_ev-accept-mutex.conf diff --git a/angie/snip.dist/core_ev-multi-accept.conf b/angie/conf.dist/core_ev-multi-accept.conf similarity index 100% rename from angie/snip.dist/core_ev-multi-accept.conf rename to angie/conf.dist/core_ev-multi-accept.conf diff --git a/angie/conf.dist/core_ev-worker.conf.in b/angie/conf.dist/core_ev-worker.conf.in deleted file mode 100644 index 87bf0c4..0000000 --- a/angie/conf.dist/core_ev-worker.conf.in +++ /dev/null @@ -1 +0,0 @@ -worker_connections ${NGX_WORKER_CONNECTIONS}; \ No newline at end of file diff --git a/angie/conf.dist/fastcgi/buffers.conf b/angie/conf.dist/fastcgi/buffers.conf new file mode 100644 index 0000000..6198dff --- /dev/null +++ b/angie/conf.dist/fastcgi/buffers.conf @@ -0,0 +1,4 @@ +fastcgi_buffers 16 16k; +fastcgi_buffer_size 16k; +fastcgi_busy_buffers_size 32k; +fastcgi_temp_file_write_size 32k; \ No newline at end of file diff --git a/angie/conf.dist/fastcgi/headers.conf.j2 b/angie/conf.dist/fastcgi/headers.conf.j2 new file mode 100644 index 0000000..ecec9d5 --- /dev/null +++ b/angie/conf.dist/fastcgi/headers.conf.j2 @@ -0,0 +1,13 @@ +## hide/remove request headers +{%- set req_hdr_list = j2cfg.fastcgi_remove_request_headers or j2cfg.remove_request_headers or [] -%} +{%- set req_hdr_list = req_hdr_list | any_to_str_list | as_cgi_header -%} +{%- for h in req_hdr_list %} +fastcgi_param {{ h }} ""; +{%- endfor %} + +## hide response headers +{%- set resp_hdr_list = j2cfg.fastcgi_remove_response_headers or j2cfg.remove_response_headers or [] -%} +{%- set resp_hdr_list = resp_hdr_list | any_to_str_list | uniq_str_list -%} +{%- for h in resp_hdr_list %} +fastcgi_hide_header {{ h }}; +{%- endfor %} diff --git a/angie/conf.dist/fastcgi/param.conf b/angie/conf.dist/fastcgi/param.conf new file mode 100644 index 0000000..863a37e --- /dev/null +++ b/angie/conf.dist/fastcgi/param.conf @@ -0,0 +1,7 @@ +include snip.d/fastcgi.conf; + +fastcgi_param PATH_INFO $path_info; + +fastcgi_param AUTH_USER $remote_user; +fastcgi_param REMOTE_USER $remote_user; +fastcgi_param HTTP_HOST $host; \ No newline at end of file diff --git a/angie/conf.dist/grpc/buffers.conf b/angie/conf.dist/grpc/buffers.conf new file mode 100644 index 0000000..03efeee --- /dev/null +++ b/angie/conf.dist/grpc/buffers.conf @@ -0,0 +1 @@ +grpc_buffer_size 16k; \ No newline at end of file diff --git a/angie/conf.dist/grpc/headers.conf.j2 b/angie/conf.dist/grpc/headers.conf.j2 new file mode 100644 index 0000000..ab7d433 --- /dev/null +++ b/angie/conf.dist/grpc/headers.conf.j2 @@ -0,0 +1,13 @@ +## hide/remove request headers +{%- set req_hdr_list = j2cfg.grpc_remove_request_headers or j2cfg.remove_request_headers or [] -%} +{%- set req_hdr_list = req_hdr_list | any_to_str_list | uniq_str_list -%} +{%- for h in req_hdr_list %} +grpc_set_header {{ h }} ""; +{%- endfor %} + +## hide response headers +{%- set resp_hdr_list = j2cfg.grpc_remove_response_headers or j2cfg.remove_response_headers or [] -%} +{%- set resp_hdr_list = resp_hdr_list | any_to_str_list | uniq_str_list -%} +{%- for h in resp_hdr_list %} +grpc_hide_header {{ h }}; +{%- endfor %} diff --git a/angie/snip.dist/gzip/buffers.conf b/angie/conf.dist/gzip/buffers.conf similarity index 100% rename from angie/snip.dist/gzip/buffers.conf rename to angie/conf.dist/gzip/buffers.conf diff --git a/angie/snip.dist/gzip/proxied.conf b/angie/conf.dist/gzip/proxied.conf similarity index 100% rename from angie/snip.dist/gzip/proxied.conf rename to angie/conf.dist/gzip/proxied.conf diff --git a/angie/conf.dist/gzip/types.conf.j2 b/angie/conf.dist/gzip/types.conf.j2 new file mode 100644 index 0000000..5897470 --- /dev/null +++ b/angie/conf.dist/gzip/types.conf.j2 @@ -0,0 +1,9 @@ +{%- set mime_types = j2cfg.gzip_compress_types or j2cfg.compress_types or [] -%} +{%- set mime_types = mime_types | any_to_str_list | uniq_str_list -%} +{%- if mime_types -%} +gzip_types +{%- for t in mime_types %} + {{ t }} +{%- endfor %} +; +{%- endif -%} \ No newline at end of file diff --git a/angie/snip.dist/gzip/vary.conf b/angie/conf.dist/gzip/vary.conf similarity index 100% rename from angie/snip.dist/gzip/vary.conf rename to angie/conf.dist/gzip/vary.conf diff --git a/angie/snip.dist/http-brotli-static.conf b/angie/conf.dist/http-brotli-static.conf similarity index 100% rename from angie/snip.dist/http-brotli-static.conf rename to angie/conf.dist/http-brotli-static.conf diff --git a/angie/conf.dist/http-brotli.conf b/angie/conf.dist/http-brotli.conf new file mode 100644 index 0000000..f31f7ed --- /dev/null +++ b/angie/conf.dist/http-brotli.conf @@ -0,0 +1,2 @@ +include conf.d/brotli/*.conf; +brotli on; \ No newline at end of file diff --git a/angie/conf.dist/http-fastcgi.conf b/angie/conf.dist/http-fastcgi.conf new file mode 100644 index 0000000..a286a45 --- /dev/null +++ b/angie/conf.dist/http-fastcgi.conf @@ -0,0 +1 @@ +include conf.d/fastcgi/*.conf; \ No newline at end of file diff --git a/angie/conf.dist/http-grpc.conf b/angie/conf.dist/http-grpc.conf new file mode 100644 index 0000000..d6c368f --- /dev/null +++ b/angie/conf.dist/http-grpc.conf @@ -0,0 +1,4 @@ +## this should be enabled explicitly to avoid config mess +# include conf.d/http-v2.conf; + +include conf.d/grpc/*.conf; \ No newline at end of file diff --git a/angie/conf.dist/http-gunzip.conf b/angie/conf.dist/http-gunzip.conf new file mode 100644 index 0000000..ca799e2 --- /dev/null +++ b/angie/conf.dist/http-gunzip.conf @@ -0,0 +1,2 @@ +gunzip_buffers 16 16k; +gunzip on; \ No newline at end of file diff --git a/angie/snip.dist/http-gzip-static.conf b/angie/conf.dist/http-gzip-static.conf similarity index 100% rename from angie/snip.dist/http-gzip-static.conf rename to angie/conf.dist/http-gzip-static.conf diff --git a/angie/conf.dist/http-gzip.conf b/angie/conf.dist/http-gzip.conf new file mode 100644 index 0000000..0ebfbfa --- /dev/null +++ b/angie/conf.dist/http-gzip.conf @@ -0,0 +1,2 @@ +include conf.d/gzip/*.conf; +gzip on; \ No newline at end of file diff --git a/angie/conf.dist/http-max-ranges.conf.in b/angie/conf.dist/http-max-ranges.conf.in deleted file mode 100644 index 91658f0..0000000 --- a/angie/conf.dist/http-max-ranges.conf.in +++ /dev/null @@ -1 +0,0 @@ -max_ranges ${NGX_HTTP_MAX_RANGES}; \ No newline at end of file diff --git a/angie/conf.dist/http-modsecurity.conf b/angie/conf.dist/http-modsecurity.conf new file mode 100644 index 0000000..0f1725b --- /dev/null +++ b/angie/conf.dist/http-modsecurity.conf @@ -0,0 +1,4 @@ +modsecurity_rules_file /etc/angie/modsecurity.d/rules.conf; + +## NOT enabling ModSecurity by default! +# modsecurity on; \ No newline at end of file diff --git a/angie/conf.dist/http-njs.conf b/angie/conf.dist/http-njs.conf new file mode 100644 index 0000000..cbed30d --- /dev/null +++ b/angie/conf.dist/http-njs.conf @@ -0,0 +1 @@ +js_path /etc/angie/site.d; \ No newline at end of file diff --git a/angie/conf.dist/http-perl.conf b/angie/conf.dist/http-perl.conf new file mode 100644 index 0000000..b3317bb --- /dev/null +++ b/angie/conf.dist/http-perl.conf @@ -0,0 +1 @@ +perl_modules /etc/angie/site.d; \ No newline at end of file diff --git a/angie/conf.dist/http-response-headers.conf.j2 b/angie/conf.dist/http-response-headers.conf.j2 new file mode 100644 index 0000000..645a02c --- /dev/null +++ b/angie/conf.dist/http-response-headers.conf.j2 @@ -0,0 +1,6 @@ +## add response headers +{%- set resp_hdr_list = ( j2cfg.add_response_headers or {} ) -%} +{%- for h, v in resp_hdr_list.items() %} +{#- TODO: precise quotation #} +add_header {{ h }} {{ v.__repr__() }}; +{%- endfor %} diff --git a/angie/conf.dist/http-scgi.conf b/angie/conf.dist/http-scgi.conf new file mode 100644 index 0000000..436efe8 --- /dev/null +++ b/angie/conf.dist/http-scgi.conf @@ -0,0 +1 @@ +include conf.d/scgi/*.conf; \ No newline at end of file diff --git a/angie/conf.dist/http-uwsgi.conf b/angie/conf.dist/http-uwsgi.conf new file mode 100644 index 0000000..a9567c2 --- /dev/null +++ b/angie/conf.dist/http-uwsgi.conf @@ -0,0 +1 @@ +include conf.d/uwsgi/*.conf; \ No newline at end of file diff --git a/angie/conf.dist/http-v2.conf b/angie/conf.dist/http-v2.conf new file mode 100644 index 0000000..cfba10a --- /dev/null +++ b/angie/conf.dist/http-v2.conf @@ -0,0 +1,2 @@ +http2_chunk_size 16k; +http2 on; \ No newline at end of file diff --git a/angie/snip.dist/http-zstd-static.conf b/angie/conf.dist/http-zstd-static.conf similarity index 100% rename from angie/snip.dist/http-zstd-static.conf rename to angie/conf.dist/http-zstd-static.conf diff --git a/angie/conf.dist/http-zstd.conf b/angie/conf.dist/http-zstd.conf new file mode 100644 index 0000000..34116a1 --- /dev/null +++ b/angie/conf.dist/http-zstd.conf @@ -0,0 +1,2 @@ +include conf.d/zstd/*.conf; +zstd on; \ No newline at end of file diff --git a/angie/conf.dist/proxy/headers.conf.j2 b/angie/conf.dist/proxy/headers.conf.j2 new file mode 100644 index 0000000..c2d1b7e --- /dev/null +++ b/angie/conf.dist/proxy/headers.conf.j2 @@ -0,0 +1,13 @@ +## hide/remove request headers +{%- set req_hdr_list = j2cfg.proxy_remove_request_headers or j2cfg.remove_request_headers or [] -%} +{%- set req_hdr_list = req_hdr_list | any_to_str_list | uniq_str_list -%} +{%- for h in req_hdr_list %} +proxy_set_header {{ h }} ""; +{%- endfor %} + +## hide response headers +{%- set resp_hdr_list = j2cfg.proxy_remove_response_headers or j2cfg.remove_response_headers or [] -%} +{%- set resp_hdr_list = resp_hdr_list | any_to_str_list | uniq_str_list -%} +{%- for h in resp_hdr_list %} +proxy_hide_header {{ h }}; +{%- endfor %} diff --git a/angie/conf.dist/scgi/buffers.conf b/angie/conf.dist/scgi/buffers.conf new file mode 100644 index 0000000..9871886 --- /dev/null +++ b/angie/conf.dist/scgi/buffers.conf @@ -0,0 +1,4 @@ +scgi_buffers 16 16k; +scgi_buffer_size 16k; +scgi_busy_buffers_size 32k; +scgi_temp_file_write_size 32k; \ No newline at end of file diff --git a/angie/conf.dist/scgi/headers.conf.j2 b/angie/conf.dist/scgi/headers.conf.j2 new file mode 100644 index 0000000..8535057 --- /dev/null +++ b/angie/conf.dist/scgi/headers.conf.j2 @@ -0,0 +1,13 @@ +## hide/remove request headers +{%- set req_hdr_list = j2cfg.scgi_remove_request_headers or j2cfg.remove_request_headers or [] -%} +{%- set req_hdr_list = req_hdr_list | any_to_str_list | as_cgi_header -%} +{%- for h in req_hdr_list %} +scgi_param {{ h }} ""; +{%- endfor %} + +## hide response headers +{%- set resp_hdr_list = j2cfg.scgi_remove_response_headers or j2cfg.remove_response_headers or [] -%} +{%- set resp_hdr_list = resp_hdr_list | any_to_str_list | uniq_str_list -%} +{%- for h in resp_hdr_list %} +scgi_hide_header {{ h }}; +{%- endfor %} diff --git a/angie/conf.dist/scgi/param.conf b/angie/conf.dist/scgi/param.conf new file mode 100644 index 0000000..2e0c45b --- /dev/null +++ b/angie/conf.dist/scgi/param.conf @@ -0,0 +1,7 @@ +include snip.d/scgi_params; + +scgi_param PATH_INFO $path_info; + +scgi_param AUTH_USER $remote_user; +scgi_param REMOTE_USER $remote_user; +scgi_param HTTP_HOST $host; \ No newline at end of file diff --git a/angie/conf.dist/uwsgi/buffers.conf b/angie/conf.dist/uwsgi/buffers.conf new file mode 100644 index 0000000..2ac16d7 --- /dev/null +++ b/angie/conf.dist/uwsgi/buffers.conf @@ -0,0 +1,4 @@ +uwsgi_buffers 16 16k; +uwsgi_buffer_size 16k; +uwsgi_busy_buffers_size 32k; +uwsgi_temp_file_write_size 32k; \ No newline at end of file diff --git a/angie/conf.dist/uwsgi/headers.conf.j2 b/angie/conf.dist/uwsgi/headers.conf.j2 new file mode 100644 index 0000000..e727e97 --- /dev/null +++ b/angie/conf.dist/uwsgi/headers.conf.j2 @@ -0,0 +1,13 @@ +## hide/remove request headers +{%- set req_hdr_list = j2cfg.uwsgi_remove_request_headers or j2cfg.remove_request_headers or [] -%} +{%- set req_hdr_list = req_hdr_list | any_to_str_list | as_cgi_header -%} +{%- for h in req_hdr_list %} +uwsgi_param {{ h }} ""; +{%- endfor %} + +## hide response headers +{%- set resp_hdr_list = j2cfg.uwsgi_remove_response_headers or j2cfg.remove_response_headers or [] -%} +{%- set resp_hdr_list = resp_hdr_list | any_to_str_list | uniq_str_list -%} +{%- for h in resp_hdr_list %} +uwsgi_hide_header {{ h }}; +{%- endfor %} diff --git a/angie/conf.dist/uwsgi/param.conf b/angie/conf.dist/uwsgi/param.conf new file mode 100644 index 0000000..7ac1edc --- /dev/null +++ b/angie/conf.dist/uwsgi/param.conf @@ -0,0 +1,7 @@ +include snip.d/uwsgi_params; + +uwsgi_param PATH_INFO $path_info; + +uwsgi_param AUTH_USER $remote_user; +uwsgi_param REMOTE_USER $remote_user; +uwsgi_param HTTP_HOST $host; \ No newline at end of file diff --git a/angie/snip.dist/zstd/buffers.conf b/angie/conf.dist/zstd/buffers.conf similarity index 100% rename from angie/snip.dist/zstd/buffers.conf rename to angie/conf.dist/zstd/buffers.conf diff --git a/angie/conf.dist/zstd/types.conf.j2 b/angie/conf.dist/zstd/types.conf.j2 new file mode 100644 index 0000000..37fb51a --- /dev/null +++ b/angie/conf.dist/zstd/types.conf.j2 @@ -0,0 +1,9 @@ +{%- set mime_types = j2cfg.zstd_compress_types or j2cfg.compress_types or [] -%} +{%- set mime_types = mime_types | any_to_str_list | uniq_str_list -%} +{%- if mime_types -%} +zstd_types +{%- for t in mime_types %} + {{ t }} +{%- endfor %} +; +{%- endif -%} \ No newline at end of file diff --git a/angie/ctx-http.conf b/angie/ctx-http.conf index 5099ae4..8547637 100644 --- a/angie/ctx-http.conf +++ b/angie/ctx-http.conf @@ -1,5 +1,5 @@ http { - include conf.d/http-*.conf; + include autoconf.d/http-*.conf; include load/http-*.conf; include site.d/http-*.conf; } \ No newline at end of file diff --git a/angie/ctx-mail.conf b/angie/ctx-mail.conf index 6fce075..bd21fcb 100644 --- a/angie/ctx-mail.conf +++ b/angie/ctx-mail.conf @@ -1,5 +1,5 @@ mail { - include conf.d/mail-*.conf; + include autoconf.d/mail-*.conf; include load/mail-*.conf; include site.d/mail-*.conf; } \ No newline at end of file diff --git a/angie/ctx-stream.conf b/angie/ctx-stream.conf index d45bdc8..176574d 100644 --- a/angie/ctx-stream.conf +++ b/angie/ctx-stream.conf @@ -1,5 +1,5 @@ stream { - include conf.d/stream-*.conf; + include autoconf.d/stream-*.conf; include load/stream-*.conf; include site.d/stream-*.conf; } \ No newline at end of file diff --git a/angie/j2cfg.dist/add-response-headers.yml b/angie/j2cfg.dist/add-response-headers.yml new file mode 100644 index 0000000..7ad205a --- /dev/null +++ b/angie/j2cfg.dist/add-response-headers.yml @@ -0,0 +1,11 @@ +add_response_headers: + Access-Control-Allow-Origin: "*" + Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept, Authorization" + Access-Control-Allow-Methods: "GET, HEAD, POST, PUT, DELETE, OPTIONS" + Content-Security-Policy: "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline' 'unsafe-eval' ; frame-ancestors 'self';" + Permissions-Policy: "microphone=(), camera=(), geolocation=(), interest-cohort=()" + Referrer-Policy: "no-referrer-when-downgrade" + Strict-Transport-Security: "max-age=31536000; includeSubDomains; preload" + X-Content-Type-Options: "nosniff" + X-Frame-Options: "SAMEORIGIN" + X-XSS-Protection: "1; mode=block" diff --git a/angie/j2cfg.dist/core-worker-env.txt.j2 b/angie/j2cfg.dist/core-worker-env.txt.j2 index 9381896..3564d09 100644 --- a/angie/j2cfg.dist/core-worker-env.txt.j2 +++ b/angie/j2cfg.dist/core-worker-env.txt.j2 @@ -1,10 +1,9 @@ {#- prologue -#} -{%- set s_vars = ['MALLOC_ARENA_MAX', 'GLIBC_TUNABLES', 'MALLOC_CONF'] -%} {%- set c_env = ( j2cfg.core_worker_env or [] ) | any_to_env_dict -%} {%- set c_vars = c_env | dict_keys -%} -{%- set c_vars_preserve = c_env | dict_empty_keys -%} -{%- set vars_preserve = ( c_vars_preserve + ( s_vars | list_diff(c_vars) )) | sort -%} +{%- set c_vars_passthrough = c_env | dict_empty_keys -%} +{%- set vars_passthrough = ((env_passthrough | list_diff(c_vars)) + c_vars_passthrough) | uniq | list_intersect(env | dict_keys) -%} {#- main part -#} -{%- for k in vars_preserve -%} +{%- for k in vars_passthrough -%} {{ k }} {% endfor -%} diff --git a/angie/j2cfg.dist/remove-request-headers.yml b/angie/j2cfg.dist/remove-request-headers.yml new file mode 100644 index 0000000..e2f8aef --- /dev/null +++ b/angie/j2cfg.dist/remove-request-headers.yml @@ -0,0 +1,3 @@ +remove_request_headers: + ## do not pass Accept-Encoding to backend +- Accept-Encoding \ No newline at end of file diff --git a/angie/j2cfg.dist/remove-response-headers.yml b/angie/j2cfg.dist/remove-response-headers.yml new file mode 100644 index 0000000..9c43c15 --- /dev/null +++ b/angie/j2cfg.dist/remove-response-headers.yml @@ -0,0 +1,12 @@ +remove_response_headers: +- Access-Control-Allow-Headers +- Access-Control-Allow-Methods +- Access-Control-Allow-Origin +- Content-Security-Policy +- Permissions-Policy +- Referrer-Policy +- Strict-Transport-Security +- Vary +- X-Content-Type-Options +- X-Frame-Options +- X-XSS-Protection \ No newline at end of file diff --git a/angie/modsecurity.dist/rules.conf b/angie/modsecurity.dist/rules.conf new file mode 100644 index 0000000..f6892b2 --- /dev/null +++ b/angie/modsecurity.dist/rules.conf @@ -0,0 +1,33 @@ +Include modsecurity.conf + +# To enable the OWASP CRS, please perform the following steps: +# +# 1. Checkout Core Rule Set from GitHub and create config files as shown below: +# +# version='v4.5.0' +# uri="https://github.com/coreruleset/coreruleset/archive/refs/tags/${version}.tar.gz" +# dst_dir='/etc/angie/modsecurity/coreruleset' +# w=$(mktemp -d) ; : "${w:?}" +# cd "$w/" +# tarball="coreruleset.tar.gz" +# /usr/lib/apt/apt-helper download-file "${uri}" "${tarball}" +# mkdir coreruleset +# tar -C ./coreruleset --strip-components=1 -xf "${tarball}" +# rm -f "${tarball}" ; unset tarball +# for p in \ +# crs-setup.conf \ +# rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf \ +# rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf \ +# ; do +# src="coreruleset/$p.example" +# dst="${dst_dir}/$p" +# [ -f "${src}" ] || continue +# [ -d "${dst%/*}" ] || mkdir -p "${dst%/*}" +# cp -nv "${src}" "${dst}" +# done +# rm -rf "${w:?}/" ; unset w +# +# 2. Uncomment both 'Include' directives below + +#Include coreruleset/crs-setup.conf +#Include coreruleset/rules/*.conf \ No newline at end of file diff --git a/angie/snip.dist/brotli/gzip.conf b/angie/snip.dist/brotli/gzip.conf deleted file mode 100644 index 76f9958..0000000 --- a/angie/snip.dist/brotli/gzip.conf +++ /dev/null @@ -1 +0,0 @@ -include snip.d/gzip/vary.conf; \ No newline at end of file diff --git a/angie/snip.dist/brotli/types.conf.j2 b/angie/snip.dist/brotli/types.conf.j2 deleted file mode 100644 index bf09900..0000000 --- a/angie/snip.dist/brotli/types.conf.j2 +++ /dev/null @@ -1,8 +0,0 @@ -{%- set mime_types = ( j2cfg.compress_types or [] )|any_to_str_list|uniq_str_list -%} -{%- if mime_types %} -brotli_types -{%- for t in mime_types %} - {{ t }} -{%- endfor %} -; -{%- endif %} \ No newline at end of file diff --git a/angie/snip.dist/deny-dotfiles b/angie/snip.dist/deny-dotfiles new file mode 100644 index 0000000..5f11f8d --- /dev/null +++ b/angie/snip.dist/deny-dotfiles @@ -0,0 +1,3 @@ +location ~ /\. { + include snip.d/internal-area; +} \ No newline at end of file diff --git a/angie/snip.dist/disable-compression.j2 b/angie/snip.dist/disable-compression.j2 new file mode 100644 index 0000000..599fdde --- /dev/null +++ b/angie/snip.dist/disable-compression.j2 @@ -0,0 +1,8 @@ +{#- safe to specify all the time -#} +gzip off; +{%- set modules = ( env.NGX_HTTP_MODULES or '' ) | str_split_to_list -%} +{%- for ext_comp in ['brotli', 'zstd'] %} +{%- if ext_comp in modules %} +{{ ext_comp }} off; +{%- endif %} +{%- endfor %} \ No newline at end of file diff --git a/angie/snip.dist/empty-favicon b/angie/snip.dist/empty-favicon new file mode 100644 index 0000000..bc796c3 --- /dev/null +++ b/angie/snip.dist/empty-favicon @@ -0,0 +1,4 @@ +location = /favicon.ico { + empty_gif; + expires 1d; +} \ No newline at end of file diff --git a/angie/snip.dist/fastcgi-location b/angie/snip.dist/fastcgi-location new file mode 100644 index 0000000..9e99f1e --- /dev/null +++ b/angie/snip.dist/fastcgi-location @@ -0,0 +1,5 @@ +try_files $fastcgi_script_name =444; + +## bypass the fact that try_files resets $fastcgi_path_info +## see: https://trac.nginx.org/nginx/ticket/321 +set $path_info $fastcgi_path_info; \ No newline at end of file diff --git a/angie/snip.dist/gzip/types.conf.j2 b/angie/snip.dist/gzip/types.conf.j2 deleted file mode 100644 index 34f084d..0000000 --- a/angie/snip.dist/gzip/types.conf.j2 +++ /dev/null @@ -1,8 +0,0 @@ -{%- set mime_types = ( j2cfg.compress_types or [] )|any_to_str_list|uniq_str_list -%} -{%- if mime_types %} -gzip_types -{%- for t in mime_types %} - {{ t }} -{%- endfor %} -; -{%- endif %} \ No newline at end of file diff --git a/angie/snip.dist/http-brotli.conf b/angie/snip.dist/http-brotli.conf deleted file mode 100644 index e06238a..0000000 --- a/angie/snip.dist/http-brotli.conf +++ /dev/null @@ -1,2 +0,0 @@ -include snip.d/brotli/*.conf; -brotli on; \ No newline at end of file diff --git a/angie/snip.dist/http-gunzip.conf b/angie/snip.dist/http-gunzip.conf deleted file mode 100644 index 16c2020..0000000 --- a/angie/snip.dist/http-gunzip.conf +++ /dev/null @@ -1,2 +0,0 @@ -include snip.d/http-gunzip.modconf; -gunzip on; \ No newline at end of file diff --git a/angie/snip.dist/http-gunzip.modconf b/angie/snip.dist/http-gunzip.modconf deleted file mode 100644 index 19dd7da..0000000 --- a/angie/snip.dist/http-gunzip.modconf +++ /dev/null @@ -1 +0,0 @@ -gunzip_buffers 16 16k; \ No newline at end of file diff --git a/angie/snip.dist/http-gzip.conf b/angie/snip.dist/http-gzip.conf deleted file mode 100644 index ffd80c6..0000000 --- a/angie/snip.dist/http-gzip.conf +++ /dev/null @@ -1,2 +0,0 @@ -include snip.d/gzip/*.conf; -gzip on; \ No newline at end of file diff --git a/angie/snip.dist/http-zstd.conf b/angie/snip.dist/http-zstd.conf deleted file mode 100644 index 6e8540d..0000000 --- a/angie/snip.dist/http-zstd.conf +++ /dev/null @@ -1,2 +0,0 @@ -include snip.d/zstd/*.conf; -zstd on; \ No newline at end of file diff --git a/angie/snip.dist/internal-area b/angie/snip.dist/internal-area new file mode 100644 index 0000000..08bc53d --- /dev/null +++ b/angie/snip.dist/internal-area @@ -0,0 +1,5 @@ +## always sourced by snip.d/deny-dotfiles + +access_log off; +log_not_found off; +internal; \ No newline at end of file diff --git a/angie/snip.dist/zstd/gzip.conf b/angie/snip.dist/zstd/gzip.conf deleted file mode 100644 index 76f9958..0000000 --- a/angie/snip.dist/zstd/gzip.conf +++ /dev/null @@ -1 +0,0 @@ -include snip.d/gzip/vary.conf; \ No newline at end of file diff --git a/angie/snip.dist/zstd/types.conf.j2 b/angie/snip.dist/zstd/types.conf.j2 deleted file mode 100644 index 32934aa..0000000 --- a/angie/snip.dist/zstd/types.conf.j2 +++ /dev/null @@ -1,8 +0,0 @@ -{%- set mime_types = ( j2cfg.compress_types or [] )|any_to_str_list|uniq_str_list -%} -{%- if mime_types %} -zstd_types -{%- for t in mime_types %} - {{ t }} -{%- endfor %} -; -{%- endif %} \ No newline at end of file diff --git a/image-entry.d/00-common.envsh b/image-entry.d/00-common.envsh index 7c2dc72..9449983 100644 --- a/image-entry.d/00-common.envsh +++ b/image-entry.d/00-common.envsh @@ -82,7 +82,7 @@ untemplate_path() { "${volume_root}"/* | /etc/angie/run/* ) strip_suffix "$1" "$2" ;; - /etc/angie/conf.d/* | /etc/angie/j2cfg.d/* | /etc/angie/mod.d/* | /etc/angie/modules.d/* | /etc/angie/site.d/* | /etc/angie/snip.d/* ) + /etc/angie/autoconf.d/* | /etc/angie/conf.d/* | /etc/angie/j2cfg.d/* | /etc/angie/mod.d/* | /etc/angie/modules.d/* | /etc/angie/site.d/* | /etc/angie/snip.d/* ) strip_suffix "$1" "$2" ;; /etc/angie/static.d/* ) @@ -212,6 +212,10 @@ remap_path() { [ -n "$1" ] || return case "$1" in + ## autoconf + /etc/angie/autoconf.dist/* ) echo "${2:-/etc/angie/autoconf.d}${1#/etc/angie/autoconf.dist}" ;; + /etc/angie/autoconf/* ) echo "${2:-/etc/angie/autoconf.d}${1#/etc/angie/autoconf}" ;; + /angie/autoconf/* ) echo "${2:-/etc/angie/autoconf.d}${1#/angie/autoconf}" ;; ## conf /etc/angie/conf.dist/* ) echo "${2:-/etc/angie/conf.d}${1#/etc/angie/conf.dist}" ;; /etc/angie/conf/* ) echo "${2:-/etc/angie/conf.d}${1#/etc/angie/conf}" ;; @@ -277,6 +281,14 @@ is_builtin_module() { grep -Fxq -e "$2" "/etc/angie/builtin.$1" || return 1 } +normalize_list() { + [ -n "$1" ] || return 0 + + printf '%s' "$1" \ + | tr -s '[:space:]' ' ' \ + | sed -zE 's/^ //;s/ $//' +} + sort_dedup_list() { [ -n "$1" ] || return 0 diff --git a/image-entry.d/01-defaults.envsh b/image-entry.d/01-defaults.envsh index 1daecf4..e62c8f5 100755 --- a/image-entry.d/01-defaults.envsh +++ b/image-entry.d/01-defaults.envsh @@ -19,7 +19,7 @@ if [ "${NGX_HTTP}${NGX_MAIL}${NGX_STREAM}" = '000' ] ; then fi unset default_dirs_merge default_dirs_link -default_dirs_merge='conf j2cfg mod modules site snip' +default_dirs_merge='autoconf conf j2cfg mod modules site snip' default_dirs_link='' if [ "${NGX_PROCESS_STATIC}" = 1 ] ; then diff --git a/image-entry.d/02-detect-nonroot.envsh b/image-entry.d/02-nonroot.envsh similarity index 100% rename from image-entry.d/02-detect-nonroot.envsh rename to image-entry.d/02-nonroot.envsh diff --git a/image-entry.d/03-detect-local-override.envsh b/image-entry.d/03-local-override.envsh similarity index 100% rename from image-entry.d/03-detect-local-override.envsh rename to image-entry.d/03-local-override.envsh diff --git a/image-entry.d/04-detect-local-ip-addresses.envsh b/image-entry.d/04-local-ip-addresses.envsh similarity index 100% rename from image-entry.d/04-detect-local-ip-addresses.envsh rename to image-entry.d/04-local-ip-addresses.envsh diff --git a/image-entry.d/11-core-modules.envsh b/image-entry.d/11-core-modules.envsh index 4edfda1..f10ace9 100755 --- a/image-entry.d/11-core-modules.envsh +++ b/image-entry.d/11-core-modules.envsh @@ -9,8 +9,15 @@ unset i for i in ${NGX_CORE_MODULES:-} ; do [ -n "$i" ] || continue + case "$i" in + */* | *\** | *\?* ) + log_always "module '$i' is not legal, skipping" + continue + ;; + esac + if is_builtin_module core "$i" ; then - log "$i is builtin module, moving to confload" + log "$i is builtin module, moving to NGX_CORE_CONFLOAD" core_confload="${core_confload} $i" continue fi diff --git a/image-entry.d/13-core-worker-defaults.envsh b/image-entry.d/13-core-worker-defaults.envsh deleted file mode 100755 index a30ecbe..0000000 --- a/image-entry.d/13-core-worker-defaults.envsh +++ /dev/null @@ -1,146 +0,0 @@ -#!/bin/sh - -unset _NGX_WORKER_PROCESSES _NGX_WORKER_PRIORITY _NGX_WORKER_RLIMIT_NOFILE _NGX_WORKER_CONNECTIONS -## here should be SANE defaults (!) -_NGX_WORKER_PROCESSES=2 -_NGX_WORKER_PRIORITY=0 -_NGX_WORKER_RLIMIT_NOFILE=16384 -_NGX_WORKER_CONNECTIONS=4096 - -[ -n "${NGX_WORKER_PROCESSES:-}" ] || NGX_WORKER_PROCESSES=${_NGX_WORKER_PROCESSES} -case "${NGX_WORKER_PROCESSES}" in -"${_NGX_WORKER_PROCESSES}" ) ;; -## allow values within [1;999] -[1-9] | [1-9][0-9] | [1-9][0-9][0-9] ) ;; -[Aa][Uu][Tt][Oo] ) - ## adjust - NGX_WORKER_PROCESSES=auto - log_always "NGX_WORKER_PROCESSES: \"auto\" isn't supported by container yet" - log_always "offloading decision to Angie (this could be a problem!)" -;; -0 ) - log_always "NGX_WORKER_PROCESSES: \"0\" isn't supported by container yet" - log_always "setting NGX_WORKER_PROCESSES=${_NGX_WORKER_PROCESSES}" - NGX_WORKER_PROCESSES=${_NGX_WORKER_PROCESSES} -;; -* ) - log_always "NGX_WORKER_PROCESSES: unrecognized value: ${NGX_WORKER_PROCESSES}" - log_always "setting NGX_WORKER_PROCESSES=${_NGX_WORKER_PROCESSES}" - NGX_WORKER_PROCESSES=${_NGX_WORKER_PROCESSES} -;; -esac - -[ -n "${NGX_WORKER_PRIORITY:-}" ] || NGX_WORKER_PRIORITY=${_NGX_WORKER_PRIORITY} -case "${NGX_WORKER_PRIORITY}" in -"${_NGX_WORKER_PRIORITY}" ) ;; --[1-9] | -1[0-9] | -20 ) ;; - [0-9] | 1[0-9] | 20 ) ;; - -0 ) - log_always "NGX_WORKER_PRIORITY: likely an error: '-0'" - log_always "adjusting NGX_WORKER_PRIORITY=0" - NGX_WORKER_PRIORITY=0 -;; -* ) - log_always "NGX_WORKER_PRIORITY: unrecognized value: ${NGX_WORKER_PRIORITY}" - log_always "setting NGX_WORKER_PRIORITY=${_NGX_WORKER_PRIORITY}" - NGX_WORKER_PRIORITY=${_NGX_WORKER_PRIORITY} -;; -esac - -[ -n "${NGX_WORKER_RLIMIT_NOFILE:-}" ] || NGX_WORKER_RLIMIT_NOFILE=${_NGX_WORKER_RLIMIT_NOFILE} -case "${NGX_WORKER_RLIMIT_NOFILE}" in -"${_NGX_WORKER_RLIMIT_NOFILE}" ) ;; -[0-9] | [1-9][0-9] ) - log_always "NGX_WORKER_RLIMIT_NOFILE: too low: ${NGX_WORKER_RLIMIT_NOFILE}" - log_always "setting NGX_WORKER_RLIMIT_NOFILE=${_NGX_WORKER_RLIMIT_NOFILE}" - NGX_WORKER_RLIMIT_NOFILE=${_NGX_WORKER_RLIMIT_NOFILE} -;; -## allow values within [100;9999999] -[1-9][0-9][0-9] ) ;; -[1-9][0-9][0-9][0-9] ) ;; -[1-9][0-9][0-9][0-9][0-9] ) ;; -[1-9][0-9][0-9][0-9][0-9][0-9] ) ;; -[1-9][0-9][0-9][0-9][0-9][0-9][0-9] ) ;; -* ) - log_always "NGX_WORKER_RLIMIT_NOFILE: unrecognized value: ${NGX_WORKER_RLIMIT_NOFILE}" - log_always "setting NGX_WORKER_RLIMIT_NOFILE=${_NGX_WORKER_RLIMIT_NOFILE}" - NGX_WORKER_RLIMIT_NOFILE=${_NGX_WORKER_RLIMIT_NOFILE} -;; -esac - -[ -n "${NGX_WORKER_CONNECTIONS:-}" ] || NGX_WORKER_CONNECTIONS=${_NGX_WORKER_CONNECTIONS} -case "${NGX_WORKER_CONNECTIONS}" in -"${_NGX_WORKER_CONNECTIONS}" ) ;; -[0-9] | [1-9][0-9] ) - log_always "NGX_WORKER_CONNECTIONS: too low: ${NGX_WORKER_CONNECTIONS}" - log_always "setting NGX_WORKER_CONNECTIONS=${_NGX_WORKER_CONNECTIONS}" - NGX_WORKER_CONNECTIONS=${_NGX_WORKER_CONNECTIONS} -;; -## allow values within [100;9999999] -[1-9][0-9][0-9] ) ;; -[1-9][0-9][0-9][0-9] ) ;; -[1-9][0-9][0-9][0-9][0-9] ) ;; -[1-9][0-9][0-9][0-9][0-9][0-9] ) ;; -[1-9][0-9][0-9][0-9][0-9][0-9][0-9] ) ;; -* ) - log_always "NGX_WORKER_CONNECTIONS: unrecognized value: ${NGX_WORKER_CONNECTIONS}" - log_always "setting NGX_WORKER_CONNECTIONS=${_NGX_WORKER_CONNECTIONS}" - NGX_WORKER_CONNECTIONS=${_NGX_WORKER_CONNECTIONS} -;; -esac - -nofile_soft=$(ulimit -Sn) -nofile_hard=$(ulimit -Hn) - -if [ "${nofile_hard}" = unlimited ] ; then - ## minor hack (if applicable) :) - nofile_hard=$((NGX_WORKER_RLIMIT_NOFILE * 2)) -fi - -nofile_ok=0 -while : ; do - [ ${nofile_hard} -ge ${NGX_WORKER_RLIMIT_NOFILE} ] || break - [ ${nofile_soft} -ge ${NGX_WORKER_RLIMIT_NOFILE} ] || break - - nofile_ok=1 -break ; done - -if [ ${nofile_ok} = 0 ] ; then - log_always "adjusting 'nofile' limits" - - log_always "Limits before:" - sed -En '1p;/open files/p' < /proc/$$/limits >&2 - - if [ ${nofile_hard} -lt ${NGX_WORKER_RLIMIT_NOFILE} ] ; then - ulimit -Hn "${NGX_WORKER_RLIMIT_NOFILE}" - nofile_hard=$(ulimit -Hn) - fi - if [ ${nofile_hard} -lt ${NGX_WORKER_RLIMIT_NOFILE} ] ; then - log_always "lowering NGX_WORKER_RLIMIT_NOFILE to ${nofile_hard} due to hard limit" - NGX_WORKER_RLIMIT_NOFILE=${nofile_hard} - fi - - if [ ${nofile_soft} -lt ${NGX_WORKER_RLIMIT_NOFILE} ] ; then - ulimit -Sn "${NGX_WORKER_RLIMIT_NOFILE}" - fi - - log_always "Limits after:" - sed -En '1p;/open files/p' < /proc/$$/limits >&2 -fi -unset nofile_soft nofile_hard nofile_ok - -export NGX_WORKER_PROCESSES NGX_WORKER_PRIORITY NGX_WORKER_RLIMIT_NOFILE NGX_WORKER_CONNECTIONS - -unset _NGX_WORKER_PROCESSES _NGX_WORKER_PRIORITY _NGX_WORKER_RLIMIT_NOFILE _NGX_WORKER_CONNECTIONS - -if [ ${NGX_WORKER_RLIMIT_NOFILE} -lt ${NGX_WORKER_CONNECTIONS} ] ; then - log_always "WARNING: NGX_WORKER_RLIMIT_NOFILE is less than NGX_WORKER_CONNECTIONS (${NGX_WORKER_RLIMIT_NOFILE} < ${NGX_WORKER_CONNECTIONS})" -else - ratio=$(mawk -v "a=${NGX_WORKER_RLIMIT_NOFILE}" -v "b=${NGX_WORKER_CONNECTIONS}" 'BEGIN{print a/b;exit;}' &2 + + if [ ${nofile_hard} -lt ${NGX_WORKER_RLIMIT_NOFILE} ] ; then + ulimit -Hn "${NGX_WORKER_RLIMIT_NOFILE}" + nofile_hard=$(ulimit -Hn) + fi + if [ ${nofile_hard} -lt ${NGX_WORKER_RLIMIT_NOFILE} ] ; then + log_always "lowering NGX_WORKER_RLIMIT_NOFILE to ${nofile_hard} due to hard limit" + NGX_WORKER_RLIMIT_NOFILE=${nofile_hard} + fi + + if [ ${nofile_soft} -lt ${NGX_WORKER_RLIMIT_NOFILE} ] ; then + ulimit -Sn "${NGX_WORKER_RLIMIT_NOFILE}" + fi + + log_always "Limits after:" + sed -En '1p;/open files/p' < /proc/$$/limits >&2 + fi + unset nofile_soft nofile_hard nofile_ok + + export NGX_WORKER_RLIMIT_NOFILE +fi + +if [ -z "${NGX_WORKER_RLIMIT_NOFILE:-}" ] ; then + nofile_limit=$(ulimit -Hn) + nofile_kind="'ulimit:nofile'" +else + nofile_limit=${NGX_WORKER_RLIMIT_NOFILE} + nofile_kind='NGX_WORKER_RLIMIT_NOFILE' +fi +if [ ${nofile_limit} -lt ${NGX_WORKER_CONNECTIONS} ] ; then + log_always "WARNING: ${nofile_kind} is less than NGX_WORKER_CONNECTIONS (${nofile_limit} < ${NGX_WORKER_CONNECTIONS})" +else + ratio=$(mawk -v "a=${nofile_limit}" -v "b=${NGX_WORKER_CONNECTIONS}" 'BEGIN{print a/b;exit;}' list: return [str(x)] -def is_re_match(a: (list, set), pattern, flags=0) -> bool: - return any(re.match(pattern, x, flags) for x in a) +def is_re_match(x, pattern, flags=0) -> bool: + if isinstance(x, str): + return bool(re.match(pattern, x, flags)) + if is_sequence(x): + return any(is_re_match(v, pattern, flags) for v in x) + if is_mapping(x): + return any(is_re_match(v, pattern, flags) for v in x.keys()) + return False -def is_re_fullmatch(a: (list, set), pattern, flags=0) -> bool: - return any(re.fullmatch(pattern, x, flags) for x in a) +def is_re_fullmatch(x, pattern, flags=0) -> bool: + if isinstance(x, str): + return bool(re.fullmatch(pattern, x, flags)) + if is_sequence(x): + return any(is_re_fullmatch(v, pattern, flags) for v in x) + if is_mapping(x): + return any(is_re_fullmatch(v, pattern, flags) for v in x.keys()) + return False -def re_match(a: (list, set), pattern, flags=0) -> list: - return [x for x in a if re.match(pattern, x, flags)] +def re_match(x, pattern, flags=0): + if isinstance(x, str): + return re.match(pattern, x, flags) + if is_sequence(x): + return [v for v in x + if re_match(v, pattern, flags)] + if is_mapping(x): + return {k: v for k, v in x.items() + if re_match(k, pattern, flags)} + return None -def re_fullmatch(a: (list, set), pattern, flags=0) -> list: - return [x for x in a if re.fullmatch(pattern, x, flags)] +def re_fullmatch(x, pattern, flags=0): + if isinstance(x, str): + return re.fullmatch(pattern, x, flags) + if is_sequence(x): + return [v for v in x + if re_fullmatch(v, pattern, flags)] + if is_mapping(x): + return {k: v for k, v in x.items() + if re_fullmatch(k, pattern, flags)} + return None -def re_match_negate(a: (list, set), pattern, flags=0) -> list: - return [x for x in a if not re.match(pattern, x, flags)] +def re_match_negate(x, pattern, flags=0): + if isinstance(x, str): + return not bool(re.match(pattern, x, flags)) + if is_sequence(x): + return [v for v in x + if re_match_negate(v, pattern, flags)] + if is_mapping(x): + return {k: v for k, v in x.items() + if re_match_negate(k, pattern, flags)} + return x -def re_fullmatch_negate(a: (list, set), pattern, flags=0) -> list: - return [x for x in a if not re.fullmatch(pattern, x, flags)] +def re_fullmatch_negate(x, pattern, flags=0): + if isinstance(x, str): + return not bool(re.fullmatch(pattern, x, flags)) + if is_sequence(x): + return [v for v in x + if re_fullmatch_negate(v, pattern, flags)] + if is_mapping(x): + return {k: v for k, v in x.items() + if re_fullmatch_negate(k, pattern, flags)} + return x -def re_sub(a: (list, set), pattern, repl, count=0, flags=0) -> list: - return [re.sub(pattern, repl, x, count, flags) for x in a] +def dict_remap_keys(x: dict, key_map) -> dict: + if key_map is None: + return x + all_keys = list(x.keys()) + kmap = { + k: key_map(k) + for k in all_keys + if k != key_map(k) + } + persist_keys = [ + k for k in all_keys + if k not in kmap.keys() and k not in kmap.values() + ] + return { + k: x[k] for k in persist_keys + } | { + k: x[v] for k, v in kmap.items() + } -@jinja2.pass_environment -def sh_like_file_to_list(j2env, file_in: str) -> list: - tpl = j2env.get_template(file_in) - text = pathlib.Path(tpl.filename).read_text(encoding='utf-8') - lines = re.split(r'[\r\n]', text) - return list(itertools.filterfalse( - lambda x: re.match(r'\s*#', x), lines - )) +def re_sub(x, pattern, repl, count=0, flags=0): + if isinstance(x, str): + return re.sub(pattern, repl, x, count, flags) + if is_sequence(x): + return [ + re_sub(v, pattern, repl, count, flags) + for v in x + ] + if is_mapping(x): + return dict_remap_keys( + x, lambda k: + re_sub(k, pattern, repl, count, flags) + ) + return x -def as_cgi_header(s: str) -> str: - return 'HTTP_' + re.sub('[^A-Z0-9]+', '_', s.upper()).strip('_') +def as_cgi_header(x): + if isinstance(x, str): + return 'HTTP_' + re.sub('[^A-Z0-9]+', '_', x.upper()).strip('_') + if is_sequence(x): + return uniq([ + as_cgi_header(v) + for v in x + ]) + if is_mapping(x): + return dict_remap_keys( + x, as_cgi_header + ) + return x def any_to_env_dict(x) -> dict: @@ -156,6 +233,16 @@ def list_intersect(a: (list, set), b: (list, set)) -> list: return list(set(a) & set(b)) +@jinja2.pass_environment +def sh_like_file_to_list(j2env, file_in: str) -> list: + tpl = j2env.get_template(file_in) + text = pathlib.Path(tpl.filename).read_text(encoding='utf-8') + lines = re.split(r'[\r\n]', text) + return list(itertools.filterfalse( + lambda x: re.match(r'\s*#', x), lines + )) + + J2CFG_FILTERS = [ any_to_env_dict, any_to_str_list, @@ -163,6 +250,7 @@ J2CFG_FILTERS = [ dict_empty_keys, dict_keys, dict_non_empty_keys, + dict_remap_keys, dict_to_env_str_list, is_mapping, is_re_fullmatch, diff --git a/j2cfg/j2cfg/settings.py b/j2cfg/j2cfg/settings.py index 4c1579f..03e1481 100644 --- a/j2cfg/j2cfg/settings.py +++ b/j2cfg/j2cfg/settings.py @@ -33,6 +33,38 @@ J2CFG_BANNED_ENVS = [ r'ANGIE_BPF_MAPS(=|$)' ] +J2CFG_PRESERVE_ENVS = [ + # glibc + 'GLIBC_TUNABLES', + 'MALLOC_ARENA_MAX', + # jemalloc + 'MALLOC_CONF', +] + +J2CFG_PASSTHROUGH_ENVS = [ + # openssl (man 7 openssl-env) + 'SSL_CERT_DIR', + 'SSL_CERT_FILE', + 'OPENSSL_CONF', + 'OPENSSL_CONF_INCLUDE', + 'OPENSSL_CONFIG', + 'OPENSSL_ENGINES', + 'OPENSSL_MODULES', + 'RANDFILE', + 'CTLOG_FILE', + # openssl: processor capabilities + 'OPENSSL_armcap', + 'OPENSSL_ia32cap', + 'OPENSSL_ppccap', + 'OPENSSL_riscvcap', + 'OPENSSL_s390xcap', + 'OPENSSL_sparcv9cap', + # generic proxy settings + 'NO_PROXY', + 'HTTPS_PROXY', + 'HTTP_PROXY', +] + def is_env_banned(k: str) -> bool: for r in J2CFG_BANNED_ENVS: diff --git a/j2cfg/test.j2 b/j2cfg/test.j2 index d774128..f07b7bc 100644 --- a/j2cfg/test.j2 +++ b/j2cfg/test.j2 @@ -42,12 +42,12 @@ uniq_str_list: {{ x | uniq_str_list }} {% set x = '2 3 1 2 ' %} -"x = {{ x }}" +x = {{ x.__repr__() }} str_split_to_list: {{ x | str_split_to_list }} {% set x = '2:3::1:2:' %} -"x = {{ x }}" +x = {{ x.__repr__() }} str_split_to_list(':'): {{ x | str_split_to_list(':') }} @@ -57,7 +57,7 @@ dict_to_env_str_list: {{ x | dict_to_env_str_list }} {% set x = '1 2 3 4' %} -"x = {{ x }}" +x = {{ x.__repr__() }} any_to_str_list: {{ x | any_to_str_list }} @@ -121,22 +121,22 @@ re_sub('[mn]', '_'): {{ x | re_sub('[mn]', '_') }} {% set x = 'j2cfg-multi.py' %} -x = {{ x }} +x = {{ x.__repr__() }} sh_like_file_to_list: {{ 'j2cfg-multi.py' | sh_like_file_to_list }} {% set x = 'Accept-Encoding' %} -x = {{ x }} +x = {{ x.__repr__() }} as_cgi_header: {{ x | as_cgi_header }} {% set x = '_Permissions-Policy--' %} -x = {{ x }} +x = {{ x.__repr__() }} as_cgi_header: {{ x | as_cgi_header }} {% set x = 'VAR1=Etc/UTC' %} -x = {{ x }} +x = {{ x.__repr__() }} any_to_env_dict: {{ x | any_to_env_dict }} @@ -161,6 +161,8 @@ dict_non_empty_keys: {% set x = [1,2,3,4] %} {% set y = [3,4,5,6] %} +x = {{ x }} +y = {{ y }} list_diff(x, y): {{ x | list_diff(y) }} list_diff(y, x): diff --git a/scripts/apt-install-angie-mod.sh b/scripts/apt-install-angie-mod.sh index 64a58e6..433b377 100755 --- a/scripts/apt-install-angie-mod.sh +++ b/scripts/apt-install-angie-mod.sh @@ -13,17 +13,43 @@ if [ -z "${NGX_DEBUG:-}" ] ; then NGX_DEBUG=0 fi -# ANGIE_MODULES_DIR=/usr/lib/angie/modules -d=/etc/angie/mod.dist +set -a +ANGIE_MODULES_DIR="${ANGIE_MODULES_DIR:-/usr/lib/angie/modules}" +set +a ## produce package list -p= +pkgs= for i ; do [ -n "$i" ] || continue - p="$p${p:+ }angie-module-$i" + + i="angie-module-$i" + printf '%s' "$i" | grep -zEq '^[a-z0-9.+-]+$' || { + env printf 'package name %q is not legal, quitting!\n' "$i" >&2 + exit 1 + } + + pkgs="${pkgs}${pkgs:+ }$i" done -[ -n "$p" ] || exit 0 +[ -n "${pkgs}" ] || exit 0 + +normalize_list() { + [ -n "$1" ] || return 0 + + printf '%s' "$1" \ + | tr -s '[:space:]' ' ' \ + | sed -zE 's/^ //;s/ $//' +} + +sort_dedup_list() { + [ -n "$1" ] || return 0 + + printf '%s' "$1" \ + | tr -s '[:space:]' '\n' | sort -uV | paste -sd ' ' \ + | sed -zE 's/^\s+//;s/\s+$//' +} + +pkgs=$(sort_dedup_list "${pkgs}") dirs='cache lib log' for n in ${dirs} ; do @@ -31,20 +57,26 @@ for n in ${dirs} ; do [ -d "$d" ] || install -d "$d" done -apt-install.sh $p +apt-install.sh ${pkgs} -[ -d "$d" ] || install -d "$d" +ANGIE_MODCONF_DIR=/etc/angie/mod.dist +[ -d "${ANGIE_MODCONF_DIR}" ] || install -d "${ANGIE_MODCONF_DIR}" list_ngx_modules() { set +e dpkg-query -L "$1" \ | grep -F -e "${ANGIE_MODULES_DIR}/" \ | grep -E -e '/[^/]+_module(-debug)?\.so$' \ - | sort -V \ + | sed -E '\,^(.+)-debug\.so$,{p;s//\1.so/;p;d}' \ + | sort -uV \ | xargs -r ls -U1d 2>/dev/null set -e } +is_same_file() { + find -L "$1" -samefile "$2" -printf . -quit 2>/dev/null | grep -Fq . || return 1 +} + gen_mod_config() { if [ -s "$2" ] ; then printf '%s: configuration already exists: %s\n' "$1" "$2" >&2 @@ -53,38 +85,49 @@ gen_mod_config() { [ -n "$3" ] || return + local __m for __m in $3 ; do echo "load_module ${__m};" done > "$2" } -for i ; do - [ -n "$i" ] || continue - - p="angie-module-$i" +for p in ${pkgs} ; do + [ -n "$p" ] || continue + i="${p#angie-module-}" ## adjust modules: ## - remove debug module if not in debug image ## - move debug module to usual location otherwise - while read -r fmod ; do - case "${fmod}" in + while read -r fmod_debug ; do + # [ -n "${fmod_debug}" ] || continue + case "${fmod_debug}" in *-debug.so ) ;; * ) continue ;; esac + fmod="${fmod_debug%-debug.so}.so" + fmod_tmp=$(mktemp -u "${fmod}.XXXXXXXXXX") if [ "${NGX_DEBUG}" = 0 ] ; then - rm -fv "${fmod}" + if [ -f "${fmod}" ] ; then + fmod_real=$(readlink -f "${fmod}") + else + env printf 'missing (non-debug) file: %q\n' "${fmod}" >&2 + env printf 'falling back to (debug) file: %q\n' "${fmod_debug}" >&2 + fmod_real=$(readlink -f "${fmod_debug}") + fi else - fmod_nodebug="${fmod%-debug.so}.so" - rm -fv "${fmod_nodebug}" - mv -fv "${fmod}" "${fmod_nodebug}" + fmod_real=$(readlink -f "${fmod_debug}") fi + [ -n "${fmod_real}" ] || exit 1 + ln -v "${fmod_real}" "${fmod_tmp}" + rm -fv "${fmod}" "${fmod_debug}" + mv -fv "${fmod_tmp}" "${fmod}" done <<-EOF $(list_ngx_modules "$p") EOF - if [ -e "$d/.$i.preseed" ] ; then - printf '%s: skipping generation of attachable module configs\n' "$p" >&2 + if [ -e "${ANGIE_MODCONF_DIR}/.$i.preseed" ] ; then + printf '%s: skipping generation of module load config (preseed is in effect)\n' "$p" >&2 continue fi @@ -93,6 +136,8 @@ for i ; do mail_modules= stream_modules= while read -r fmod ; do + [ -n "${fmod}" ] || continue + fmod_short="modules.d/${fmod#"${ANGIE_MODULES_DIR}/"}" fname=${fmod##*/} case "${fname}" in @@ -118,7 +163,7 @@ for i ; do $(list_ngx_modules "$p") EOF - [ -z "${http_modules}" ] || gen_mod_config "$p" "$d/http-$i.conf" "${http_modules}" - [ -z "${mail_modules}" ] || gen_mod_config "$p" "$d/mail-$i.conf" "${mail_modules}" - [ -z "${stream_modules}" ] || gen_mod_config "$p" "$d/stream-$i.conf" "${stream_modules}" + [ -z "${http_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/http-$i.conf" "${http_modules}" + [ -z "${mail_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/mail-$i.conf" "${mail_modules}" + [ -z "${stream_modules}" ] || gen_mod_config "$p" "${ANGIE_MODCONF_DIR}/stream-$i.conf" "${stream_modules}" done diff --git a/scripts/divert-rm.sh b/scripts/divert-rm.sh index 3793b22..79742d5 100755 --- a/scripts/divert-rm.sh +++ b/scripts/divert-rm.sh @@ -1,7 +1,7 @@ #!/bin/sh set -ef : "${1:?}" -d=$(printf '%s' "/run/$1" | tr -s '/') -mkdir -p "$(dirname "$d")" +d=$(printf '%s' "/run/angie/divert/$1" | tr -s '/') +mkdir -p "${d%/*}" dpkg-divert --divert "$d" --rename "$1" 2>/dev/null rm -f "$d"