Skip to content

Commit d87266f

Browse files
committed
Cache docs
1 parent 4f4c6c5 commit d87266f

File tree

11 files changed

+555
-124
lines changed

11 files changed

+555
-124
lines changed

docs/cache/external.mdx

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
---
2+
description: External cache options for imgproxy including CDNs, nginx, and Varnish
3+
---
4+
5+
# External cache
6+
7+
External cache refers to caching layers in front of imgproxy, such as CDNs, reverse proxies, or caching appliances. These solutions provide edge caching, geo-distribution, and high-performance image delivery.
8+
9+
## CDN options
10+
11+
Most major CDNs (Cloudflare, Fastly, AWS CloudFront, Akamai, etc.) can cache imgproxy responses:
12+
13+
### Recommended CDN settings
14+
15+
* **Origin shield** - Add a secondary cache layer between your CDN and imgproxy origin
16+
* **Image optimization** - Disable CDN image optimization to avoid double-processing
17+
* **Compression** - Enable gzip/Brotli compression for bandwidth savings
18+
* **HTTP/2 Server Push** - Push critical images to reduce latency
19+
20+
## nginx caching
21+
22+
nginx can act as a reverse proxy cache in front of imgproxy:
23+
24+
```nginx
25+
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=imgproxy_cache:10m max_size=50g inactive=30d;
26+
27+
upstream imgproxy {
28+
server localhost:8080;
29+
}
30+
31+
server {
32+
listen 80;
33+
server_name images.example.com;
34+
35+
# Include request and feature signals that can change imgproxy output
36+
proxy_cache_key "$scheme$request_method$host$request_uri:accept=$http_accept:dpr=$http_dpr:width=$http_width:chdpr=$http_sec_ch_dpr:chwidth=$http_sec_ch_width";
37+
38+
location / {
39+
proxy_pass http://imgproxy;
40+
41+
# Cache configuration
42+
proxy_cache imgproxy_cache;
43+
proxy_cache_valid 200 24h;
44+
proxy_cache_valid 304 24h;
45+
proxy_cache_valid 404 1m;
46+
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
47+
proxy_cache_background_update on;
48+
proxy_cache_lock on;
49+
proxy_cache_bypass $http_pragma $http_authorization;
50+
proxy_no_cache $http_pragma $http_authorization;
51+
52+
# Add cache status header for debugging
53+
add_header X-Cache-Status $upstream_cache_status;
54+
}
55+
}
56+
```
57+
58+
### Possible cache key setup
59+
60+
The exact key depends on which imgproxy features can change output for the same URL.
61+
62+
1. Basic key when output depends only on URL/path options:
63+
64+
```nginx
65+
proxy_cache_key "$scheme$proxy_host$request_uri";
66+
```
67+
68+
2. Include format negotiation signal when WebP/AVIF/JXL preference can vary by client:
69+
70+
```nginx
71+
proxy_cache_key "$scheme$proxy_host$request_uri$http_accept";
72+
```
73+
74+
3. Include Client Hints dimensions when width/DPR affect output:
75+
76+
```nginx
77+
proxy_cache_key "$scheme$request_method$host$request_uri:accept=$http_accept:dpr=$http_dpr:width=$http_width:chdpr=$http_sec_ch_dpr:chwidth=$http_sec_ch_width";
78+
```
79+
80+
Use the smallest key that still prevents collisions for your traffic profile.
81+
82+
### Key recommendations
83+
84+
* Include `Accept` in the cache key if format negotiation is used
85+
* Include DPR/width-related hints in the cache key if Client Hints are used to vary output
86+
* Set long `inactive` timeout (30d) to keep popular images in cache
87+
* Configure `proxy_cache_use_stale` for graceful degradation during origin issues
88+
* Monitor `/proc/sys/fs/file-max` and increase if needed for large caches
89+
* Use separate cache zones for different image types if needed
90+
91+
## Varnish caching
92+
93+
Varnish is a powerful reverse proxy cache optimized for HTTP performance:
94+
95+
```vcl
96+
vcl 4.1;
97+
98+
backend imgproxy {
99+
.host = "localhost";
100+
.port = "8080";
101+
.connect_timeout = 600ms;
102+
.first_byte_timeout = 600s;
103+
.between_bytes_timeout = 60s;
104+
}
105+
106+
sub vcl_recv {
107+
set req.backend_hint = imgproxy;
108+
109+
# Cache only GET and HEAD requests
110+
if (req.method != "GET" && req.method != "HEAD") {
111+
return (pass);
112+
}
113+
114+
# Include important headers in cache key
115+
if (req.http.Accept) {
116+
set req.http.X-Accept = req.http.Accept;
117+
}
118+
119+
# Keep DPR if Client Hints are not enabled
120+
if (req.http.DPR) {
121+
set req.http.X-DPR = req.http.DPR;
122+
}
123+
124+
if (req.http.Width) {
125+
set req.http.X-Width = req.http.Width;
126+
}
127+
128+
if (req.http.Sec-CH-DPR) {
129+
set req.http.X-CH-DPR = req.http.Sec-CH-DPR;
130+
}
131+
132+
if (req.http.Sec-CH-Width) {
133+
set req.http.X-CH-Width = req.http.Sec-CH-Width;
134+
}
135+
}
136+
137+
sub vcl_hash {
138+
# Base hash
139+
hash_data(req.url);
140+
hash_data(req.http.Host);
141+
142+
# Include Accept header for format negotiation
143+
if (req.http.X-Accept) {
144+
hash_data(req.http.X-Accept);
145+
}
146+
147+
# Include DPR if present
148+
if (req.http.X-DPR) {
149+
hash_data(req.http.X-DPR);
150+
}
151+
152+
if (req.http.X-Width) {
153+
hash_data(req.http.X-Width);
154+
}
155+
156+
if (req.http.X-CH-DPR) {
157+
hash_data(req.http.X-CH-DPR);
158+
}
159+
160+
if (req.http.X-CH-Width) {
161+
hash_data(req.http.X-CH-Width);
162+
}
163+
}
164+
165+
sub vcl_backend_response {
166+
# Cache successful responses for 24 hours
167+
if (beresp.status == 200) {
168+
set beresp.ttl = 24h;
169+
set beresp.keep = 24h;
170+
}
171+
172+
# Cache 404s for a short period
173+
if (beresp.status == 404) {
174+
set beresp.ttl = 1m;
175+
}
176+
177+
# Enable cache using stale object if backend is down
178+
set beresp.grace = 24h;
179+
}
180+
181+
sub vcl_deliver {
182+
# Add cache hit/miss header
183+
if (obj.hits > 0) {
184+
set resp.http.X-Cache = "HIT";
185+
set resp.http.X-Cache-Hits = obj.hits;
186+
} else {
187+
set resp.http.X-Cache = "MISS";
188+
}
189+
}
190+
```
191+
192+
### Key recommendations
193+
194+
* Use `sub vcl_hash` to customize cache key behavior
195+
* Include `Accept` for format negotiation
196+
* Include DPR/width-related headers when they can affect output (`DPR`, `Width`, `Sec-CH-DPR`, `Sec-CH-Width`)
197+
* Set grace period (`beresp.grace`) for graceful error handling
198+
* Monitor Varnish statistics with `varnishstat`
199+
* Use tags for efficient cache purging: add `set beresp.http.Surrogate-Key = "images:product:123"` in `vcl_backend_response`
200+
* Configure workspace limits if caching many large images
201+
202+
## Cache headers from imgproxy
203+
204+
imgproxy sends the following headers useful for external caching:
205+
206+
* `Cache-Control: public, max-age=31536000` - Long-term caching (1 year default, configurable with `IMGPROXY_TTL`)
207+
* `ETag` - If `IMGPROXY_USE_ETAG=true` (by default), enables conditional requests
208+
* `Last-Modified` - If `IMGPROXY_USE_LAST_MODIFIED=true` (by default), enables conditional requests
209+
* `Content-Type` - Important for cache key if not in `Accept` header

docs/cache/internal.mdx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
title: Internal cache
3+
description: Learn about how to configure and use imgproxy's internal cache
4+
---
5+
6+
# Internal cache ((pro))
7+
8+
imgproxy Pro provides an internal cache that stores processed images on disk or in cloud storage. This cache can act as both a primary cache and a secondary cache that serves as a fallback when your CDN cache misses.
9+
10+
:::tip
11+
While putting a CDN in front of imgproxy is and will always be a best practice, the internal cache provides long-term storage for cases that require an additional caching layer.
12+
:::
13+
14+
## Why use internal cache?
15+
16+
The internal cache provides long-term persistent storage for processed images, unlike CDNs that typically delete rarely accessed content. It stores images in a single location rather than across multiple edge stores, eliminating cache misses when requests hit different edges. The cache is designed specifically for imgproxy, working seamlessly with features like modern image format detection and client hints support that generic external caches don't understand.
17+
18+
The cache is protected by the same security measures as imgproxy itself, including URL signatures and processing restrictions. Importantly, URL signatures are not part of the cache key, so you can rotate keys or use multiple key/salt pairs without invalidating cached images. You maintain full control over where the cache is stored and how it integrates with your infrastructure.
19+
20+
## Configuration
21+
22+
You need to define the following config variables to enable the internal cache:
23+
24+
* [`IMGPROXY_CACHE_USE`]: the cache storage adapter to use. Can be `filesystem`, `s3`, `gcs`, `abs` (Azure Blob Storage), or `swift`. When blank, the cache is disabled. Default: blank
25+
* [`IMGPROXY_CACHE_PATH_PREFIX`]: _(optional)_ a path prefix for the cache files. This can be useful to organize cache files in a specific directory structure. Default: blank
26+
* [`IMGPROXY_CACHE_BUCKET`]: _(optional)_ the bucket name for cloud storage adapters (S3, GCS, ABS, Swift). When using filesystem adapter, this can be used as an additional path component. Default: blank
27+
* [`IMGPROXY_CACHE_KEY_HEADERS`]: _(optional)_ a list of HTTP request headers (comma-separated) to include in the cache key. This allows caching different versions of the same image based on request headers. Default: blank
28+
* [`IMGPROXY_CACHE_KEY_COOKIES`]: _(optional)_ a list of HTTP request cookies (comma-separated) to include in the cache key. This allows caching different versions of the same image based on cookies. Default: blank
29+
* [`IMGPROXY_CACHE_REPORT_ERRORS`]: when `true`, imgproxy will report cache errors instead of silently falling back to processing without cache. Default: `false`
30+
31+
### Storage configuration
32+
33+
The internal cache supports all the storage backends that imgproxy can read source images from: local filesystem, Amazon S3 and compatible services (Cloudflare R2, DigitalOcean Spaces, MinIO, etc.), Google Cloud Storage, Microsoft Azure Blob Storage, and OpenStack Swift.
34+
35+
Configure the storage backend using `IMGPROXY_CACHE_*` variables:
36+
37+
* For filesystem cache, see [Cache storage: Local filesystem](./internal/local_filesystem.mdx)
38+
* For S3 cache, see [Cache storage: Amazon S3](./internal/amazon_s3.mdx)
39+
* For GCS cache, see [Cache storage: Google Cloud Storage](./internal/google_cloud_storage.mdx)
40+
* For Azure Blob Storage cache, see [Cache storage: Azure Blob Storage](./internal/azure_blob_storage.mdx)
41+
* For Swift cache, see [Cache storage: OpenStack Object Storage ("Swift")](./internal/openstack_swift.mdx)
42+
43+
## Cache key
44+
45+
The cache key is generated based on:
46+
47+
* Source image URL
48+
* Processing options
49+
* Output format
50+
* Optional: Request headers specified in `IMGPROXY_CACHE_KEY_HEADERS`
51+
* Optional: Request cookies specified in `IMGPROXY_CACHE_KEY_COOKIES`
52+
53+
URL signature is **not** a part of the cache key, which allows key rotation without invalidating the cache.
54+
55+
## Limitations
56+
57+
* **No manual cache invalidation**: Currently, imgproxy doesn't provide built-in means to invalidate the cache. However, imgproxy includes the [cachebuster](../usage/processing.mdx#cache-buster) in the cache key, so you can use it to force cache invalidation when needed. Most storage offerings also support object expiration, so you can set a reasonable expiration time for cached images.
58+
* **No cache for info requests**: The internal cache is currently only used for image processing requests. Requests to the `/info` endpoint are not cached.
59+
60+
## How it works
61+
62+
When a request comes in:
63+
64+
1. imgproxy checks the URL signature (if enabled)
65+
2. imgproxy generates the cache key from the request parameters
66+
3. imgproxy checks if a cached image exists in the configured storage
67+
4. If the cached image exists and is valid, imgproxy serves it directly
68+
5. If not, imgproxy processes the image and stores the result in the cache before serving it
69+
70+
## Monitoring
71+
72+
Monitor cache performance with metrics:
73+
74+
* Cache hit rate
75+
* Cache size
76+
* Cache evictions
77+
* Cache latency
78+
79+
These metrics are available through [monitoring endpoints](../monitoring/prometheus.mdx).

docs/cache/internal/amazon_s3.mdx

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
description: Learn about how to configure Amazon S3 cache in imgproxy
3+
---
4+
5+
# Cache storage: Amazon S3
6+
7+
imgproxy can store cached images in Amazon S3 buckets or S3-compatible storage. To use S3 cache, do the following:
8+
9+
1. Set `IMGPROXY_CACHE_USE` environment variable to `s3`.
10+
2. [Set up the necessary credentials](#set-up-credentials) to grant access to your cache bucket.
11+
3. _(optional)_ Specify the AWS region with `IMGPROXY_CACHE_S3_REGION`. Default: `us-west-1`
12+
4. _(optional)_ Specify the cache bucket name with `IMGPROXY_CACHE_BUCKET`.
13+
5. _(optional)_ Specify the S3 endpoint with `IMGPROXY_CACHE_S3_ENDPOINT`. You can also set `IMGPROXY_CACHE_S3_ENDPOINT_USE_PATH_STYLE=false` to use the virtual host style for the endpoint.
14+
6. _(optional)_ Specify the AWS IAM Role to Assume with `IMGPROXY_CACHE_S3_ASSUME_ROLE_ARN`.
15+
7. _(optional)_ Specify the External ID that needs to be passed in along with the AWS IAM Role to Assume with `IMGPROXY_CACHE_S3_ASSUME_ROLE_EXTERNAL_ID`. This will have no effect if the assume role ARN is not specified.
16+
17+
### Configuration
18+
19+
* `IMGPROXY_CACHE_USE`: set to `s3` to enable S3 cache.
20+
* `IMGPROXY_CACHE_BUCKET`: the S3 bucket name for cache storage. Default: blank
21+
* `IMGPROXY_CACHE_S3_REGION`: the S3 region for the cache bucket. Default: blank
22+
* `IMGPROXY_CACHE_S3_ENDPOINT`: a custom S3 endpoint for the cache. Useful for S3-compatible services like MinIO, Cloudflare R2, DigitalOcean Spaces, etc. Default: blank
23+
* `IMGPROXY_CACHE_S3_ENDPOINT_USE_PATH_STYLE`: controls how the S3 bucket endpoint is constructed. When `true`, the endpoint will be constructed using the path style (`https://your-endpoint.com/%bucket`). When `false`, the endpoint will be constructed using the virtual host style (`https://%bucket.your-endpoint.com`). Default: `true`
24+
* `IMGPROXY_CACHE_S3_ASSUME_ROLE_ARN`: the ARN of an IAM role to assume for cache access. Default: blank
25+
* `IMGPROXY_CACHE_S3_ASSUME_ROLE_EXTERNAL_ID`: the external ID required to assume the IAM role for cache access. Default: blank
26+
* `IMGPROXY_CACHE_PATH_PREFIX`: a path prefix for the cache files. Default: blank
27+
* `IMGPROXY_CACHE_KEY_HEADERS`: a comma-separated list of HTTP request headers to include in the cache key. Default: blank
28+
* `IMGPROXY_CACHE_KEY_COOKIES`: a comma-separated list of HTTP request cookies to include in the cache key. Default: blank
29+
* `IMGPROXY_CACHE_REPORT_ERRORS`: when `true`, imgproxy will report cache errors instead of silently falling back to processing without cache. Default: `false`
30+
31+
### Set up credentials
32+
33+
There are three ways to specify your AWS credentials. The credentials need to have read/write rights for the cache bucket:
34+
35+
#### IAM Roles
36+
37+
If you're running imgproxy on an Amazon Web Services platform, you can use IAM roles to get the security credentials to make calls to AWS S3.
38+
39+
* **Elastic Container Service (ECS):** Assign an [IAM role to a task](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html).
40+
* **Elastic Kubernetes Service (EKS):** Assign a [service account to a pod](https://docs.aws.amazon.com/eks/latest/userguide/pod-configuration.html).
41+
* **Elastic Beanstalk:** Assign an [IAM role to an instance](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/iam-instanceprofile.html).
42+
43+
#### Environment variables
44+
45+
You can specify an AWS Access Key ID and a Secret Access Key by setting the standard `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables.
46+
47+
```bash
48+
AWS_ACCESS_KEY_ID=my_access_key AWS_SECRET_ACCESS_KEY=my_secret_key imgproxy
49+
50+
# same for Docker
51+
docker run -e AWS_ACCESS_KEY_ID=my_access_key -e AWS_SECRET_ACCESS_KEY=my_secret_key -it ghcr.io/imgproxy/imgproxy
52+
```
53+
54+
#### Shared credentials file
55+
56+
Alternatively, you can create the `.aws/credentials` file in your home directory with the following content:
57+
58+
```ini
59+
[default]
60+
aws_access_key_id = %access_key_id
61+
aws_secret_access_key = %secret_access_key
62+
```
63+
64+
#### Cross-Account Access
65+
66+
Cache S3 access credentials may be acquired by assuming a role using STS. To do so specify the IAM Role arn with the `IMGPROXY_CACHE_S3_ASSUME_ROLE_ARN` environment variable. Additionally, if you require an external ID to be passed when assuming a role, specify the `IMGPROXY_CACHE_S3_ASSUME_ROLE_EXTERNAL_ID` environment variable. This approach still requires you to provide initial AWS credentials by using one of the ways described above. The provided credentials role should allow assuming the role with provided ARN.
67+
68+
### Choosing the AWS region
69+
70+
The AWS region specified with the `IMGPROXY_CACHE_S3_REGION` environment variable determines the S3 endpoint used by imgproxy for the initial request to the bucket. If AWS reports that the bucket is in a different region, imgproxy will remember this, retry the request, and use the new region for all subsequent requests for this bucket.
71+
72+
This allows imgproxy to access buckets in any region. However, the initial request to the bucket in a different region than the one specified in the environment variable may add some latency.

0 commit comments

Comments
 (0)