symfony / ux-ipx-image
Symfony UX Image IPX Bridge
Package info
github.com/symfony/ux-ipx-image
Type:symfony-ux-image-bridge
pkg:composer/symfony/ux-ipx-image
Requires
- php: >=8.4
- symfony/ux-image: ^3.7
Requires (Dev)
- phpunit/phpunit: ^12.0
- spatie/phpunit-snapshot-assertions: ^5.2.3
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-29 22:09:30 UTC
README
EXPERIMENTAL This component is currently experimental and is likely to change, or even change drastically.
IPX integration for Symfony UX Image. IPX is a self-hosted image server built on sharp. It reads the transformation from the URL path, /<modifiers>/<image path>.
Installation
Install the bridge using Composer and Symfony Flex:
composer require symfony/ux-ipx-image
DSN example
UX_IMAGE_DSN=ipx://images.example.com
The DSN uses HTTPS by default. The port and the path are optional, like ipx://images.example.com:8443/_ipx. Add secure=false to switch to plain HTTP.
Running IPX
IPX runs from the official node:26-alpine Docker image. You configure it with environment variables. This example reads the images from your application's public/ directory:
# compose.yaml services: ipx: image: node:26-alpine command: npx --yes ipx@4 serve environment: IPX_FS_DIR: /srv/public IPX_ALLOWED_MODIFIERS: width,height,resize,fit,format,quality volumes: - ./public:/srv/public:ro
Warning
IPX has no URL signing, so anyone can request any transformation it accepts. In IPX_ALLOWED_MODIFIERS, list only what you use. width, height, resize, fit, format and quality cover the common parameters. Add every extra operation you pass.
Local development
Publish the IPX port in compose.override.yaml. Docker Compose reads this file on top of compose.yaml:
# compose.override.yaml services: ipx: ports: [3000]
The Symfony CLI sets IPX_HOST and IPX_PORT from the published port. IPX serves plain HTTP, so the DSN needs secure=false:
# .env.dev UX_IMAGE_DSN=ipx://${IPX_HOST}:${IPX_PORT}?secure=false
Production
In production, set UX_IMAGE_DSN in .env.prod.local or as a Symfony secret. Use the host where IPX will be reachable:
# .env.prod.local UX_IMAGE_DSN=ipx://images.example.com
IPX listens on port 3000. Put it behind a reverse proxy that serves this host. compose.prod.yaml publishes IPX on a fixed port, on 127.0.0.1 only, so a reverse proxy on the same machine can reach it and the outside cannot:
# compose.prod.yaml services: ipx: ports: ['127.0.0.1:3000:3000']
In production, start the services with both files, and do not use compose.override.yaml:
docker compose -f compose.yaml -f compose.prod.yaml up -d
IPX does not store transformed images. It transforms the image again on every request, so cache its responses in the reverse proxy or a CDN.
By default, IPX sends Cache-Control: max-age=60. To use a longer duration, set IPX_FS_MAX_AGE in seconds, like 86400.
Parameter mapping
ImageTransformation properties are mapped to IPX modifiers:
ImageTransformation |
IPX modifier | Notes |
|---|---|---|
width |
w |
|
height |
h |
|
width and height |
s_<width>x<height> |
IPX reads fit only with s |
fit: Fit::Cover |
fit_cover |
|
fit: Fit::Contain |
fit_inside |
fit_contain would pad the image to the requested box |
format |
f |
format: 'auto' becomes f_auto, negotiated from Accept |
quality |
q |
|
operations |
(as given) | merged in verbatim, see below |
Supported operations
You can pass any of these keys through ImageTransformation::$operations. They are forwarded as-is as modifiers:
animated, autoorient, background, blur, brightness, clahe, dilate, enlarge, erode, extend, extract, flatten, flip, flop, gamma, grayscale, hue, kernel, lightness, linear, median, modulate, negate, normalize, opacity, position, rotate, saturation, sharpen, threshold, tint, trim, unflatten.
Join the arguments of an operation with _, like extract: '0_0_800_450'. Pass true for an operation without arguments, like grayscale. See the modifier reference for what each one does.
Supported formats
avif, webp, jpeg, png.