Docs / Configuration & operations / Config key reference

Config key reference v0.2.0

Every key in config.toml, with its type, default and what it does. All of them are optional, and picturium runs fine without a config file at all. Configuration & operations explains how config is loaded and how to size caches, concurrency, CORS and logs. Signing, validators, cache busting and capacity are covered in the Request model.

  • To use an environment variable, uppercase the key, add the PICTURIUM__ prefix, and put __ between levels. For example, output.encoder.avif.bitdepth becomes PICTURIUM__OUTPUT__ENCODER__AVIF__BITDEPTH. Environment variables override the file.
  • List values (cors.allowed_origins, data.serve, output.format_priority, output.metadata) are comma-separated in an environment variable.
  • picturium validates values at startup. An out-of-range value or unknown key prevents the server from starting.
  • The repository includes config.toml.example with the same defaults and inline comments.

[server]

log_level

Controls log detail. RUST_LOG overrides this value when set.

host

Address used by the HTTP listener. 0.0.0.0 accepts connections on every network interface.

port

TCP port the listener binds to.

workers

Maximum number of images rendered at once. 0 means twice the logical CPU count.

queue_size

Maximum number of requests waiting for a worker. A full queue rejects new requests with 503.

[security]

signature_enabled

Requires every request to include a valid HMAC token for its path and query. When false, requests do not need a signature.

signature_secret

Shared secret used for HMAC-SHA256 signatures. Generate one with openssl rand -hex 48. Used only when signature_enabled is true.

health_token

Bearer token that unlocks details on GET /health (version, worker and queue counts, memory statistics) when sent as Authorization: Bearer <token> or as ?token=<token>. The query form ends up in access logs, so prefer the header. Without a token /health returns only the status; a wrong token gets 401. Empty disables the details.

[cors]

allowed_origins

Origins allowed to read responses across origins. "*" allows all origins; otherwise each origin must match exactly. Invalid entries are ignored.

[vips]

debug

Turns on libvips leak checking and prints the objects still alive at shutdown. Diagnostics only; it adds overhead.

concurrency

Threads libvips may use inside a single operation. Total threads ≈ server.workers × vips.concurrency.

[data]

dir

Root folder for source files. Requests cannot access files outside it.

serve

Non-image file extensions that picturium may return unchanged, such as "zip" or "txt". ["*"] allows every extension; unlisted types return 415.

[cache]

Both cache tiers are enabled by default. picturium checks memory first, then disk. A result that fits neither is returned without being cached.

dir

Directory used by the disk cache. Only one running process can use it at a time.

cache_control

Sent verbatim as Cache-Control on every successful response. A force=true response sends no-store instead.

memory.enabled

Enables the memory cache, which is checked before disk.

memory.limit

Total memory budget for the memory tier. Each entry is charged its own size.

memory.entry_limit

Largest single response kept in memory. Bigger renders fall through to disk, or are served uncached.

disk.enabled

Enables the disk cache and locks the cache directory for this process.

disk.limit

Effective on-disk capacity, shared by finished responses and Office / SVG / video intermediates. foyer evicts and reclaims automatically.

disk.entry_limit

Largest single response written to disk. Also foyer's block size, the unit it reclaims in. Changing it discards the existing disk cache.

[svg]

unlimited

Allow loading SVG files larger than libvips' 10 MB safety limit.

load_dpi

Resolution an SVG is rasterised at when the request gives no dpi.

allow_local_resources

Allows an SVG rendered as PDF (f=pdf) to embed files referenced by <image href>. References must stay inside the data directory; absolute paths and ".." are rejected. Keep this off when users should not read each other's files.

[pdf]

load_dpi

Resolution a PDF page is rasterised at when the request gives no dpi.

background

Colour behind PDF and Office pages when they are rasterised. A bg parameter on the request wins. Must parse as a colour or startup fails.

max_file_size

PDFs larger than this are not rendered. The original file is served as-is instead, or the fallback is rendered when the request has one.

max_pages

Most pages one request may select with page / pages. Larger selections get a 400, or the fallback when the request has one. Applies to PDF, Office and vector-art sources; animated images are not limited by it.

max_image_pixels

Refuses to render a PDF when its first page, at the resolved render scale, would exceed this many pixels. The request fails with a 500, or renders the fallback when the request has one.

[office]

conversion_timeout

How long LibreOffice may take to convert one document before the request fails.

kill_timeout

Hard limit for one LibreOffice run. A conversion that outlives conversion_timeout keeps going in the background to fill the cache until this limit kills it. Must not be lower than conversion_timeout.

max_processes

Maximum number of LibreOffice processes running at once, background conversions included. Further conversions wait for a free slot. 0 means the logical CPU count.

[vector]

conversion_timeout

How long Inkscape may take to convert one .ai / .cdr / .cmx / .cdt / .eps / .dxf source before the request fails.

[video]

See Animation & video for request syntax and how these defaults affect still-frame and clip extraction.

default_time

Frame position used when the request does not set t. The one-second default avoids many black or fading first frames.

extraction_timeout

Time budget for pulling a single frame out of a video.

animation_timeout

Time limit for extracting a clip. Unlike a single-frame seek, a clip decodes every frame in its range.

animation_frames

Frames sampled for a clip when anim gives no count.

animation_fps

Sample rate for a clip when anim gives no timing or fps.

max_animation_frames

Hard ceiling on frames in one clip, whatever anim=frames asks for.

[image]

Default sizing and layout values. Each value can be overridden by the matching URL parameter. See Cropping for how image.crop_gravity controls the grouped crop= parameter.

auto_rotate

Apply the EXIF orientation tag so the image faces the right way. Request override: autorot.

upsize

Allows output larger than the source. When false, picturium shrinks the requested box to fit the original. Request override: upsize.

extend

How area added by padding or aspect-ratio fill is filled. bg uses the background colour. Request override: extend.

fit

Controls how the image fills the requested box: cover crops overflow, contain adds padding, and force stretches. Request override: fit.

gravity

Chooses which part a cover crop keeps, or where a contained image sits. attention and entropy use libvips smart cropping. Request override: g.

crop_gravity

Default gravity for the crop= parameter specifically — it does not inherit image.gravity.

resample

Resampling kernel used when scaling. Request override: resample.

[watermark]

Defaults for watermarks when enabled is true. Each key can be overridden with watermark=…, and watermark=false disables the mark for one request. An image takes priority over text. See Watermarking for request syntax, source precedence, placement, and complete configuration examples.

enabled

Adds a watermark to every supported response unless the request opts out. Set image.path or text.text before enabling it.

position

Where the mark sits. repeat tiles it across the image.

opacity

Mark opacity, in percent.

padding

CSS-like shorthand. Gap between the mark and the edge, and between tiles under position = "repeat".

rotate

Rotation of the mark, any angle.

max_scale

Largest fraction of the image width and height the mark itself may cover. Padding can reduce the available space further.

image.path

Operator-supplied path to the watermark image. Not confined to the data directory, unlike a request-supplied watermark=image: path.

image.scale

Scale factor applied to the watermark image.

text.text

Text drawn as the watermark when no image path is set.

text.font_color

Colour of a text watermark. Must parse as a colour or startup fails.

[output]

See Output format & quality for how these defaults affect a request.

format_priority

Order used by f=auto when checking the client's Accept header. It falls back to webp. gif is not selected automatically.

enable_avif

Reserved; the current pipeline does not use this key to gate AVIF output.

enable_webp

Reserved; the current pipeline does not use this key to gate WebP output.

enable_jxl

Reserved; the current pipeline does not use this key to gate JPEG XL output.

metadata

Metadata blocks copied into the output. none strips everything. Request override: meta.

quality

Default quality. A named level shifts the per-format quality curve; a number is used directly. Request override: q.

high_bitdepth

Reserved; the current raster encoder pipeline does not read this key.

cmyk

Reserved; the current raster encoder pipeline does not read this key.

max_width

Maximum output width. Wider results are scaled down without changing their aspect ratio. Request override: limit=dimension.

max_height

Ceiling on output height.

max_size

Maximum output file size. picturium re-encodes the image at a lower quality until it fits. Request override: limit=size.

max_size_threshold

How far under max_size counts as close enough — a result in that band is accepted without another recompress.

max_size_attempts

Maximum recompress passes when chasing max_size.

max_animation_frames

Hard cap on frames in one animated response. Each frame is a full pass through the geometry stages.

[output.quality_curves]

Each format has a quality curve based on image size. Images at or below max_area use max quality; images at or above min_area use min quality. Sizes between them are interpolated. The requested q level then shifts that value; medium and auto do not apply an offset. All formats, including JXL, use the shared 1–100 scale here. low, high, and maximum are offsets from −100 to 100.

min_area

At or above this area, quality bottoms out at each curve's min.

max_area

At or below this area, quality tops out at each curve's max. Must be above 0 and below min_area.

Per-format curves — output.quality_curves.<format>.<key>:

jpeg
webp
avif
png
jxl
gif

[output.encoder]

Encoder settings live under output.encoder.<format> for jpeg, webp, png, avif, jxl, and gif. Each codec has its own effort scale; higher values usually encode more slowly and produce smaller files.

jpeg.optimize_coding

Optimise Huffman tables — slower, slightly smaller. JPEG has no effort setting.

webp.effort

Encode effort. Higher is slower and smaller.

webp.text_preset_area

At or below this area the WebP encoder uses preset_small instead of preset_large.

webp.preset_small

libwebp preset for images at or below text_preset_area.

webp.preset_large

libwebp preset for larger images.

webp.min_alpha_quality

Alpha is never encoded below this quality.

webp.smart_subsample

Still images only. Smarter chroma subsampling; skipped on animation where it is slower and larger.

webp.animation_min_size

Animation only. Try every frame encoding and keep the smallest file. Much slower.

webp.animation_kmin

Animation only. Smallest gap between keyframes. 0 lets libwebp place none.

webp.animation_kmax

Animation only. Largest gap between keyframes. Closer keyframes seek better but cost encode time and size.

png.effort

Encode effort.

png.lossless_quality

Quality at or above which PNG switches to the lossless (non-palette) branch.

png.compression

Deflate level for the palette branch.

png.lossless_compression

Deflate level for the lossless branch.

png.dither

Quantisation dithering for the palette branch.

png.lossless_dither

Quantisation dithering for the lossless branch.

avif.effort

Encode effort.

avif.bitdepth

Bits per channel.

avif.compression

Codec carried in the AVIF container.

avif.encoder

Which encoder implementation to use.

avif.subsample

Chroma subsampling.

jxl.effort

Encode effort.

jxl.tier

Decode-speed tier. Higher decodes faster and compresses worse.

jxl.lossless

Force lossless JXL.

jxl.distance_per_quality

Converts the shared 1–100 quality to a JXL distance: distance = distance_per_quality × (100 − q).

gif.effort

Encode effort.

gif.bitdepth

Palette at quality 100 is 2^bitdepth colours.

gif.min_bitdepth

Palette bit depth at quality 1, interpolated up to bitdepth across the quality range.

gif.dither

Quantisation dithering at quality 100.

gif.min_dither

Quantisation dithering at quality 1.

gif.interframe_maxerror

Animation only. At quality 1 (0 at quality 100), pixels that changed less than this are reused from the previous frame.

gif.interpalette_maxerror

Animation only. At quality 1 (0 at quality 100), above this a frame reuses the previous frame’s palette.