Imgforge LogoImgforge

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>  # shorthand

Configuration

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>  # shorthand

The 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/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWFnZS5qcGc

Presets-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 OK

Rejected 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 option

All 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 applies

Writing 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.8

Version 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:

  1. Default preset (if defined) expands first
  2. URL options/presets expand left-to-right
  3. 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:

  1. default=quality:80quality:80
  2. preset:thumbnailresize:fit:150:150/quality:90 (quality now 90)
  3. quality:95 → (quality now 95, overrides preset)
  4. preset:sharpsharpen: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 wins

This 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 preset

Unexpected 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 sequence

Presets-Only Mode Rejecting Valid Presets

Symptom: 400 Bad Request even with preset:name in URL

Causes:

  • Extra processing options mixed with preset
  • Typo: preset_name instead of preset: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 imgforge

Caching with Presets

The cache key is the request path as writtenpr: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:200

The 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>   rejected

Signature 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

On this page