diff --git a/Dockerfile b/Dockerfile index 8afc497..a599e67 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:xenial +FROM openresty/openresty:1.29.2.1-alpine-fat # Expose port EXPOSE 80 @@ -6,80 +6,19 @@ EXPOSE 80 # Declare volume where github auth cache and listing cache will be stored VOLUME ["/data/nginx"] -# Download and install requirements for entrypoint scripts and nginx compilation -RUN apt-get update && \ - apt-get install --no-install-recommends --no-upgrade --assume-yes curl ca-certificates dnsutils wget gcc make libpcre3-dev libssl-dev libxml2-dev libxslt1-dev zlib1g-dev +# Install runtime dependencies: +# - bash: required by start.sh (#!/bin/bash) +# - curl: used by stop.sh to poll nginx_status +# - bind-tools: provides 'host' command used by start.sh for DNS resolution +RUN apk add --no-cache bash curl bind-tools -# Define components versions -ENV LUA_RESTY_CORE 0.1.17 -ENV LUA_RESTY_LRUCACHE 0.09 -ENV LUAJIT2_VERSION 2.1-20190626 -ENV NGX_DEVEL_KIT_VERSION 0.3.1 -ENV LUA_NGINX_MODULE_VERSION 0.10.15 -ENV SET_MISC_NGINX_MODULE 0.32 -ENV NGINX_VERSION 1.16.1 - -WORKDIR /tmp - -# Download build and install lua-resty-core -RUN wget https://github.com/openresty/lua-resty-core/archive/v${LUA_RESTY_CORE}.tar.gz -O lua-resty-core.tar.gz && \ - mkdir lua-resty-core && \ - tar zxf lua-resty-core.tar.gz -C lua-resty-core --strip-components=1 -RUN make install -C lua-resty-core - -# Download build and install lua-resty-lrucache -RUN wget https://github.com/openresty/lua-resty-lrucache/archive/v${LUA_RESTY_LRUCACHE}.tar.gz -O lua-resty-lrucache.tar.gz && \ - mkdir lua-resty-lrucache && \ - tar zxf lua-resty-lrucache.tar.gz -C lua-resty-lrucache --strip-components=1 -RUN make install -C lua-resty-lrucache - -# Download build and install LuaJIT -RUN wget https://github.com/openresty/luajit2/archive/v${LUAJIT2_VERSION}.tar.gz -O luajit2.tar.gz && \ - mkdir luajit2 && \ - tar zxf luajit2.tar.gz -C luajit2 --strip-components=1 -RUN make -C luajit2 -RUN make install -C luajit2 - -# Tell system where to find LuaJIT 2.1 -ENV LUAJIT_LIB=/usr/local/lib -ENV LUAJIT_INC=/usr/local/include/luajit-2.1 - -# Download ngx_devel_kit -RUN wget https://github.com/simplresty/ngx_devel_kit/archive/v${NGX_DEVEL_KIT_VERSION}.tar.gz -O ngx_devel_kit.tar.gz && \ - mkdir ngx_devel_kit && \ - tar zxf ngx_devel_kit.tar.gz -C ngx_devel_kit --strip-components=1 - -# Download lua-nginx-module -RUN wget https://github.com/openresty/lua-nginx-module/archive/v${LUA_NGINX_MODULE_VERSION}.tar.gz -O lua-nginx-module.tar.gz && \ - mkdir lua-nginx-module && \ - tar zxf lua-nginx-module.tar.gz -C lua-nginx-module --strip-components=1 - -# Download set-misc-nginx-module -RUN wget https://github.com/openresty/set-misc-nginx-module/archive/v${SET_MISC_NGINX_MODULE}.tar.gz -O set-misc-nginx-module.tar.gz && \ - mkdir set-misc-nginx-module && \ - tar zxf set-misc-nginx-module.tar.gz -C set-misc-nginx-module --strip-components=1 - -# Download nginx -RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz -O nginx.tar.gz && \ - mkdir nginx && \ - tar zxf nginx.tar.gz -C nginx --strip-components=1 - -WORKDIR /tmp/nginx - -# Build and install nginx -RUN ./configure --sbin-path=/usr/local/sbin \ - --conf-path=/etc/nginx/nginx.conf \ - --pid-path=/var/run/nginx.pid \ - --error-log-path=/dev/stderr \ - --http-log-path=/dev/stdout \ - --with-http_ssl_module \ - --with-http_xslt_module \ - --with-http_stub_status_module \ - --add-module=/tmp/ngx_devel_kit \ - --add-module=/tmp/lua-nginx-module \ - --add-module=/tmp/set-misc-nginx-module -RUN make -RUN make install +# Create compatibility symlinks so start.sh/stop.sh work without modification: +# - /usr/local/sbin/nginx -> OpenResty nginx binary +# - /etc/nginx -> OpenResty conf dir (also makes mime.types available at /etc/nginx/mime.types) +RUN mkdir -p /usr/local/sbin && \ + ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/local/sbin/nginx && \ + rm -rf /etc/nginx && \ + ln -sf /usr/local/openresty/nginx/conf /etc/nginx # Install start scripts COPY full_listing_cache_update.sh /full_listing_cache_update.sh @@ -101,20 +40,20 @@ COPY lua/search_metadata.lua /etc/nginx/search_metadata.lua COPY lua/browse.lua /etc/nginx/browse.lua COPY lua/github_access.lua /etc/nginx/github_access.lua -RUN /usr/local/bin/luajit -b /etc/nginx/canonicalize_path.lua /etc/nginx/canonicalize_path.ljbc -RUN /usr/local/bin/luajit -b /etc/nginx/compute_aws_s3_signature.lua /etc/nginx/compute_aws_s3_signature.ljbc -RUN /usr/local/bin/luajit -b /etc/nginx/find_build.lua /etc/nginx/find_build.ljbc -RUN /usr/local/bin/luajit -b /etc/nginx/copy_build.lua /etc/nginx/copy_build.ljbc -RUN /usr/local/bin/luajit -b /etc/nginx/version_object.lua /etc/nginx/version_object.ljbc -RUN /usr/local/bin/luajit -b /etc/nginx/add_metadata.lua /etc/nginx/add_metadata.ljbc -RUN /usr/local/bin/luajit -b /etc/nginx/search_metadata.lua /etc/nginx/search_metadata.ljbc -RUN /usr/local/bin/luajit -b /etc/nginx/browse.lua /etc/nginx/browse.ljbc -RUN /usr/local/bin/luajit -b /etc/nginx/github_access.lua /etc/nginx/github_access.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/canonicalize_path.lua /etc/nginx/canonicalize_path.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/compute_aws_s3_signature.lua /etc/nginx/compute_aws_s3_signature.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/find_build.lua /etc/nginx/find_build.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/copy_build.lua /etc/nginx/copy_build.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/version_object.lua /etc/nginx/version_object.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/add_metadata.lua /etc/nginx/add_metadata.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/search_metadata.lua /etc/nginx/search_metadata.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/browse.lua /etc/nginx/browse.ljbc +RUN /usr/local/openresty/luajit/bin/luajit -b /etc/nginx/github_access.lua /etc/nginx/github_access.ljbc # Install xslt filter COPY xslt/browse.raw.xslt.template /etc/nginx/browse.raw.xslt.template -# Install nginx configurations file +# Install nginx configuration file COPY conf/nginx.conf.template /etc/nginx/nginx.conf.template # Launch nginx diff --git a/conf/nginx.conf.template b/conf/nginx.conf.template index 38a0e87..ceadd77 100644 --- a/conf/nginx.conf.template +++ b/conf/nginx.conf.template @@ -1,3 +1,6 @@ +# Load xslt dynamic module (required with OpenResty alpine-fat) +load_module modules/ngx_http_xslt_filter_module.so; + # Reverse-proxy configuration for listing, download, upload, redirect # operations on a Google Cloud Storage S3 compatible bucket, with some # additional features to find build depending on prefix and status, and @@ -18,7 +21,9 @@ env BOT_TOKEN; env AWS_BUCKET_PREFIX; # It is recommended to set one worker process per CPU core. -worker_processes 2; +pid /run/nginx.pid; + +worker_processes auto; # The maximum number of connections allowed to a worker. events { @@ -90,15 +95,15 @@ http { # Max number of unused keep-alive connections kept open per worker process # for the pool. # - keepalive 16; + keepalive 64; # Max number of requests per connection. # - keepalive_requests 256; + keepalive_requests 1000; # Max time of inactivity per connection. # - keepalive_timeout 60s; + keepalive_timeout 75s; } upstream ${AWS_BUCKET_PREFIX}-prolonged { @@ -113,9 +118,9 @@ http { server __S3_ENDPOINT_GENERIC_IPV4__:__S3_ENDPOINT_PORT__ max_fails=0 backup; server __S3_ENDPOINT_GENERIC_IPV4__:__S3_ENDPOINT_PORT__ max_fails=0 backup; - keepalive 16; - keepalive_requests 256; - keepalive_timeout 60s; + keepalive 64; + keepalive_requests 1000; + keepalive_timeout 75s; } upstream ${AWS_BUCKET_PREFIX}-promoted { @@ -130,9 +135,9 @@ http { server __S3_ENDPOINT_GENERIC_IPV4__:__S3_ENDPOINT_PORT__ max_fails=0 backup; server __S3_ENDPOINT_GENERIC_IPV4__:__S3_ENDPOINT_PORT__ max_fails=0 backup; - keepalive 16; - keepalive_requests 256; - keepalive_timeout 60s; + keepalive 64; + keepalive_requests 1000; + keepalive_timeout 75s; } # Do not store client request body before sending it via proxy_pass. diff --git a/lua/compute_aws_s3_signature.lua b/lua/compute_aws_s3_signature.lua index 9947065..7419d9e 100644 --- a/lua/compute_aws_s3_signature.lua +++ b/lua/compute_aws_s3_signature.lua @@ -243,7 +243,7 @@ elseif signature_mode == "PRESIGN" then -- Set presignature expiration -- - expires = ngx.time() + 60 + expires = ngx.time() + 3600 -- Compute presignature. -- diff --git a/lua/github_access.lua b/lua/github_access.lua index 6485fd5..bbd6098 100644 --- a/lua/github_access.lua +++ b/lua/github_access.lua @@ -99,7 +99,12 @@ function lock_cache(auth_md5, username) local path = github_auth_cache_dir .. "/" .. auth_md5 .. ".lock" local status = os.execute("mkdir " .. path .. " 2> /dev/null") - if status ~= 0 then + -- In OpenResty 1.29.x / LuaJIT with Lua 5.2 semantics, os.execute returns + -- true on success and nil on failure (not integer exit codes as in Lua 5.1). + -- The original check `status ~= 0` is always true in both cases under Lua 5.2, + -- so we need to check for the boolean true to detect a successful mkdir. + local lock_created = (status == true) or (status == 0) + if not lock_created then -- Someone else is already in the process of updating this cache entry. -- Wait for the entry to be there. ngx.log(ngx.DEBUG, "cache write already locked for " .. username .. " (" .. auth_md5 .. "), waiting") @@ -248,6 +253,14 @@ function restriction_check(auth) return false end +-- Skip auth for the internal github API proxy location to prevent deadlock: +-- ngx.location.capture("/force_github_request/...") triggers this access_by_lua_file +-- again, and the cache lock mechanism would deadlock since the parent request holds +-- the lock while waiting for the subrequest to complete. +if string.sub(ngx.var.uri, 1, 21) == "/force_github_request" then + return +end + if github_api_enabled == 'true' and ngx.var.remote_addr ~= '127.0.0.1' then local auth = verify_header() if not auth then