Presets
A preset is a named bundle of processing options defined on the server. Reference it by name instead of repeating the option chain in every URL: the URLs get shorter, the transformations stay consistent, and changing a definition changes every URL that uses it.
Presets also make it possible to lock down what clients may request at all — see presets-only mode.
Syntax:
preset:<name>
pr:<name> # shorthandConfiguration
Define presets via the IMGFORGE_PRESETS environment variable. Each preset maps a name to a slash-separated list of processing options.
Basic Format
export IMGFORGE_PRESETS="name=option1:arg1/option2:arg2,name2=option3:arg3"Single Preset
export IMGFORGE_PRESETS="thumbnail=resize:fit:150:150/quality:80"This creates a preset called thumbnail that resizes images to 150×150 using the fit mode and outputs at 80% quality.
Multiple Presets
export IMGFORGE_PRESETS="thumbnail=resize:fit:150:150/quality:80,avatar=resize:fill:64:64/quality:85,banner=resize:fill:1200:300/quality:90"Separate multiple presets with commas. Each preset name must be unique.
Complex Presets
Presets can include any valid processing option:
export IMGFORGE_PRESETS="product_hero=resize:fit:1200:1200/quality:92/sharpen:1.2/background:ffffff/watermark:0.7:soea"The Default Preset
A preset named default receives special treatment—it applies automatically to every request before URL-specific options or named presets.
Example
export IMGFORGE_PRESETS="default=quality:90/dpr:1/auto_rotate:true"With this configuration, all images will:
- Use 90% quality (unless overridden)
- Apply 1.0 DPR scaling (unless overridden)
- Honor EXIF orientation by default
URL options and named presets can still override these defaults, which makes default the right place for organisation-wide baselines — a house quality setting, a preferred output format — rather than anything that must hold absolutely.
URL Usage
Basic Preset Reference
/<signature>/preset:thumbnail/<encoded_url>
/<signature>/pr:thumbnail/<encoded_url> # shorthandThe pr: shorthand is equivalent to preset: and saves bytes in URLs.
The source URL segment that follows the preset can use either encoding style supported by imgforge:
- Base64 URL-safe – append an optional
.<ext>suffix to force an output format/<signature>/preset:thumbnail/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWFnZS5qcGc.webp - Plain URL – start the segment with
plain/and percent-encode the URL, optionally adding@<ext>/<signature>/preset:thumbnail/plain/https%3A%2F%2Fexample.com%2Fimage.jpg@webp
Choose whichever form matches your signing tooling; presets work the same either way.
Chaining Presets
Multiple presets can be combined:
/<signature>/preset:base/preset:quality_high/<encoded_url>Later presets override earlier ones if they set the same parameter.
Mixing Presets and Options
Presets expand into options, so you can mix them freely:
/<signature>/preset:thumbnail/quality:95/<encoded_url>The explicit quality:95 overrides the quality setting from the thumbnail preset.
Signed URLs with Presets
Presets are part of the URL path and must be included in the signature:
# Path to sign
/preset:thumbnail/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWFnZS5qcGc
# Generate signature for this path
signature=$(./sign_url.sh "/preset:thumbnail/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWFnZS5qcGc")
# Full URL
https://imgforge.example.com/${signature}/preset:thumbnail/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWFnZS5qcGcPresets-Only Mode
Enable strict governance by setting IMGFORGE_ONLY_PRESETS=true. In this mode, imgforge rejects URLs that contain non-preset processing options.
Configuration
export IMGFORGE_PRESETS="small=resize:fit:300:300,medium=resize:fit:600:600,large=resize:fit:1200:1200"
export IMGFORGE_ONLY_PRESETS="true"Allowed Requests
✓ /<signature>/preset:small/<encoded_url>
✓ /<signature>/pr:medium/<encoded_url>
✓ /<signature>/preset:small/preset:large/<encoded_url> # chaining OKRejected Requests
✗ /<signature>/resize:fit:400:400/<encoded_url> # raw option
✗ /<signature>/preset:small/quality:95/<encoded_url> # mixed with option
✗ /<signature>/blur:5/<encoded_url> # non-preset optionAll rejected requests return 400 Bad Request with an error message.
This is the mode to use on multi-tenant platforms, or anywhere the cost of an arbitrary resize:fit:9999:9999 matters: clients can only ask for transformations you have already approved.
Exception: Default Preset
If a default preset exists, requests with no processing options at all will still succeed in presets-only mode, because the default preset is implicitly applied:
export IMGFORGE_PRESETS="default=quality:85,small=resize:fit:300:300"
export IMGFORGE_ONLY_PRESETS="true"✓ /<signature>/<encoded_url> # Allowed: default preset appliesWriting good presets
Name them after what they are for, not what they do — product_grid, avatar_lg, og_image. The name ends up in every URL and in the code that builds them, and t or p1 tells a future reader nothing.
Spell out quality and format rather than leaning on defaults. A preset that only sets dimensions inherits whatever the server default happens to be, which is exactly what changes underneath you.
# Leaves nothing to the server defaults
thumbnail=resize:fit:150:150/quality:80/format:webp/sharpen:0.8Version the name when the definition changes. Editing a preset in place silently changes every image already referenced by that URL, and old cache entries and new renders will disagree until the cache turns over:
export IMGFORGE_PRESETS="thumbnail_v1=resize:fit:150:150/quality:80,thumbnail_v2=resize:fit:150:150/quality:85/format:webp"Common Preset Patterns
Responsive Image Sets
Define presets for each breakpoint:
export IMGFORGE_PRESETS="\
mobile=resize:fit:400:400/quality:80/format:webp,\
tablet=resize:fit:800:800/quality:85/format:webp,\
desktop=resize:fit:1200:1200/quality:88/format:webp,\
retina=resize:fit:2400:2400/quality:90/format:webp"Usage in HTML:
<picture>
<source srcset="/<sig>/pr:mobile/<url>" media="(max-width: 640px)">
<source srcset="/<sig>/pr:tablet/<url>" media="(max-width: 1024px)">
<source srcset="/<sig>/pr:desktop/<url>" media="(max-width: 1920px)">
<img src="/<sig>/pr:retina/<url>" alt="...">
</picture>Size Ladders
The same shape works for any fixed set of sizes — avatars, product images, thumbnails. Set the gravity explicitly whenever you crop with fill, since the anchor decides which part of the image survives:
export IMGFORGE_PRESETS="\
avatar_xs=resize:fill:32:32/gravity:ce/quality:85,\
avatar_md=resize:fill:128:128/gravity:ce/quality:88,\
avatar_lg=resize:fill:256:256/gravity:ce/quality:90"Composable Modifiers
Presets chain, so a small preset that sets only the output format can be combined with a preset that sets only the geometry:
export IMGFORGE_PRESETS="thumbnail=resize:fit:150:150,webp_hq=quality:92/format:webp"/<signature>/preset:thumbnail/preset:webp_hq/<encoded_url>Keep the pieces disjoint. Two chained presets that both set quality resolve by position, not by intent, and the result depends on the order they appear in the URL.
Preset Expansion Order
Understanding expansion order helps predict the final result when combining multiple presets and options.
Expansion sequence:
- Default preset (if defined) expands first
- URL options/presets expand left-to-right
- Later values override earlier ones for the same parameter
Example
Configuration:
export IMGFORGE_PRESETS="default=quality:80,thumbnail=resize:fit:150:150/quality:90,sharp=sharpen:1.5"URL:
/<signature>/preset:thumbnail/quality:95/preset:sharp/<encoded_url>Expansion steps:
default=quality:80→quality:80preset:thumbnail→resize:fit:150:150/quality:90(quality now 90)quality:95→ (quality now 95, overrides preset)preset:sharp→sharpen:1.5
Final options: resize:fit:150:150/quality:95/sharpen:1.5
Override Strategy
Later options always win:
# These all produce quality:95
/<sig>/preset:thumbnail/quality:95/<url> # explicit override
/<sig>/quality:70/preset:thumbnail/<url> # preset overrides earlier
/<sig>/preset:low_quality/preset:high_quality/<url> # second preset winsThis makes it safe to set defaults and override selectively.
Troubleshooting
Preset Not Found Error
Symptom: 400 Bad Request with message "unknown preset: xyz"
Causes:
- Preset name misspelled in URL
- Preset not defined in
IMGFORGE_PRESETS - Environment variable not loaded (server restart needed)
Fix:
# Verify preset is defined
echo $IMGFORGE_PRESETS
# Check imgforge startup logs
docker logs imgforge | grep -i presetUnexpected Transformation Results
Symptom: Image doesn't match expected dimensions/quality
Causes:
- Option override you didn't expect
- Default preset applying unintended options
- Multiple presets with conflicting settings
Debug:
# Enable debug logging
export IMGFORGE_LOG_LEVEL="imgforge=debug"
# Check logs for "Applying default preset" or "Expanding preset"
# This shows exact expansion sequencePresets-Only Mode Rejecting Valid Presets
Symptom: 400 Bad Request even with preset:name in URL
Causes:
- Extra processing options mixed with preset
- Typo:
preset_nameinstead ofpreset:name - Space or special character in preset name
Fix:
# Valid in presets-only mode
/<sig>/pr:thumbnail/<url>
# Invalid - mixing preset with option
/<sig>/pr:thumbnail/quality:95/<url>Preset Changes Not Applied
Symptom: Old preset definition still being used
Cause: Environment variable not reloaded
Fix:
# Update environment variable
export IMGFORGE_PRESETS="new_definition"
# Restart imgforge
systemctl restart imgforge
# or
docker restart imgforgeCaching with Presets
The cache key is the request path as written — pr:thumbnail, not the options it expands to. Editing a preset definition therefore does not invalidate anything:
# Cached under the path containing "pr:thumbnail"
/<sig>/pr:thumbnail/<url> → [cached at 150x150]
export IMGFORGE_PRESETS="thumbnail=resize:fit:200:200/quality:90" # was 150x150
# Restart imgforge
/<sig>/pr:thumbnail/<url> → [still the cached 150x150 bytes]The old rendering keeps being served until that entry is evicted, while any URL that missed the cache renders at the new size. Two sizes in circulation at once is rarely what you want.
So when a definition changes, give it a new name and move the application to it:
thumbnail_v1=resize:fit:150:150
thumbnail_v2=resize:fit:200:200The new name is a new path, so it is a new cache entry, and the old entries age out on their own. There is no purge API.
Security Considerations
Preset Definition Protection
Presets are defined server-side and cannot be modified by clients. This makes them safer than allowing arbitrary options:
# Safe: preset controls transformations
export IMGFORGE_PRESETS="thumbnail=resize:fit:150:150/quality:80"
export IMGFORGE_ONLY_PRESETS="true"
# Clients can only use defined presets
/<sig>/pr:thumbnail/<url> ✓
/<sig>/resize:fit:9999:9999/<url> ✗ rejectedSignature Coverage
Preset names are part of the URL path and must be included in the HMAC signature. This prevents:
- Preset name tampering
- Substituting one preset for another
- Adding presets to unsigned URLs
See Also
- Processing Options – Complete options reference
- Configuration – Environment variable details
- URL Structure – URL signing and encoding
- Caching – Cache behavior with presets
- Performance – Optimization strategies