|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +NGINX S3 Gateway is a containerized NGINX configuration that acts as an authenticating and caching gateway to AWS S3 or S3-compatible services. It uses NGINX with NJS (NGINX JavaScript) modules to implement AWS Signature v2/v4 authentication. |
| 8 | + |
| 9 | +## Architecture |
| 10 | + |
| 11 | +### Directory Structure |
| 12 | + |
| 13 | +- `common/` - Shared configuration files for both OSS and Plus |
| 14 | + - `etc/nginx/include/s3gateway.js` - Core NJS module implementing S3 authentication (AWS Sig v2/v4) |
| 15 | + - `etc/nginx/templates/` - NGINX config templates processed by Docker entrypoint |
| 16 | + - `docker-entrypoint.sh` - Main entrypoint script that processes templates with env vars |
| 17 | +- `oss/` - NGINX OSS-specific configs |
| 18 | +- `plus/` - NGINX Plus-specific configs with advanced caching features |
| 19 | +- `test/` - Testing infrastructure |
| 20 | + - `unit/` - NJS unit tests |
| 21 | + - `integration/` - Integration tests against Minio |
| 22 | +- `examples/` - Extension examples (brotli, gzip, modsecurity) |
| 23 | +- `deployments/` - CloudFormation and ECS deployment configs |
| 24 | + |
| 25 | +### Key Components |
| 26 | + |
| 27 | +**S3 Gateway NJS Module** (`common/etc/nginx/include/s3gateway.js`): |
| 28 | +- Implements AWS Signature v2 and v4 signing algorithms |
| 29 | +- Handles credential retrieval from environment or EC2/ECS instance metadata |
| 30 | +- Provides functions called from NGINX config to sign S3 requests |
| 31 | +- Supports directory listing via XSL transformation |
| 32 | +- Static site hosting with index.html transformation |
| 33 | + |
| 34 | +**NGINX Configuration Flow**: |
| 35 | +1. `nginx.conf` - Main config loading NJS modules and preserving env vars |
| 36 | +2. `templates/default.conf.template` - Server block with S3 proxy configuration |
| 37 | +3. `templates/gateway/v{2,4}_*.conf.template` - Version-specific signing configs |
| 38 | +4. Templates are processed by entrypoint, substituting environment variables |
| 39 | + |
| 40 | +**Docker Entrypoint**: |
| 41 | +- Validates required environment variables |
| 42 | +- Sets DNS resolvers dynamically |
| 43 | +- Processes `.template` files to generate final NGINX configs |
| 44 | + |
| 45 | +## Build and Test Commands |
| 46 | + |
| 47 | +### Building |
| 48 | + |
| 49 | +```bash |
| 50 | +# Build NGINX OSS version |
| 51 | +docker build -f Dockerfile.oss --tag nginx-s3-gateway:oss . |
| 52 | + |
| 53 | +# Build NGINX Plus version (requires nginx-repo.crt/key in plus/etc/ssl/nginx/) |
| 54 | +DOCKER_BUILDKIT=1 docker build -f Dockerfile.buildkit.plus \ |
| 55 | + --secret id=nginx-crt,src=plus/etc/ssl/nginx/nginx-repo.crt \ |
| 56 | + --secret id=nginx-key,src=plus/etc/ssl/nginx/nginx-repo.key \ |
| 57 | + --tag nginx-plus-s3-gateway:plus . |
| 58 | + |
| 59 | +# Build with latest NJS from source |
| 60 | +docker build -f Dockerfile.latest-njs --tag nginx-s3-gateway:latest-njs-oss . |
| 61 | +``` |
| 62 | + |
| 63 | +### Testing |
| 64 | + |
| 65 | +```bash |
| 66 | +# Run all tests (unit + integration) for NGINX OSS |
| 67 | +./test.sh oss |
| 68 | + |
| 69 | +# Test with latest NJS |
| 70 | +./test.sh latest-njs-oss |
| 71 | + |
| 72 | +# Test NGINX Plus |
| 73 | +./test.sh plus |
| 74 | + |
| 75 | +# Run only unit tests |
| 76 | +docker run --rm -v "$(pwd)/test/unit:/var/tmp" --workdir /var/tmp \ |
| 77 | + -e S3_BUCKET_NAME=test -e S3_SERVER=test -e S3_REGION=test \ |
| 78 | + -e AWS_SIGS_VERSION=4 --entrypoint /usr/bin/njs \ |
| 79 | + nginx-s3-gateway -t module -p '/etc/nginx' /var/tmp/s3gateway_test.js |
| 80 | +``` |
| 81 | + |
| 82 | +**Test Dependencies**: docker, docker-compose, curl, md5sum, wait-for-it (optional) |
| 83 | + |
| 84 | +**Test Workflow**: |
| 85 | +- `test.sh` builds Docker image, runs unit tests via NJS, then starts docker-compose with Minio |
| 86 | +- Integration tests verify AWS Sig v2/v4, directory listing, index pages, and slash appending |
| 87 | +- Tests run against local Minio server (http://localhost:9090) |
| 88 | + |
| 89 | +### Running |
| 90 | + |
| 91 | +```bash |
| 92 | +# Run with environment file |
| 93 | +docker run --env-file ./settings --publish 80:80 nginx-s3-gateway:oss |
| 94 | + |
| 95 | +# Required environment variables (see settings.example): |
| 96 | +# S3_BUCKET_NAME, S3_ACCESS_KEY_ID, S3_SECRET_KEY, S3_SERVER, |
| 97 | +# S3_SERVER_PORT, S3_SERVER_PROTO, S3_REGION, AWS_SIGS_VERSION, S3_STYLE |
| 98 | +``` |
| 99 | + |
| 100 | +## Configuration System |
| 101 | + |
| 102 | +All configuration is via environment variables (see `settings.example`): |
| 103 | + |
| 104 | +**Core S3 Settings**: |
| 105 | +- `AWS_SIGS_VERSION` - Set to 2 or 4 for signature version |
| 106 | +- `S3_STYLE` - `virtual` (DNS-style bucket.host) or `path` (host/bucket/) |
| 107 | +- `S3_ACCESS_KEY_ID` / `S3_SECRET_KEY` - Omit to use instance profile credentials |
| 108 | + |
| 109 | +**Feature Flags**: |
| 110 | +- `ALLOW_DIRECTORY_LIST` - Enable S3 directory listing |
| 111 | +- `PROVIDE_INDEX_PAGE` - Transform `/path/` to `/path/index.html` |
| 112 | +- `APPEND_SLASH_FOR_POSSIBLE_DIRECTORY` - 302 redirect to add trailing slash |
| 113 | + |
| 114 | +**Caching**: |
| 115 | +- `PROXY_CACHE_VALID_OK`, `PROXY_CACHE_VALID_NOTFOUND`, `PROXY_CACHE_VALID_FORBIDDEN` |
| 116 | + |
| 117 | +Environment variables are preserved via `env` directives in `nginx.conf` and accessed in NJS via `process.env`. |
| 118 | + |
| 119 | +## Development Patterns |
| 120 | + |
| 121 | +### Adding New Features |
| 122 | + |
| 123 | +1. Modify `common/etc/nginx/include/s3gateway.js` for NJS logic changes |
| 124 | +2. Update `common/etc/nginx/templates/*.template` for NGINX config changes |
| 125 | +3. Add unit tests to `test/unit/s3gateway_test.js` |
| 126 | +4. Add integration tests to `test/integration/test_api.sh` |
| 127 | +5. Update both OSS and Plus configs if behavior differs |
| 128 | + |
| 129 | +### AWS Signature Implementation |
| 130 | + |
| 131 | +The gateway signs requests to S3 in NJS before proxying: |
| 132 | +- Credentials from env vars or fetched from EC2/ECS metadata endpoints |
| 133 | +- HMAC-SHA256 signing using `crypto` module |
| 134 | +- Signature inserted as `Authorization` header or query parameters (v2 style) |
| 135 | +- Requests proxied to S3 via upstream defined in templates |
| 136 | + |
| 137 | +### Instance Profile Credentials |
| 138 | + |
| 139 | +When `S3_ACCESS_KEY_ID`/`S3_SECRET_KEY` are omitted: |
| 140 | +- Gateway queries EC2 metadata API (169.254.169.254) or ECS credentials endpoint |
| 141 | +- Credentials cached in NGINX Plus via `keyval_zone` or fetched per-request in OSS |
| 142 | +- Must set `http-put-response-hop-limit 3` when running in containers on EC2 |
0 commit comments