From 70f33a772781233e289975fad9e05db53e070140 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:11:16 +0000 Subject: [PATCH 1/7] Initial plan From e046d8c0e0d4c811187b34d66a342bcd2e4471db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:15:14 +0000 Subject: [PATCH 2/7] Add comprehensive CI/CD workflow for zstd-nginx-module Co-authored-by: tokers <10428333+tokers@users.noreply.github.com> --- .github/workflows/ci.yml | 211 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0ff3f9c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,211 @@ +name: CI + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + workflow_dispatch: + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-20.04, ubuntu-22.04] + nginx_version: ['1.24.0', '1.25.3', '1.26.0'] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + libpcre3 libpcre3-dev \ + zlib1g zlib1g-dev \ + libssl-dev \ + libzstd-dev \ + perl \ + cpanminus + + - name: Install Perl test dependencies + run: | + sudo cpanm --notest Test::Nginx + + - name: Cache nginx + id: cache-nginx + uses: actions/cache@v4 + with: + path: ~/nginx-${{ matrix.nginx_version }} + key: nginx-${{ matrix.nginx_version }}-${{ matrix.os }} + + - name: Download and extract nginx + if: steps.cache-nginx.outputs.cache-hit != 'true' + run: | + cd ~ + wget -q http://nginx.org/download/nginx-${{ matrix.nginx_version }}.tar.gz + tar -xzf nginx-${{ matrix.nginx_version }}.tar.gz + + - name: Configure and build nginx with zstd module + run: | + cd ~/nginx-${{ matrix.nginx_version }} + ./configure \ + --prefix=/tmp/nginx \ + --with-http_ssl_module \ + --with-http_v2_module \ + --add-module=${{ github.workspace }} + make -j$(nproc) + sudo make install + + - name: Add nginx to PATH + run: | + echo "/tmp/nginx/sbin" >> $GITHUB_PATH + + - name: Verify nginx installation + run: | + /tmp/nginx/sbin/nginx -V + + - name: Run tests + run: | + export PATH=/tmp/nginx/sbin:$PATH + cd ${{ github.workspace }} + prove -r t/ + env: + TEST_NGINX_BINARY: /tmp/nginx/sbin/nginx + + build-docker: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build test Dockerfile + run: | + cat > Dockerfile.test << 'EOF' + FROM nginx:1.26.0 AS builder + + # Install build dependencies + RUN apt-get update && apt-get install -y \ + build-essential \ + libpcre3-dev \ + zlib1g-dev \ + libssl-dev \ + libzstd-dev \ + wget \ + && rm -rf /var/lib/apt/lists/* + + # Get nginx source + WORKDIR /build + RUN wget -q http://nginx.org/download/nginx-1.26.0.tar.gz && \ + tar -xzf nginx-1.26.0.tar.gz + + # Copy module source + COPY . /build/zstd-nginx-module + + # Build nginx with zstd module + WORKDIR /build/nginx-1.26.0 + RUN ./configure \ + --prefix=/etc/nginx \ + --sbin-path=/usr/sbin/nginx \ + --modules-path=/usr/lib/nginx/modules \ + --conf-path=/etc/nginx/nginx.conf \ + --error-log-path=/var/log/nginx/error.log \ + --http-log-path=/var/log/nginx/access.log \ + --pid-path=/var/run/nginx.pid \ + --lock-path=/var/run/nginx.lock \ + --http-client-body-temp-path=/var/cache/nginx/client_temp \ + --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ + --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ + --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ + --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ + --user=nginx \ + --group=nginx \ + --with-http_ssl_module \ + --with-http_realip_module \ + --with-http_addition_module \ + --with-http_sub_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_mp4_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_random_index_module \ + --with-http_secure_link_module \ + --with-http_stub_status_module \ + --with-http_auth_request_module \ + --with-http_v2_module \ + --with-http_slice_module \ + --with-threads \ + --with-file-aio \ + --add-module=/build/zstd-nginx-module && \ + make -j$(nproc) && \ + make install + + # Runtime stage + FROM nginx:1.26.0 + + # Install runtime dependencies + RUN apt-get update && apt-get install -y \ + libzstd1 \ + && rm -rf /var/lib/apt/lists/* + + # Copy compiled nginx with zstd module + COPY --from=builder /usr/sbin/nginx /usr/sbin/nginx + + # Test configuration + RUN nginx -V 2>&1 | grep zstd + + EXPOSE 80 443 + CMD ["nginx", "-g", "daemon off;"] + EOF + + - name: Build Docker image + run: | + docker build -f Dockerfile.test -t nginx-zstd:test . + + - name: Test Docker image + run: | + # Start container + docker run -d --name nginx-zstd-test nginx-zstd:test + sleep 2 + + # Check if nginx is running + docker ps | grep nginx-zstd-test + + # Check nginx version includes zstd + docker exec nginx-zstd-test nginx -V 2>&1 | grep zstd + + # Cleanup + docker stop nginx-zstd-test + docker rm nginx-zstd-test + + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check for trailing whitespace + run: | + if git grep -I --line-number -P '\s+$' -- '*.c' '*.h' 'config' 2>/dev/null; then + echo "Error: Found trailing whitespace" + exit 1 + else + echo "No trailing whitespace found" + fi + + - name: Check file permissions + run: | + # Check that source files don't have execute permissions + if find . -name '*.c' -o -name '*.h' | xargs ls -l | grep '^-rwxr'; then + echo "Error: Source files should not be executable" + exit 1 + else + echo "File permissions are correct" + fi From 25c03780ff36151661912c64d0976afeaaab3d37 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:16:57 +0000 Subject: [PATCH 3/7] Add example configurations and Dockerfile for users Co-authored-by: tokers <10428333+tokers@users.noreply.github.com> --- example/Dockerfile | 97 ++++++++++++++++++++++++++++++ example/README.md | 147 +++++++++++++++++++++++++++++++++++++++++++++ example/nginx.conf | 69 +++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 example/Dockerfile create mode 100644 example/README.md create mode 100644 example/nginx.conf diff --git a/example/Dockerfile b/example/Dockerfile new file mode 100644 index 0000000..ff33c9c --- /dev/null +++ b/example/Dockerfile @@ -0,0 +1,97 @@ +# Multi-stage Dockerfile for building Nginx with zstd-nginx-module +# +# This Dockerfile demonstrates how to build a production-ready Nginx image +# with the zstd compression module integrated. +# +# Usage: +# docker build -t nginx-zstd:latest . +# docker run -d -p 80:80 nginx-zstd:latest + +ARG NGINX_VERSION=1.26.0 + +# Build stage +FROM nginx:${NGINX_VERSION} AS builder + +# Install build dependencies +RUN apt-get update && apt-get install -y \ + build-essential \ + libpcre3-dev \ + zlib1g-dev \ + libssl-dev \ + libzstd-dev \ + wget \ + && rm -rf /var/lib/apt/lists/* + +# Download and extract Nginx source +WORKDIR /build +RUN wget -q http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz && \ + tar -xzf nginx-${NGINX_VERSION}.tar.gz + +# Copy zstd-nginx-module source +COPY . /build/zstd-nginx-module + +# Configure and build Nginx with zstd module +WORKDIR /build/nginx-${NGINX_VERSION} +RUN ./configure \ + --prefix=/etc/nginx \ + --sbin-path=/usr/sbin/nginx \ + --modules-path=/usr/lib/nginx/modules \ + --conf-path=/etc/nginx/nginx.conf \ + --error-log-path=/var/log/nginx/error.log \ + --http-log-path=/var/log/nginx/access.log \ + --pid-path=/var/run/nginx.pid \ + --lock-path=/var/run/nginx.lock \ + --http-client-body-temp-path=/var/cache/nginx/client_temp \ + --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ + --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ + --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ + --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ + --user=nginx \ + --group=nginx \ + --with-http_ssl_module \ + --with-http_realip_module \ + --with-http_addition_module \ + --with-http_sub_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_mp4_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_random_index_module \ + --with-http_secure_link_module \ + --with-http_stub_status_module \ + --with-http_auth_request_module \ + --with-http_v2_module \ + --with-http_slice_module \ + --with-threads \ + --with-file-aio \ + --add-module=/build/zstd-nginx-module && \ + make -j$(nproc) && \ + make install + +# Runtime stage +FROM nginx:${NGINX_VERSION} + +# Install runtime dependencies +RUN apt-get update && apt-get install -y \ + libzstd1 \ + && rm -rf /var/lib/apt/lists/* + +# Copy compiled Nginx binary with zstd module +COPY --from=builder /usr/sbin/nginx /usr/sbin/nginx + +# Copy example configuration (optional) +COPY example/nginx.conf /etc/nginx/nginx.conf.example + +# Verify the module is loaded +RUN nginx -V 2>&1 | grep -q zstd || (echo "zstd module not found!" && exit 1) + +# Expose ports +EXPOSE 80 443 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost/ || exit 1 + +# Start Nginx +CMD ["nginx", "-g", "daemon off;"] diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..4ef1a4a --- /dev/null +++ b/example/README.md @@ -0,0 +1,147 @@ +# Examples + +This directory contains example configurations and Dockerfiles for using the zstd-nginx-module. + +## Contents + +- `nginx.conf` - Example Nginx configuration with zstd compression enabled +- `Dockerfile` - Multi-stage Dockerfile for building Nginx with zstd module + +## Using the Dockerfile + +Build the Docker image: + +```bash +docker build -t nginx-zstd:latest . +``` + +Run the container: + +```bash +docker run -d -p 80:80 --name nginx-zstd nginx-zstd:latest +``` + +Test zstd compression: + +```bash +# Request with zstd accept-encoding +curl -H "Accept-Encoding: zstd" -I http://localhost/ + +# You should see "Content-Encoding: zstd" in the response headers +``` + +## Using the nginx.conf + +The example configuration demonstrates: + +1. **Basic zstd compression** - Enabled globally with compression level 3 +2. **Compression thresholds** - Only compress responses larger than 256 bytes +3. **MIME type filtering** - Compress specific content types +4. **Static pre-compressed files** - Serve `.zst` files when available +5. **Logging compression ratio** - Track compression efficiency with `$zstd_ratio` variable + +To use this configuration: + +1. Copy it to your Nginx configuration directory: + ```bash + cp nginx.conf /etc/nginx/nginx.conf + ``` + +2. Test the configuration: + ```bash + nginx -t + ``` + +3. Reload Nginx: + ```bash + nginx -s reload + ``` + +## Building Nginx Manually + +If you prefer to build Nginx manually without Docker: + +```bash +# Install dependencies +sudo apt-get install -y build-essential libpcre3-dev zlib1g-dev libssl-dev libzstd-dev + +# Download Nginx source +wget http://nginx.org/download/nginx-1.26.0.tar.gz +tar -xzf nginx-1.26.0.tar.gz +cd nginx-1.26.0 + +# Configure with zstd module +./configure --prefix=/usr/local/nginx \ + --with-http_ssl_module \ + --with-http_v2_module \ + --add-module=/path/to/zstd-nginx-module + +# Build and install +make -j$(nproc) +sudo make install +``` + +## Testing Compression + +After setting up Nginx with zstd module, you can test compression: + +```bash +# Create a test HTML file +echo "

Hello World

$(yes 'Test content ' | head -1000)" > /usr/share/nginx/html/test.html + +# Request without compression +curl -H "Accept-Encoding:" http://localhost/test.html -o /tmp/uncompressed.html + +# Request with zstd compression +curl -H "Accept-Encoding: zstd" http://localhost/test.html --compressed -o /tmp/compressed.html + +# Compare sizes +ls -lh /tmp/uncompressed.html /tmp/compressed.html +``` + +## Advanced Configuration + +### Using Zstd Dictionary + +For even better compression ratios, you can use a pre-trained dictionary: + +```nginx +http { + # Specify dictionary file + zstd_dict_file /etc/nginx/zstd_dict.bin; + + # ... rest of configuration +} +``` + +**Warning**: Both client and server must use the same dictionary. Ensure clients support your dictionary before enabling this feature. + +### Static Pre-compressed Files + +To serve pre-compressed `.zst` files: + +```bash +# Pre-compress static files +zstd -k -19 /usr/share/nginx/html/large-file.js + +# This creates large-file.js.zst +``` + +Nginx will automatically serve the `.zst` version when `zstd_static on;` is configured and the client supports zstd encoding. + +## Performance Tips + +1. **Compression Level**: Use levels 1-3 for dynamic content, 10-19 for static files +2. **Minimum Length**: Set `zstd_min_length` to avoid compressing small files +3. **MIME Types**: Only compress compressible content types +4. **Static Pre-compression**: Pre-compress static assets at build time +5. **Buffer Size**: Adjust `zstd_buffers` based on your content size + +## Browser Support + +Zstd compression is supported by: +- Chrome/Edge 123+ +- Firefox 126+ +- Safari (partial support) + +Always include fallback compression methods (gzip, brotli) for broader compatibility. diff --git a/example/nginx.conf b/example/nginx.conf new file mode 100644 index 0000000..d12fcd1 --- /dev/null +++ b/example/nginx.conf @@ -0,0 +1,69 @@ +# Example Nginx Configuration with zstd-nginx-module + +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + 'zstd_ratio:$zstd_ratio'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + # Enable zstd compression globally + zstd on; + zstd_comp_level 3; + zstd_min_length 256; + zstd_types + text/plain + text/css + text/xml + text/javascript + application/json + application/javascript + application/xml+rss + application/rss+xml + application/atom+xml + image/svg+xml + application/x-font-ttf + application/x-font-opentype + application/vnd.ms-fontobject; + + server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + + # Enable zstd compression for this location + zstd on; + } + + location /static/ { + # Serve pre-compressed .zst files if they exist + zstd_static on; + root /usr/share/nginx/html; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +} From a2dc043a414c234c2310fe393f7f4cd9a8840f5c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:19:52 +0000 Subject: [PATCH 4/7] Fix YAML formatting in CI workflow Co-authored-by: tokers <10428333+tokers@users.noreply.github.com> --- .github/workflows/ci.yml | 373 ++++++++++++++++++++------------------- 1 file changed, 188 insertions(+), 185 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ff3f9c..ec9883e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ main, master ] + branches: [main, master] pull_request: - branches: [ main, master ] + branches: [main, master] workflow_dispatch: jobs: @@ -15,197 +15,200 @@ jobs: matrix: os: [ubuntu-20.04, ubuntu-22.04] nginx_version: ['1.24.0', '1.25.3', '1.26.0'] - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - build-essential \ - libpcre3 libpcre3-dev \ - zlib1g zlib1g-dev \ - libssl-dev \ - libzstd-dev \ - perl \ - cpanminus - - - name: Install Perl test dependencies - run: | - sudo cpanm --notest Test::Nginx - - - name: Cache nginx - id: cache-nginx - uses: actions/cache@v4 - with: - path: ~/nginx-${{ matrix.nginx_version }} - key: nginx-${{ matrix.nginx_version }}-${{ matrix.os }} - - - name: Download and extract nginx - if: steps.cache-nginx.outputs.cache-hit != 'true' - run: | - cd ~ - wget -q http://nginx.org/download/nginx-${{ matrix.nginx_version }}.tar.gz - tar -xzf nginx-${{ matrix.nginx_version }}.tar.gz - - - name: Configure and build nginx with zstd module - run: | - cd ~/nginx-${{ matrix.nginx_version }} - ./configure \ - --prefix=/tmp/nginx \ - --with-http_ssl_module \ - --with-http_v2_module \ - --add-module=${{ github.workspace }} - make -j$(nproc) - sudo make install - - - name: Add nginx to PATH - run: | - echo "/tmp/nginx/sbin" >> $GITHUB_PATH - - - name: Verify nginx installation - run: | - /tmp/nginx/sbin/nginx -V - - - name: Run tests - run: | - export PATH=/tmp/nginx/sbin:$PATH - cd ${{ github.workspace }} - prove -r t/ - env: - TEST_NGINX_BINARY: /tmp/nginx/sbin/nginx - build-docker: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Build test Dockerfile - run: | - cat > Dockerfile.test << 'EOF' - FROM nginx:1.26.0 AS builder - - # Install build dependencies - RUN apt-get update && apt-get install -y \ + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ build-essential \ - libpcre3-dev \ - zlib1g-dev \ + libpcre3 libpcre3-dev \ + zlib1g zlib1g-dev \ libssl-dev \ libzstd-dev \ - wget \ - && rm -rf /var/lib/apt/lists/* - - # Get nginx source - WORKDIR /build - RUN wget -q http://nginx.org/download/nginx-1.26.0.tar.gz && \ - tar -xzf nginx-1.26.0.tar.gz - - # Copy module source - COPY . /build/zstd-nginx-module - - # Build nginx with zstd module - WORKDIR /build/nginx-1.26.0 - RUN ./configure \ - --prefix=/etc/nginx \ - --sbin-path=/usr/sbin/nginx \ - --modules-path=/usr/lib/nginx/modules \ - --conf-path=/etc/nginx/nginx.conf \ - --error-log-path=/var/log/nginx/error.log \ - --http-log-path=/var/log/nginx/access.log \ - --pid-path=/var/run/nginx.pid \ - --lock-path=/var/run/nginx.lock \ - --http-client-body-temp-path=/var/cache/nginx/client_temp \ - --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ - --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ - --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ - --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ - --user=nginx \ - --group=nginx \ + perl \ + cpanminus + + - name: Install Perl test dependencies + run: | + sudo cpanm --notest Test::Nginx + + - name: Cache nginx + id: cache-nginx + uses: actions/cache@v4 + with: + path: ~/nginx-${{ matrix.nginx_version }} + key: nginx-${{ matrix.nginx_version }}-${{ matrix.os }} + + - name: Download and extract nginx + if: steps.cache-nginx.outputs.cache-hit != 'true' + run: | + cd ~ + NGINX_VERSION="${{ matrix.nginx_version }}" + wget -q "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" + tar -xzf "nginx-${NGINX_VERSION}.tar.gz" + + - name: Configure and build nginx with zstd module + run: | + cd ~/nginx-${{ matrix.nginx_version }} + ./configure \ + --prefix=/tmp/nginx \ --with-http_ssl_module \ - --with-http_realip_module \ - --with-http_addition_module \ - --with-http_sub_module \ - --with-http_dav_module \ - --with-http_flv_module \ - --with-http_mp4_module \ - --with-http_gunzip_module \ - --with-http_gzip_static_module \ - --with-http_random_index_module \ - --with-http_secure_link_module \ - --with-http_stub_status_module \ - --with-http_auth_request_module \ --with-http_v2_module \ - --with-http_slice_module \ - --with-threads \ - --with-file-aio \ - --add-module=/build/zstd-nginx-module && \ - make -j$(nproc) && \ - make install - - # Runtime stage - FROM nginx:1.26.0 - - # Install runtime dependencies - RUN apt-get update && apt-get install -y \ - libzstd1 \ - && rm -rf /var/lib/apt/lists/* - - # Copy compiled nginx with zstd module - COPY --from=builder /usr/sbin/nginx /usr/sbin/nginx - - # Test configuration - RUN nginx -V 2>&1 | grep zstd - - EXPOSE 80 443 - CMD ["nginx", "-g", "daemon off;"] - EOF - - - name: Build Docker image - run: | - docker build -f Dockerfile.test -t nginx-zstd:test . - - - name: Test Docker image - run: | - # Start container - docker run -d --name nginx-zstd-test nginx-zstd:test - sleep 2 - - # Check if nginx is running - docker ps | grep nginx-zstd-test - - # Check nginx version includes zstd - docker exec nginx-zstd-test nginx -V 2>&1 | grep zstd - - # Cleanup - docker stop nginx-zstd-test - docker rm nginx-zstd-test + --add-module=${{ github.workspace }} + make -j$(nproc) + sudo make install + + - name: Add nginx to PATH + run: | + echo "/tmp/nginx/sbin" >> $GITHUB_PATH + + - name: Verify nginx installation + run: | + /tmp/nginx/sbin/nginx -V + + - name: Run tests + run: | + export PATH=/tmp/nginx/sbin:$PATH + cd ${{ github.workspace }} + prove -r t/ + env: + TEST_NGINX_BINARY: /tmp/nginx/sbin/nginx + + build-docker: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build test Dockerfile + run: | + cat > Dockerfile.test << 'EOF' + FROM nginx:1.26.0 AS builder + + # Install build dependencies + RUN apt-get update && apt-get install -y \ + build-essential \ + libpcre3-dev \ + zlib1g-dev \ + libssl-dev \ + libzstd-dev \ + wget \ + && rm -rf /var/lib/apt/lists/* + + # Get nginx source + WORKDIR /build + RUN wget -q http://nginx.org/download/nginx-1.26.0.tar.gz && \ + tar -xzf nginx-1.26.0.tar.gz + + # Copy module source + COPY . /build/zstd-nginx-module + + # Build nginx with zstd module + WORKDIR /build/nginx-1.26.0 + RUN ./configure \ + --prefix=/etc/nginx \ + --sbin-path=/usr/sbin/nginx \ + --modules-path=/usr/lib/nginx/modules \ + --conf-path=/etc/nginx/nginx.conf \ + --error-log-path=/var/log/nginx/error.log \ + --http-log-path=/var/log/nginx/access.log \ + --pid-path=/var/run/nginx.pid \ + --lock-path=/var/run/nginx.lock \ + --http-client-body-temp-path=/var/cache/nginx/client_temp \ + --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ + --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ + --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ + --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ + --user=nginx \ + --group=nginx \ + --with-http_ssl_module \ + --with-http_realip_module \ + --with-http_addition_module \ + --with-http_sub_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_mp4_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_random_index_module \ + --with-http_secure_link_module \ + --with-http_stub_status_module \ + --with-http_auth_request_module \ + --with-http_v2_module \ + --with-http_slice_module \ + --with-threads \ + --with-file-aio \ + --add-module=/build/zstd-nginx-module && \ + make -j$(nproc) && \ + make install + + # Runtime stage + FROM nginx:1.26.0 + + # Install runtime dependencies + RUN apt-get update && apt-get install -y \ + libzstd1 \ + && rm -rf /var/lib/apt/lists/* + + # Copy compiled nginx with zstd module + COPY --from=builder /usr/sbin/nginx /usr/sbin/nginx + + # Test configuration + RUN nginx -V 2>&1 | grep zstd + + EXPOSE 80 443 + CMD ["nginx", "-g", "daemon off;"] + EOF + + - name: Build Docker image + run: | + docker build -f Dockerfile.test -t nginx-zstd:test . + + - name: Test Docker image + run: | + # Start container + docker run -d --name nginx-zstd-test nginx-zstd:test + sleep 2 + + # Check if nginx is running + docker ps | grep nginx-zstd-test + + # Check nginx version includes zstd + docker exec nginx-zstd-test nginx -V 2>&1 | grep zstd + + # Cleanup + docker stop nginx-zstd-test + docker rm nginx-zstd-test lint: runs-on: ubuntu-latest - + steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Check for trailing whitespace - run: | - if git grep -I --line-number -P '\s+$' -- '*.c' '*.h' 'config' 2>/dev/null; then - echo "Error: Found trailing whitespace" - exit 1 - else - echo "No trailing whitespace found" - fi - - - name: Check file permissions - run: | - # Check that source files don't have execute permissions - if find . -name '*.c' -o -name '*.h' | xargs ls -l | grep '^-rwxr'; then - echo "Error: Source files should not be executable" - exit 1 - else - echo "File permissions are correct" - fi + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check for trailing whitespace + run: | + if git grep -I --line-number -P '\s+$' -- '*.c' '*.h' 'config' \ + 2>/dev/null; then + echo "Error: Found trailing whitespace" + exit 1 + else + echo "No trailing whitespace found" + fi + + - name: Check file permissions + run: | + # Check that source files don't have execute permissions + if find . -name '*.c' -o -name '*.h' | xargs ls -l \ + | grep '^-rwxr'; then + echo "Error: Source files should not be executable" + exit 1 + else + echo "File permissions are correct" + fi From b33ebb12eafecc98fa38f4aef47e0620bea0c4ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:20:49 +0000 Subject: [PATCH 5/7] Add CI badge and Docker installation guide to README Co-authored-by: tokers <10428333+tokers@users.noreply.github.com> --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 6105896..846f350 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # Name + +[![CI](https://github.com/tokers/zstd-nginx-module/actions/workflows/ci.yml/badge.svg)](https://github.com/tokers/zstd-nginx-module/actions/workflows/ci.yml) + zstd-nginx-module - Nginx module for the [Zstandard compression](https://facebook.github.io/zstd/). # Table of Contents @@ -67,6 +70,17 @@ To use theses modules, configure your nginx branch with `--add-module=/path/to/z * System's zstd bundle will be linked if `ZSTD_INC` and `ZSTD_LIB` are not specified. * Both `ngx_http_zstd_static_module` and `ngx_http_zstd_filter_module` will be configured. +## Docker Installation + +A Dockerfile and example configuration are provided in the `example/` directory for easy containerized deployment: + +```bash +docker build -f example/Dockerfile -t nginx-zstd:latest . +docker run -d -p 80:80 nginx-zstd:latest +``` + +See the [example README](example/README.md) for more details on Docker deployment and configuration examples. + # Directives ## ngx_http_zstd_filter_module From c16956ba94e719fd95c6747a617849430bb2cf40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:22:28 +0000 Subject: [PATCH 6/7] Add CI/CD implementation documentation Co-authored-by: tokers <10428333+tokers@users.noreply.github.com> --- CI_CD_IMPLEMENTATION.md | 170 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 CI_CD_IMPLEMENTATION.md diff --git a/CI_CD_IMPLEMENTATION.md b/CI_CD_IMPLEMENTATION.md new file mode 100644 index 0000000..7d9e13c --- /dev/null +++ b/CI_CD_IMPLEMENTATION.md @@ -0,0 +1,170 @@ +# CI/CD Implementation Summary + +This document describes the CI/CD implementation for the zstd-nginx-module project. + +## Overview + +A comprehensive GitHub Actions CI/CD pipeline has been implemented to automatically build and test the zstd-nginx-module with various nginx versions and operating systems. + +## Workflow File + +Location: `.github/workflows/ci.yml` + +## CI/CD Features + +### 1. Test Job + +The main test job builds nginx with the zstd module and runs the test suite: + +**Matrix Testing:** +- **Operating Systems:** Ubuntu 20.04, Ubuntu 22.04 +- **Nginx Versions:** 1.24.0, 1.25.3, 1.26.0 +- **Total Combinations:** 6 test configurations + +**Steps:** +1. Checkout code +2. Install system dependencies (build tools, libzstd, perl, etc.) +3. Install Perl test dependencies (Test::Nginx) +4. Cache nginx source for faster builds +5. Download and extract nginx source (if not cached) +6. Configure nginx with zstd module using `--add-module` +7. Build nginx +8. Install nginx +9. Verify installation +10. Run test suite with `prove -r t/` + +### 2. Docker Build Job + +Tests building a Docker image with nginx and zstd module: + +**Steps:** +1. Creates a multi-stage Dockerfile for optimal image size +2. Builds nginx with zstd module in builder stage +3. Copies compiled binary to runtime stage +4. Verifies the module is properly integrated +5. Tests the container runs correctly + +### 3. Lint Job + +Performs basic code quality checks: + +**Checks:** +- Trailing whitespace in source files +- Incorrect file permissions on source files + +## Example Files + +Three example files have been added to help users: + +### 1. `example/nginx.conf` + +Complete nginx configuration demonstrating: +- Global zstd compression settings +- Compression level configuration +- Minimum length thresholds +- MIME type filtering +- Static pre-compressed file serving +- Compression ratio logging + +### 2. `example/Dockerfile` + +Production-ready multi-stage Dockerfile showing: +- How to build nginx with zstd module +- Proper dependency installation +- Optimized layer caching +- Runtime image preparation +- Health checks + +### 3. `example/README.md` + +Comprehensive documentation covering: +- Docker usage instructions +- Manual build process +- Configuration examples +- Testing compression +- Performance tips +- Browser compatibility notes + +## Documentation Updates + +### README.md + +Added: +- CI status badge showing workflow status +- Docker installation section with quick start +- Link to example documentation + +## Workflow Triggers + +The CI workflow runs on: +- Push to `main` or `master` branches +- Pull requests to `main` or `master` branches +- Manual workflow dispatch + +## Caching Strategy + +The workflow uses GitHub Actions cache to speed up builds: +- **Cached:** nginx source code by version and OS +- **Benefits:** Faster subsequent builds, reduced network usage + +## Testing + +The test suite uses the Test::Nginx framework which: +- Starts temporary nginx instances +- Tests module functionality +- Validates configuration options +- Ensures proper compression behavior + +## Status + +✅ CI/CD workflow created and validated +✅ YAML syntax verified with yamllint +✅ Example configurations provided +✅ Documentation updated +⏳ Workflow pending approval (common for new workflows) + +## Next Steps for Users + +1. **Repository Maintainer:** Approve the workflow run in GitHub Actions +2. **Review Results:** Check the workflow runs to ensure all tests pass +3. **Customize:** Adjust nginx versions or OS versions as needed +4. **Extend:** Add more test cases or additional checks + +## Maintenance + +To update the CI/CD: + +### Add a New Nginx Version + +Edit `.github/workflows/ci.yml`: +```yaml +matrix: + nginx_version: ['1.24.0', '1.25.3', '1.26.0', '1.27.0'] # Add new version +``` + +### Add a New OS Version + +Edit `.github/workflows/ci.yml`: +```yaml +matrix: + os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04] # Add new OS +``` + +### Add More Tests + +Add new test files to the `t/` directory following the Test::Nginx format. + +## Benefits + +1. **Automated Testing:** Every change is automatically tested +2. **Multi-Version Support:** Ensures compatibility across nginx versions +3. **Quality Assurance:** Catches build and test failures early +4. **Documentation:** Examples help users get started quickly +5. **Visibility:** CI badge shows project health at a glance + +## Resources + +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Test::Nginx Documentation](https://metacpan.org/pod/Test::Nginx::Socket) +- [Nginx Module Development](https://nginx.org/en/docs/dev/development_guide.html) +- [Zstandard Compression](https://facebook.github.io/zstd/) From c86652c96bc94d1f6aaf8b5986c9a146e4e178d7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:25:13 +0000 Subject: [PATCH 7/7] Add explicit GITHUB_TOKEN permissions for security Co-authored-by: tokers <10428333+tokers@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec9883e..3b1f51a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,9 @@ on: branches: [main, master] workflow_dispatch: +permissions: + contents: read + jobs: test: runs-on: ${{ matrix.os }}