Browse Source
Revert "Merge branch 'fix-ipv6-brackets-default-port' of https://github.com/seaweedfs/seaweedfs into fix-ipv6-brackets-default-port"
Revert "Merge branch 'fix-ipv6-brackets-default-port' of https://github.com/seaweedfs/seaweedfs into fix-ipv6-brackets-default-port"
This reverts commitpull/7414/headcca3f3985f, reversing changes made to2b8f9de78e.
3 changed files with 1 additions and 445 deletions
@ -1,353 +0,0 @@ |
|||||
# Nginx Reverse Proxy Configuration for SeaweedFS S3 API |
|
||||
|
|
||||
This guide explains how to properly configure nginx as a reverse proxy for SeaweedFS S3 API while maintaining AWS Signature V4 authentication compatibility. |
|
||||
|
|
||||
## The Challenge |
|
||||
|
|
||||
AWS Signature V4 authentication calculates a cryptographic signature based on the exact request including headers, URI, and body. When using nginx as a reverse proxy, any modification to the signed request components will cause signature verification to fail. |
|
||||
|
|
||||
## Critical Requirements |
|
||||
|
|
||||
1. **Preserve the Authorization header**: Must pass through untouched |
|
||||
2. **Preserve all X-Amz-* headers**: These are part of the signature calculation |
|
||||
3. **Preserve the Host header**: Use `$http_host` instead of `$host` to maintain the original port |
|
||||
4. **Do not modify the request URI**: Avoid path rewriting |
|
||||
5. **Disable buffering for chunked uploads**: Required for streaming uploads |
|
||||
6. **Preserve the request body**: Must not be modified |
|
||||
|
|
||||
## Recommended Nginx Configuration |
|
||||
|
|
||||
### Basic Configuration for S3 API |
|
||||
|
|
||||
```nginx |
|
||||
upstream seaweedfs_s3 { |
|
||||
server s3:8333; |
|
||||
keepalive 32; |
|
||||
} |
|
||||
|
|
||||
server { |
|
||||
listen 443 ssl http2; |
|
||||
server_name your-domain.com; |
|
||||
|
|
||||
# SSL Configuration |
|
||||
ssl_certificate /etc/nginx/certs/server.crt; |
|
||||
ssl_certificate_key /etc/nginx/certs/server.key; |
|
||||
|
|
||||
# Logging |
|
||||
access_log /var/log/nginx/s3-access.log; |
|
||||
error_log /var/log/nginx/s3-error.log; |
|
||||
|
|
||||
# Client upload limits |
|
||||
client_max_body_size 0; # No limit for S3 uploads |
|
||||
client_body_timeout 300s; |
|
||||
|
|
||||
# Disable buffering for AWS chunked uploads |
|
||||
proxy_buffering off; |
|
||||
proxy_request_buffering off; |
|
||||
|
|
||||
# HTTP version and connection settings |
|
||||
proxy_http_version 1.1; |
|
||||
proxy_set_header Connection ""; |
|
||||
|
|
||||
# Timeouts |
|
||||
proxy_connect_timeout 300s; |
|
||||
proxy_send_timeout 300s; |
|
||||
proxy_read_timeout 300s; |
|
||||
|
|
||||
location / { |
|
||||
proxy_pass http://seaweedfs_s3; |
|
||||
|
|
||||
# CRITICAL: Preserve original Host header including port |
|
||||
# Use $http_host instead of $host to preserve the port |
|
||||
proxy_set_header Host $http_host; |
|
||||
|
|
||||
# CRITICAL: Pass all headers through unchanged |
|
||||
# AWS Signature V4 includes these in signature calculation |
|
||||
proxy_pass_request_headers on; |
|
||||
|
|
||||
# Optional: Forward client IP information |
|
||||
# (These are NOT part of AWS signature) |
|
||||
proxy_set_header X-Real-IP $remote_addr; |
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
|
||||
proxy_set_header X-Forwarded-Proto $scheme; |
|
||||
|
|
||||
# CRITICAL: Do not modify request body |
|
||||
proxy_pass_request_body on; |
|
||||
|
|
||||
# Ignore invalid headers (S3 may send non-standard headers) |
|
||||
ignore_invalid_headers off; |
|
||||
} |
|
||||
|
|
||||
# Health check endpoint |
|
||||
location /health { |
|
||||
add_header Content-Type text/plain; |
|
||||
return 200 "OK\n"; |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### Configuration with mTLS Client Certificate Authentication |
|
||||
|
|
||||
If you need to add mTLS authentication **in addition to** S3 authentication: |
|
||||
|
|
||||
```nginx |
|
||||
upstream seaweedfs_s3 { |
|
||||
server s3:8333; |
|
||||
keepalive 32; |
|
||||
} |
|
||||
|
|
||||
server { |
|
||||
listen 443 ssl http2; |
|
||||
server_name your-domain.com; |
|
||||
|
|
||||
# SSL Configuration |
|
||||
ssl_certificate /etc/nginx/certs/server.crt; |
|
||||
ssl_certificate_key /etc/nginx/certs/server.key; |
|
||||
|
|
||||
# mTLS Configuration |
|
||||
ssl_client_certificate /etc/nginx/certs/ca.crt; |
|
||||
ssl_verify_client optional; # or 'on' to require client certificates |
|
||||
ssl_verify_depth 2; |
|
||||
|
|
||||
# Logging with mTLS info |
|
||||
log_format mtls '$remote_addr - $remote_user [$time_local] ' |
|
||||
'"$request" $status $body_bytes_sent ' |
|
||||
'verify=$ssl_client_verify dn="$ssl_client_s_dn"'; |
|
||||
|
|
||||
access_log /var/log/nginx/s3-mtls-access.log mtls; |
|
||||
error_log /var/log/nginx/s3-error.log; |
|
||||
|
|
||||
# Client upload limits |
|
||||
client_max_body_size 0; |
|
||||
client_body_timeout 300s; |
|
||||
|
|
||||
# Disable buffering for AWS chunked uploads |
|
||||
proxy_buffering off; |
|
||||
proxy_request_buffering off; |
|
||||
|
|
||||
# HTTP version and connection settings |
|
||||
proxy_http_version 1.1; |
|
||||
proxy_set_header Connection ""; |
|
||||
|
|
||||
# Timeouts |
|
||||
proxy_connect_timeout 300s; |
|
||||
proxy_send_timeout 300s; |
|
||||
proxy_read_timeout 300s; |
|
||||
|
|
||||
location / { |
|
||||
proxy_pass http://seaweedfs_s3; |
|
||||
|
|
||||
# CRITICAL: Preserve original Host header |
|
||||
proxy_set_header Host $http_host; |
|
||||
|
|
||||
# CRITICAL: Pass all headers through unchanged |
|
||||
proxy_pass_request_headers on; |
|
||||
|
|
||||
# Forward client IP information |
|
||||
proxy_set_header X-Real-IP $remote_addr; |
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
|
||||
proxy_set_header X-Forwarded-Proto $scheme; |
|
||||
|
|
||||
# Optional: Forward mTLS certificate info to backend |
|
||||
proxy_set_header X-SSL-Client-Verify $ssl_client_verify; |
|
||||
proxy_set_header X-SSL-Client-DN $ssl_client_s_dn; |
|
||||
|
|
||||
# CRITICAL: Do not modify request body |
|
||||
proxy_pass_request_body on; |
|
||||
|
|
||||
# Ignore invalid headers |
|
||||
ignore_invalid_headers off; |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## Common Mistakes to Avoid |
|
||||
|
|
||||
### ❌ DO NOT explicitly set AWS headers |
|
||||
|
|
||||
```nginx |
|
||||
# WRONG - Do not do this! |
|
||||
proxy_set_header Authorization $http_authorization; |
|
||||
proxy_set_header X-Amz-Date $http_x_amz_date; |
|
||||
proxy_set_header X-Amz-Content-Sha256 $http_x_amz_content_sha256; |
|
||||
``` |
|
||||
|
|
||||
**Why?** When you explicitly set headers, nginx may normalize or modify them. Use `proxy_pass_request_headers on` instead to pass ALL headers through unchanged. |
|
||||
|
|
||||
### ❌ DO NOT use `proxy_set_header Host $host` |
|
||||
|
|
||||
```nginx |
|
||||
# WRONG - Loses port information |
|
||||
proxy_set_header Host $host; |
|
||||
``` |
|
||||
|
|
||||
**Why?** `$host` contains only the hostname without the port. AWS Signature V4 includes the Host header with port in signature calculation. Use `$http_host` instead. |
|
||||
|
|
||||
### ❌ DO NOT enable request buffering for large uploads |
|
||||
|
|
||||
```nginx |
|
||||
# WRONG for S3 uploads |
|
||||
proxy_request_buffering on; |
|
||||
``` |
|
||||
|
|
||||
**Why?** This breaks AWS chunked transfer encoding used for large file uploads. Keep it off for S3 API endpoints. |
|
||||
|
|
||||
### ❌ DO NOT rewrite paths |
|
||||
|
|
||||
```nginx |
|
||||
# WRONG - Path rewriting breaks signature |
|
||||
location /s3/ { |
|
||||
rewrite ^/s3/(.*) /$1 break; |
|
||||
proxy_pass http://seaweedfs_s3; |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**Why?** The URI is part of the AWS Signature V4 calculation. Any path modification will cause signature verification to fail. |
|
||||
|
|
||||
## Testing Your Configuration |
|
||||
|
|
||||
### Test with AWS CLI |
|
||||
|
|
||||
```bash |
|
||||
# Configure AWS CLI |
|
||||
aws configure set aws_access_key_id your_access_key |
|
||||
aws configure set aws_secret_access_key your_secret_key |
|
||||
aws configure set region us-east-1 |
|
||||
|
|
||||
# Test through nginx proxy |
|
||||
aws s3 ls s3://your-bucket/ --endpoint-url https://your-nginx-domain |
|
||||
``` |
|
||||
|
|
||||
### Test with boto3 (Python) |
|
||||
|
|
||||
```python |
|
||||
import boto3 |
|
||||
|
|
||||
s3_client = boto3.client( |
|
||||
's3', |
|
||||
endpoint_url='https://your-nginx-domain', |
|
||||
aws_access_key_id='your_access_key', |
|
||||
aws_secret_access_key='your_secret_key', |
|
||||
region_name='us-east-1' |
|
||||
) |
|
||||
|
|
||||
# List buckets |
|
||||
response = s3_client.list_buckets() |
|
||||
print(response) |
|
||||
|
|
||||
# Upload a file |
|
||||
s3_client.upload_file('local_file.txt', 'bucket-name', 'remote_file.txt') |
|
||||
``` |
|
||||
|
|
||||
## Debugging |
|
||||
|
|
||||
### Enable detailed logging |
|
||||
|
|
||||
Add to your nginx configuration: |
|
||||
|
|
||||
```nginx |
|
||||
error_log /var/log/nginx/error_debug.log debug; |
|
||||
|
|
||||
log_format detailed '$remote_addr - $remote_user [$time_local] ' |
|
||||
'"$request" $status $body_bytes_sent ' |
|
||||
'"$http_authorization" "$http_x_amz_date" ' |
|
||||
'upstream="$upstream_addr" ' |
|
||||
'upstream_status=$upstream_status'; |
|
||||
|
|
||||
access_log /var/log/nginx/detailed.log detailed; |
|
||||
``` |
|
||||
|
|
||||
### Check SeaweedFS logs |
|
||||
|
|
||||
Look for authentication errors in SeaweedFS S3 logs: |
|
||||
- `could not find accessKey` - Access key not configured in SeaweedFS |
|
||||
- `signature mismatch` - Request was modified by proxy |
|
||||
- `InvalidAccessKeyId` - Access key doesn't exist |
|
||||
- `SignatureDoesNotMatch` - Signature calculation failed |
|
||||
|
|
||||
### Common Issues |
|
||||
|
|
||||
1. **"Could not find accessKey" error** |
|
||||
- Verify the access key exists in SeaweedFS: `weed shell` → `s3.configure.list` |
|
||||
- Check that Authorization header is being forwarded |
|
||||
- Verify SeaweedFS can read its configuration |
|
||||
|
|
||||
2. **"SignatureDoesNotMatch" error** |
|
||||
- Check if nginx is modifying headers or URI |
|
||||
- Verify `proxy_set_header Host $http_host` is used |
|
||||
- Disable any header manipulation |
|
||||
- Check for path rewriting rules |
|
||||
|
|
||||
3. **"RequestTimeTooSkewed" error** |
|
||||
- Ensure server clocks are synchronized (use NTP) |
|
||||
- Check timezone settings on both nginx and SeaweedFS servers |
|
||||
|
|
||||
## Performance Tuning |
|
||||
|
|
||||
For production deployments with high throughput: |
|
||||
|
|
||||
```nginx |
|
||||
upstream seaweedfs_s3 { |
|
||||
server s3:8333; |
|
||||
keepalive 64; # Increase keepalive connections |
|
||||
keepalive_timeout 90s; |
|
||||
keepalive_requests 10000; |
|
||||
} |
|
||||
|
|
||||
server { |
|
||||
# ... other config ... |
|
||||
|
|
||||
# Increase worker connections if needed |
|
||||
# (in nginx.conf, not server block) |
|
||||
# worker_connections 10000; |
|
||||
|
|
||||
# Enable caching for GET requests (optional) |
|
||||
proxy_cache_path /var/cache/nginx/s3 levels=1:2 keys_zone=s3_cache:10m |
|
||||
max_size=10g inactive=60m use_temp_path=off; |
|
||||
|
|
||||
location / { |
|
||||
# Only cache GET requests |
|
||||
proxy_cache s3_cache; |
|
||||
proxy_cache_methods GET HEAD; |
|
||||
proxy_cache_valid 200 60m; |
|
||||
proxy_cache_key "$scheme$request_method$host$request_uri"; |
|
||||
|
|
||||
# Don't cache authenticated requests by default |
|
||||
proxy_cache_bypass $http_authorization; |
|
||||
proxy_no_cache $http_authorization; |
|
||||
|
|
||||
# ... rest of proxy config ... |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## Docker Compose Example |
|
||||
|
|
||||
```yaml |
|
||||
version: '3' |
|
||||
|
|
||||
services: |
|
||||
seaweedfs-s3: |
|
||||
image: chrislusf/seaweedfs:latest |
|
||||
ports: |
|
||||
- "8333:8333" |
|
||||
command: 's3 -ip=0.0.0.0 -port=8333' |
|
||||
volumes: |
|
||||
- ./s3_config:/etc/seaweedfs |
|
||||
|
|
||||
nginx: |
|
||||
image: nginx:latest |
|
||||
ports: |
|
||||
- "443:443" |
|
||||
volumes: |
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro |
|
||||
- ./certs:/etc/nginx/certs:ro |
|
||||
depends_on: |
|
||||
- seaweedfs-s3 |
|
||||
``` |
|
||||
|
|
||||
## Additional Resources |
|
||||
|
|
||||
- [AWS Signature Version 4 Documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) |
|
||||
- [SeaweedFS S3 Configuration](https://github.com/seaweedfs/seaweedfs/wiki/Amazon-S3-API) |
|
||||
- [Nginx Proxy Module Documentation](https://nginx.org/en/docs/http/ngx_http_proxy_module.html) |
|
||||
@ -1,83 +0,0 @@ |
|||||
# Example nginx configuration for SeaweedFS S3 API reverse proxy |
|
||||
# See README.md in this directory for detailed explanation |
|
||||
|
|
||||
upstream seaweedfs_s3 { |
|
||||
# Point to your SeaweedFS S3 service |
|
||||
server s3:8333; |
|
||||
# For local development: server 127.0.0.1:8333; |
|
||||
|
|
||||
# Keep connections alive for better performance |
|
||||
keepalive 32; |
|
||||
} |
|
||||
|
|
||||
server { |
|
||||
listen 443 ssl http2; |
|
||||
server_name _; # Replace with your domain |
|
||||
|
|
||||
# SSL Configuration |
|
||||
ssl_certificate /etc/nginx/certs/server.crt; |
|
||||
ssl_certificate_key /etc/nginx/certs/server.key; |
|
||||
|
|
||||
# Optional: Client certificate authentication (mTLS) |
|
||||
# ssl_client_certificate /etc/nginx/certs/ca.crt; |
|
||||
# ssl_verify_client optional; |
|
||||
# ssl_verify_depth 2; |
|
||||
|
|
||||
# Logging |
|
||||
access_log /var/log/nginx/s3-access.log; |
|
||||
error_log /var/log/nginx/s3-error.log; |
|
||||
|
|
||||
# Client upload limits |
|
||||
client_max_body_size 0; # No limit for S3 uploads |
|
||||
client_body_timeout 300s; |
|
||||
|
|
||||
# CRITICAL: Disable buffering for AWS chunked uploads |
|
||||
proxy_buffering off; |
|
||||
proxy_request_buffering off; |
|
||||
|
|
||||
# HTTP version and connection settings |
|
||||
proxy_http_version 1.1; |
|
||||
proxy_set_header Connection ""; |
|
||||
|
|
||||
# Timeouts |
|
||||
proxy_connect_timeout 300s; |
|
||||
proxy_send_timeout 300s; |
|
||||
proxy_read_timeout 300s; |
|
||||
|
|
||||
location / { |
|
||||
proxy_pass http://seaweedfs_s3; |
|
||||
|
|
||||
# CRITICAL: Preserve original Host header including port |
|
||||
# Use $http_host instead of $host to preserve the port |
|
||||
proxy_set_header Host $http_host; |
|
||||
|
|
||||
# CRITICAL: Pass all headers through unchanged |
|
||||
# AWS Signature V4 includes these in signature calculation |
|
||||
proxy_pass_request_headers on; |
|
||||
|
|
||||
# Optional: Forward client IP information |
|
||||
# (These are NOT part of AWS signature) |
|
||||
proxy_set_header X-Real-IP $remote_addr; |
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
|
||||
proxy_set_header X-Forwarded-Proto $scheme; |
|
||||
|
|
||||
# CRITICAL: Do not modify request body |
|
||||
proxy_pass_request_body on; |
|
||||
|
|
||||
# Ignore invalid headers (S3 may send non-standard headers) |
|
||||
ignore_invalid_headers off; |
|
||||
} |
|
||||
|
|
||||
# Health check endpoint |
|
||||
location /health { |
|
||||
return 200 "OK\n"; |
|
||||
add_header Content-Type text/plain; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
# Optional: HTTP to HTTPS redirect |
|
||||
server { |
|
||||
listen 80; |
|
||||
server_name _; |
|
||||
return 301 https://$host$request_uri; |
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue