How to use Nginx to proxy your S3 files

  • Proxy cache to leverage browser caching
  • URLs masking that helps a lot in case you change cloud provider later
  • Speed up transferring by offload SSL/TLS

Inspect AWS S3 response headers

$ curl -I https://ucodevn.s3-ap-southeast-1.amazonaws.com/image_restored/1867/courses/42/17773/id365442.png
HTTP/1.1 200 OK
x-amz-id-2: C8uQhUZqP8hZ3hACa3fFbG6l29kXYq/VS+i5otl9DNRHAHM4wnM+28Yk4LzDt9L/Q8OuMbLGeX4=
x-amz-request-id: 4A0191D9383DE48B
Date: Sun, 18 Oct 2020 01:47:31 GMT
Last-Modified: Mon, 27 Jul 2020 07:48:22 GMT
ETag: "356b5d3ba55b3f00bd30b071e298c5fe"
Accept-Ranges: bytes
Content-Type: image/png
Content-Length: 7481
Server: AmazonS3
$ curl -I  https://ucodevn.s3-ap-southeast-1.amazonaws.com/image_restored/1867/courses/42/17773/id365442.png --header "If-None-Match: 356b5d3ba55b3f00bd30b071e298c5fe"
HTTP/1.1 304 Not Modified
x-amz-id-2: 3HoshGpkZODJGCObVCv37r95mX2JI01A/CI9S7Kqj8uquI8GuNELi+a/1D0G7Sfu/GsTfiulT1U=
x-amz-request-id: 9C4B0A7CFF6107BB
Date: Sun, 18 Oct 2020 01:49:22 GMT
Last-Modified: Mon, 27 Jul 2020 07:48:22 GMT
ETag: "356b5d3ba55b3f00bd30b071e298c5fe"
Server: AmazonS3
$ curl -I  https://ucodevn.s3-ap-southeast-1.amazonaws.com/image_restored/1867/courses/42/17773/id365442.png --header "If-Modified-Since: Mon, 27 Jul 2020 07:48:22 GMT"
HTTP/1.1 304 Not Modified
x-amz-id-2: 2JuMRfdvkgnL8O5J07H4H5J4U7D7h7KOMHfzkDuqGiUIREduB39gFc6fIxgWm+419M564IsR2pY=
x-amz-request-id: 80E743CCBC58B5DC
Date: Sun, 18 Oct 2020 01:51:45 GMT
Last-Modified: Mon, 27 Jul 2020 07:48:22 GMT
ETag: "356b5d3ba55b3f00bd30b071e298c5fe"
Server: AmazonS3
Connection: close

Proxy using Nginx

server {
listen 80;
listen 443 ssl;
server_name statics.yourside.com;
access_log /var/log/nginx/statics.access.log combined;
error_log /var/log/nginx/statics.error.log;
set $bucket "ucodevn.s3-ap-southeast-1.amazonaws.com";
sendfile on;
location / {
resolver 8.8.8.8;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Connection "";
proxy_set_header Authorization '';
proxy_set_header Host $bucket;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
proxy_intercept_errors on;
add_header Cache-Control max-age=31536000;
proxy_pass https://$bucket; # without trailing slash
}
}
$ sudo nginx -t
$ sudo service nginx restart
$ curl -I -k https://statics.yourside.com/{path_to_your_file}
$ curl -I -k https://cdn.ucode.vn/image_restored/1867/courses/42/17773/id365442.png
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 18 Oct 2020 02:11:57 GMT
Content-Type: image/png
Content-Length: 7481
Connection: keep-alive
Last-Modified: Mon, 27 Jul 2020 07:48:22 GMT
ETag: "356b5d3ba55b3f00bd30b071e298c5fe"
Accept-Ranges: bytes
Cache-Control: max-age=31536000
Nginx proxy without cache
$ curl -I -k https://cdn.ucode.vn/image_restored/1867/courses/42/17773/id365442.png --header "If-None-Match: 356b5d3ba55b3f00bd30b071e298c5fe"
HTTP/1.1 304 Not Modified
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 18 Oct 2020 02:24:46 GMT
Connection: keep-alive
Last-Modified: Mon, 27 Jul 2020 07:48:22 GMT
ETag: "356b5d3ba55b3f00bd30b071e298c5fe"
Cache-Control: max-age=31536000
Proxy request with Condition GET

Proxy using Nginx with proxy cache

proxy_cache_path   /tmp/ levels=1:2 keys_zone=s3_cache:10m max_size=500m inactive=60m use_temp_path=off;server {
listen 80;
listen 443 ssl;
server_name cdn.ucode.vn;
access_log /var/log/nginx/ucode-cdn.access.log combined;
error_log /var/log/nginx/ucode-cdn.error.log;
set $bucket "ucodevn.s3-ap-southeast-1.amazonaws.com";
sendfile on;
# This configuration uses a 60 minute cache for files requested:
location ^~ /cached/ {
rewrite /cached(.*) $1 break;
resolver 8.8.8.8;
proxy_cache s3_cache;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Connection "";
proxy_set_header Authorization '';
proxy_set_header Host $bucket;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
proxy_cache_revalidate on;
proxy_intercept_errors on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
proxy_cache_valid 200 304 60m;
add_header Cache-Control max-age=31536000;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass https://$bucket; # without trailing slash
}
# This configuration provides direct access to the Object Storage bucket:
location / {
resolver 8.8.8.8;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Connection "";
proxy_set_header Authorization '';
proxy_set_header Host $bucket;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
proxy_intercept_errors on;
add_header Cache-Control max-age=31536000;
proxy_pass https://$bucket;
}
}
$ curl -I -k https://cdn.ucode.vn/cached/image_restored/1867/courses/42/17773/
id365442.png --header "If-None-Match: 356b5d3ba55b3f00bd30b071e298c5fe"
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 18 Oct 2020 03:11:17 GMT
Content-Type: image/png
Content-Length: 7481
Connection: keep-alive
Last-Modified: Mon, 27 Jul 2020 07:48:22 GMT
ETag: "356b5d3ba55b3f00bd30b071e298c5fe"
Cache-Control: max-age=31536000
X-Cache-Status: MISS
Accept-Ranges: bytes
$ curl -I -k https://cdn.ucode.vn/cached/image_restored/1867/courses/42/17773/
id365442.png --header "If-None-Match: 356b5d3ba55b3f00bd30b071e298c5fe"
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 18 Oct 2020 03:14:19 GMT
Content-Type: image/png
Content-Length: 7481
Connection: keep-alive
Last-Modified: Mon, 27 Jul 2020 07:48:22 GMT
ETag: "356b5d3ba55b3f00bd30b071e298c5fe"
Cache-Control: max-age=31536000
X-Cache-Status: HIT
Accept-Ranges: bytes
Proxy cache HIT
  • proxy_cache_revalidate instructs NGINX to use conditional GET requests when refreshing content from the origin servers
  • the updating parameter to the proxy_cache_use_stale directive instructs NGINX to deliver stale content when clients request an item while an update to it is being downloaded from the origin server, instead of forwarding repeated requests to the server
  • with proxy_cache_lock enabled, if multiple clients request a file that is not currently in the cache (a MISS), only the first of those requests is allowed through to the origin server.

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Socket programming in Ruby

A new beginning!

Setting up a Linux computer to analyse NGS data/find SNPs

Upload Your First Android App on Play Store(Step-by-Step):

Cloud Foundry Advisory Board Meeting, Aug 2020: cf-for-k8s 0.5 and Stratos 4.0

Proposing an Open Camera Positioning Standard

Stop Using Branches for Deploying to Different GitOps Environments

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Chi Thuc Nguyen

Chi Thuc Nguyen

More from Medium

TWIL: Deploying Node.js to Azure App Service with GitHub Actions

AWS CloudFormation Template to Build dotnet6.0 projects

AWS CodeBuild

Connect Docker with Kafka/Postgresql/Cassandra

Kafka , Postgresql , Cassandra inside Docker Container

Authentication — the bare minimum