2026
build-and-publish / build (push) Has been cancelled

This commit is contained in:
root
2026-04-26 01:38:39 +00:00
parent 51b6eaa694
commit 6689fd295b
6 changed files with 39 additions and 67 deletions
+5 -3
View File
@@ -108,9 +108,10 @@ jobs:
done done
# ---- DEBIAN/control -------------------------------------------------- # ---- DEBIAN/control --------------------------------------------------
# Minimum metadata dpkg requires. We don't declare runtime Depends: # Minimum metadata dpkg requires. The .deb bundles every shared library
# the .deb bundles every shared library nginx needs (see the ldd # nginx links against (see the ldd loop above), so the only Depends we
# loop above), so the only thing the host must provide is glibc. # declare is libjemalloc2 — the systemd unit LD_PRELOADs it for the
# nginx workers; without it, the unit would fail to start.
sudo mkdir -p "${DEB_DIR}" sudo mkdir -p "${DEB_DIR}"
sudo tee "${DEB_DIR}/control" >/dev/null <<EOF sudo tee "${DEB_DIR}/control" >/dev/null <<EOF
Package: ${PKG_NAME} Package: ${PKG_NAME}
@@ -118,6 +119,7 @@ jobs:
Section: base Section: base
Priority: optional Priority: optional
Architecture: ${ARCH} Architecture: ${ARCH}
Depends: libjemalloc2
Maintainer: Julio <me@julio.al> Maintainer: Julio <me@julio.al>
Description: Nginx L7 DDoS Protection (The-World-Is-Yours), built by RAWeb CI. Description: Nginx L7 DDoS Protection (The-World-Is-Yours), built by RAWeb CI.
EOF EOF
-46
View File
@@ -69,7 +69,6 @@ nginx -s reload
## Performance ## Performance
The default config in `static/nginx/nginx.conf` is tuned for shared hosting at 5,000+ vhost scale. Numbers below are realistic ranges from public benchmarks and our own load testing — your mileage will vary with workload.
### vs. vanilla nginx (same version, default config) ### vs. vanilla nginx (same version, default config)
@@ -82,51 +81,6 @@ The default config in `static/nginx/nginx.conf` is tuned for shared hosting at 5
| Compressed-text bandwidth | **60 to 80%** | unchanged | brotli + gzip enabled in `http {}` | | Compressed-text bandwidth | **60 to 80%** | unchanged | brotli + gzip enabled in `http {}` |
| WAF, Lua, HTTP/3 | included | not included | needs custom build | | WAF, Lua, HTTP/3 | included | not included | needs custom build |
### vs. OpenResty
| Area | Twiy | OpenResty |
|---|---|---|
| nginx version | tracks upstream stable (1.30.0) | lags upstream by months while waiting for openresty's bundle release |
| TLS backend | AWS-LC (BoringSSL fork) | OpenSSL (or quictls) by default |
| Lua stack | upstream `lua-nginx-module` + pinned `lua-resty-core` | OpenResty's vendored fork |
| Module surface | ModSecurity v3, naxsi, brotli, geoip2, http_v3, set_misc, headers_more, http-flv, srcache, redis2, testcookie, lrucache, mysql, lock | similar but defined by openresty's bundle |
| Distribution | apt repo, single `.deb` | tarball or vendor's apt repo |
OpenResty is the right choice if you want a curated, all-in-one Lua-centric stack and don't mind being a few nginx releases behind. Twiy is the right choice if you want vanilla nginx's release cadence with a hardened security/performance stack on top.
### vs. Apache (httpd)
| Area | Twiy | Apache (event/prefork MPM) |
|---|---|---|
| Concurrency model | event-driven, single-process-per-core | thread/process-per-connection (event MPM is closer but still heavier) |
| Static file req/s (small files, single core) | typically **24× higher** | baseline |
| Memory per idle connection | **~kB** | **~hundreds of kB** (per worker process/thread) |
| TLS handshake CPU | comparable with mod_ssl, **lower** with mod_md off | baseline |
| WAF | ModSecurity v3 (libmodsecurity) + naxsi | ModSecurity v2 (mod_security2) common |
| HTTP/3 / QUIC | **yes** (AWS-LC) | **no** in stable releases |
The nginx-vs-Apache static-file gap widens dramatically at high concurrency (10k+ idle keepalive connections): nginx holds them on epoll for kilobytes each; Apache event MPM still allocates significantly more per connection.
### Where the wins actually come from in this build
| Source | Yield |
|---|---|
| AWS-LC (vs vanilla OpenSSL on TLS) | 515% handshake CPU saving |
| `open_file_cache` (max=200000, inactive=30s) | 25× static throughput on a busy 5k-vhost host |
| `ssl_session_cache shared:SSL:200m` | huge — first vs resumed handshake is ~10× CPU difference |
| OCSP stapling (`ssl_stapling on`) | removes per-handshake OCSP RTT (often 50200 ms p95) |
| `worker_cpu_affinity auto` | ~5% on CPU-bound workloads (cache locality) |
| `brotli on` + `gzip on` in `http{}` | 6080% smaller text responses |
| `keepalive_requests 10000` (vs 1000 default) | fewer reconnects under sustained HTTP/2 load |
| `client_header_buffer_size 4k` (down from 2M) | drops worst-case memory amplification surface |
| `server_names_hash_max_size 32768` | makes 5k+ vhost configs actually parseable |
### Things this build deliberately does NOT do (yet)
- No HTTP/3 `listen 443 quic` directive in `static/nginx/live/default` — left to the per-vhost templates so you can opt in selectively.
- No ECDSA P-256 certificates (a per-cert decision; ECDSA handshakes are ~3× faster than RSA-2048).
- No OS-level sysctl tuning (`net.core.rmem_max` for QUIC, `net.core.somaxconn`, `fs.file-max`) — would belong in the `.deb` postinst or a `/etc/sysctl.d/twiy.conf` shipped with the package; not yet wired up.
# Support options. # Support options.
- No free support for how to do things, please don't spam with questions in discord. - No free support for how to do things, please don't spam with questions in discord.
+11 -1
View File
@@ -7,7 +7,7 @@ function reqs() {
apt-get -y install wget zip unzip build-essential libssl-dev curl nano git apt-get -y install wget zip unzip build-essential libssl-dev curl nano git
# apt-get -y install iptables ipset # apt-get -y install iptables ipset
apt-get install libtool pkg-config make cmake automake autoconf golang-go ninja-build -y apt-get install libtool pkg-config make cmake automake autoconf golang-go ninja-build -y
apt-get install libyajl-dev ssdeep zlib1g-dev libxslt1-dev libgd-dev libgeoip-dev liblmdb-dev libfuzzy-dev libmaxminddb-dev liblua5.1-dev libcurl4-openssl-dev libxml2 libxml2-dev mercurial libpcre2-dev libc-ares-dev libre2-dev -y apt-get install libyajl-dev ssdeep zlib1g-dev libxslt1-dev libgd-dev libgeoip-dev liblmdb-dev libfuzzy-dev libmaxminddb-dev liblua5.1-dev libcurl4-openssl-dev libxml2 libxml2-dev mercurial libpcre2-dev libc-ares-dev libre2-dev libzstd-dev libjemalloc2 -y
mkdir -p $LUA_SCRIPTS mkdir -p $LUA_SCRIPTS
} }
function clean_install() { function clean_install() {
@@ -204,6 +204,14 @@ function clean_install() {
cd /opt/mod/; git clone --recurse-submodules https://github.com/wargio/naxsi.git naxsi cd /opt/mod/; git clone --recurse-submodules https://github.com/wargio/naxsi.git naxsi
fi fi
# NGX_MOD_ZSTD — Zstandard compression module from tokers. Pinned via
# NGX_MOD_ZSTD; tarball pattern (dir name embeds version → cache invalidates
# automatically when the pin moves).
if [ ! -d /opt/mod/zstd-nginx-module-${NGX_MOD_ZSTD} ]; then
cd /opt/mod/; wget https://github.com/tokers/zstd-nginx-module/archive/refs/tags/${NGX_MOD_ZSTD}.tar.gz
cd /opt/mod/; tar xf ${NGX_MOD_ZSTD}.tar.gz; rm -Rf ${NGX_MOD_ZSTD}.tar.gz
fi
# END OF NGINX MODULES # END OF NGINX MODULES
# ============================================================================================================ # ============================================================================================================
} }
@@ -261,6 +269,7 @@ test_nginx() {
--add-module=/opt/mod/srcache-nginx-module-${NGX_MOD_LUA_SRCACHE} \ --add-module=/opt/mod/srcache-nginx-module-${NGX_MOD_LUA_SRCACHE} \
--add-module=/opt/mod/redis2-nginx-module \ --add-module=/opt/mod/redis2-nginx-module \
--add-module=/opt/mod/ngx_brotli \ --add-module=/opt/mod/ngx_brotli \
--add-module=/opt/mod/zstd-nginx-module-${NGX_MOD_ZSTD} \
--add-module=/opt/mod/testcookie \ --add-module=/opt/mod/testcookie \
--with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include" \ --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include" \
--with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib" --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib"
@@ -319,6 +328,7 @@ function build() {
--add-module=/opt/mod/srcache-nginx-module-${NGX_MOD_LUA_SRCACHE} \ --add-module=/opt/mod/srcache-nginx-module-${NGX_MOD_LUA_SRCACHE} \
--add-module=/opt/mod/redis2-nginx-module \ --add-module=/opt/mod/redis2-nginx-module \
--add-module=/opt/mod/ngx_brotli \ --add-module=/opt/mod/ngx_brotli \
--add-module=/opt/mod/zstd-nginx-module-${NGX_MOD_ZSTD} \
--add-module=/opt/mod/testcookie \ --add-module=/opt/mod/testcookie \
--with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include" \ --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include" \
--with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib" --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib"
+4
View File
@@ -6,6 +6,10 @@ Wants=network-online.target
[Service] [Service]
Type=forking Type=forking
PIDFile=/run/nginx.pid PIDFile=/run/nginx.pid
# jemalloc replaces glibc malloc — better fragmentation/perf under nginx's
# alloc/free churn at scale. Package depends on libjemalloc2 so the .so is
# guaranteed present. Removing this line falls back to glibc malloc cleanly.
Environment=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
ExecStartPre=/usr/bin/install -d -o nginx -g nginx -m 0755 /usr/local/nginx /usr/local/nginx/client_body_temp /usr/local/nginx/proxy_temp /usr/local/nginx/fastcgi_temp /usr/local/nginx/uwsgi_temp /usr/local/nginx/scgi_temp /var/log/nginx ExecStartPre=/usr/bin/install -d -o nginx -g nginx -m 0755 /usr/local/nginx /usr/local/nginx/client_body_temp /usr/local/nginx/proxy_temp /usr/local/nginx/fastcgi_temp /usr/local/nginx/uwsgi_temp /usr/local/nginx/scgi_temp /var/log/nginx
ExecStartPre=/usr/sbin/nginx -t ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx ExecStart=/usr/sbin/nginx
+14 -17
View File
@@ -8,7 +8,7 @@
user nginx; user nginx;
pid /var/run/nginx.pid; pid /var/run/nginx.pid;
worker_processes auto; worker_processes auto;
worker_cpu_affinity auto; # Pin workers to cores for L1/L2 locality. worker_cpu_affinity auto;
worker_rlimit_nofile 65535; worker_rlimit_nofile 65535;
events { events {
@@ -32,8 +32,6 @@ http {
# =================== END LOGS ========================= # # =================== END LOGS ========================= #
# ==================== GENERAL ========================= # # ==================== GENERAL ========================= #
# Header buffers — keep small. The previous 2M default was a memory
# amplification target (per-conn × worker_connections = absurd worst case).
client_header_buffer_size 4k; client_header_buffer_size 4k;
large_client_header_buffers 4 16k; large_client_header_buffers 4 16k;
client_body_buffer_size 16k; client_body_buffer_size 16k;
@@ -41,10 +39,10 @@ http {
client_body_timeout 30s; client_body_timeout 30s;
client_header_timeout 30s; client_header_timeout 30s;
send_timeout 30s; send_timeout 30s;
reset_timedout_connection on; # Free sockets fast under churn. reset_timedout_connection on;
keepalive_timeout 65s; # Amortise TCP setup across requests. keepalive_timeout 65s;
keepalive_requests 10000; # Default 1000 too low for HTTP/2. keepalive_requests 2000;
max_headers 100; # nginx 1.29.8 — slowloris defence. max_headers 100;
port_in_redirect off; port_in_redirect off;
sendfile on; sendfile on;
sendfile_max_chunk 1m; sendfile_max_chunk 1m;
@@ -53,8 +51,6 @@ http {
server_tokens off; server_tokens off;
server_name_in_redirect off; server_name_in_redirect off;
# 5,000+ vhost hash sizing. _max_size must exceed total server names;
# _bucket_size must be a CPU-cache-line multiple (32/64/128/256/512/1024).
server_names_hash_bucket_size 128; server_names_hash_bucket_size 128;
server_names_hash_max_size 32768; server_names_hash_max_size 32768;
types_hash_max_size 4096; types_hash_max_size 4096;
@@ -67,14 +63,13 @@ http {
# ===================== TLS ============================ # # ===================== TLS ============================ #
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off; # TLS 1.3 ciphers, client picks. ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:200m; # ~800k sessions shared across workers ssl_session_cache shared:SSL:200m;
ssl_session_timeout 1d; ssl_session_timeout 1d;
ssl_session_tickets off; # Off unless you have ticket-key rotation. ssl_session_tickets off;
ssl_stapling on; # OCSP stapling — avoid per-handshake OCSP lookups. ssl_stapling on;
ssl_stapling_verify on; ssl_stapling_verify on;
# ===================== END TLS ======================== # # ===================== END TLS ======================== #
resolver 1.1.1.1 1.0.0.1 valid=300s; resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s; resolver_timeout 5s;
default_type application/octet-stream; default_type application/octet-stream;
@@ -86,9 +81,6 @@ http {
} }
# ==================== COMPRESSION ===================== # # ==================== COMPRESSION ===================== #
# Compiled in, now actually enabled. Bandwidth saving on text responses
# is typically 60-80% for HTML/JSON/CSS/JS/SVG. Comp level 4 is the
# sweet spot for CPU vs ratio on shared hosting.
gzip on; gzip on;
gzip_vary on; gzip_vary on;
gzip_proxied any; gzip_proxied any;
@@ -100,6 +92,11 @@ http {
brotli_comp_level 4; brotli_comp_level 4;
brotli_min_length 256; brotli_min_length 256;
brotli_types text/plain text/css text/xml application/json application/javascript application/xml application/xml+rss application/atom+xml image/svg+xml font/ttf font/otf font/woff font/woff2; brotli_types text/plain text/css text/xml application/json application/javascript application/xml application/xml+rss application/atom+xml image/svg+xml font/ttf font/otf font/woff font/woff2;
zstd on;
zstd_comp_level 4;
zstd_min_length 256;
zstd_types text/plain text/css text/xml application/json application/javascript application/xml application/xml+rss application/atom+xml image/svg+xml font/ttf font/otf font/woff font/woff2;
# =================== END COMPRESSION ================== # # =================== END COMPRESSION ================== #
# =================== END GENERAL ====================== # # =================== END GENERAL ====================== #
+5
View File
@@ -52,3 +52,8 @@ export NGX_MOD_LUA_LOCK="0.09"
# https://github.com/openresty/srcache-nginx-module/tags # https://github.com/openresty/srcache-nginx-module/tags
export NGX_MOD_LUA_SRCACHE="0.33" export NGX_MOD_LUA_SRCACHE="0.33"
# https://github.com/tokers/zstd-nginx-module/tags
# Zstandard compression module. Chrome 123+ and Firefox 126+ send
# `Accept-Encoding: zstd`; older clients fall back to brotli/gzip.
export NGX_MOD_ZSTD="0.1.1"