Handling user-uploaded
images with ease and
confidence
Andrey Novikov, Evil Martians
Osaka Web Designers and Developers Meetup
22 July 2023
That title is boring!
Let’s change!
imgproxy is amazing!
Andrey Novikov, Evil Martians
Osaka Web Designers and Developers Meetup
22 July 2023
About me
Back-end engineer at Evil
Martians
Writing Ruby, Go, and whatever
SQL, Dockerfiles, TypeScript, bash…
Love open-source software
Created and maintaining a fewRuby
gems
Living in Japan for 1 year already
Driving a moped
And also a bicycle to get kids to
kindergarten
Hi, I’m Andrey
evilmartians.com
evilmartians.jp
邪悪な火星人?
イービルマーシャンズ!
Martian Open Source
Yabeda:Ruby application
instrumentation framework
Lefthook:git hooks manager AnyCable:Polyglot replacement for
ActionCable server
PostCSS:A tool for transforming
CSS with JavaScript
Imgproxy:Fast and secure
standalone server for resizing and
converting remote images
Logux:Client-server communication
framework based on Optimistic UI,
CRDT, and log
Overmind:Process manager for
Procfile-based applications and
tmux
Even more at
evilmartians.com/oss
Today's topic
So, you need to handle user images
Profile pictures
Product photos
Recipes
Reviews
Photos in feedback forms
…
Surprisingly often you need to do it in a web application!
What you will do with them?
Generate thumbnails
to save bandwidth
Crop them
to fit design
Add watermarks
to prevent theft
Apply filters
However, CSS can do it too
Showthem in various places, of course!
“Classic” way
Upload image to the server
Probablyamong other form fields
Store it somewhere
Often on S3 or other cloud storage
Generate all required thumbnails
As manyasyour design requires
Store them somewhere
Again S3 or other cloud storage
Serve them to the user
CDN will help here
“Classic” way visualized
User Server Storage JobQueue
Job
started
Uploads Image
Stores Image
Queues Job
Upload successful
Requests thumbnail
Retrieves Thumbnail
There are no thumbnails yet!
“Image is processing”
Retrieve image
Unpredictable
latency
here
Generates
thumbnail
Stores Thumbnail
Requests thumbnail
Retrieves Thumbnail
Oh yes, of course, here it is
Returns thumbnail
User Server ImageStorage JobQueue
Problems of “classic” approach
Hard to predict latency
These “image is processing” fallbacks are ugly
Hard to add newvariants
Need to reprocess all images before changing front-end
And hard to clean up old ones
Space is cheap, but not free
Deployment gets complicated
You need to install ImageMagick or something on all servers/containers
Security also is your headache
Processing images on your servers is a securityand stabilityrisk, e.g. PNG decompression
bomb.
Do we have to do things
this way?
What if we could just generate thumbnails on the fly?
Meet image processing servers
There are many of them: imaginary, cloudinary, etc. And, of course, imgproxy!
They do just one thing, but do it well
User Server Storage imgproxy
generate thumbnail
on the fly
Uploads Image
Notifies about upload
Thumbnail URL
Requests thumbnail
Retrieves image
Respond with thumbnail
User Server Storage imgproxy
What the URL!
Given original image URL:
I need to get 300×150 thumbnail, but for Retina displays, smart cropped, and
saturated, also with watermark in right bottom corner.
Here is the result URL for such a thumbnail:
See https://docs.imgproxy.net/generating_the_url
The only thing you need to care about is constructing URLs
https://www.nasa.gov/sites/default/files/thumbnails/image/pia22228.jpg
https://imgproxy.evilmartians.com/
PeInr5PpUxqmfAQlYON_cPs2HC96QOoXik3UaDzIA6c/
rs:fill:300:150:1/dpr:2/g:ce/sa:1.4/
wm:0.5:soea:0:0:0.2/wmu:aHR0cHM6Ly9pbWdwcm94eS5uZXQvd2F0ZXJtYXJrLnN2Zw/
plain/
https:%2F%2Fwww.nasa.gov%2Fsites%2Fdefault%2Ffiles%2Fthumbnails%2Fimage%2Fpia22228.jpg
Digital signature
Processing options
Original image URL
Original image
Original image: 1.9MB
Processed image
Imageprocessedwith imgproxy: 32kB
imgproxy
Written in Go
Great concurrency, lowmemoryfootprint, squeezes everything from your servers CPU
Uses libvips for image handling
Along with speciallycrafted processing pipeline optimized for speed and concurrency
Open source and open core
Free to use OSS version that covers needs of 99% users, paid PRO version with more
features and support for those who reallyneed it
Easy to deploy
Just spin up a Docker container and forget and it is readyto go.
Easy to use
Just construct a URL using one of the client libraries, send it to a browser, done!
Secure and safe
Uses signed URIs, handles image bombs, invalid images, and more.
More on security
Signed URLs
No one can generate URLswithout knowing your secret keyand use your imgproxyto
process their images for free. Or DDoS and cache-poison your CDN byrequesting your
imageswith all possible sizes and options.
Examples howto sign URL in different languages:
https://github.com/imgproxy/imgproxy/tree/master/examples
Image compression bombs
imgproxywill check metadata and won’t process images that are too large bydimensions
Authentication
imgproxycan check for authentication headers, and will not process images if someone try
to access it bypassing CDN
Source restrictions
imgproxycan be instructed to allowprocess images onlyfrom sources that you control.
How it solves “classic” approach
Latency: Dedicated servicethat do onlyimages processing
Veryperformant per se, and you can scale it independentlyfrom your main application, also
add CDN in front of it
Adding newvariants: Just construct newURL
Construct newURL, request it, done!
Cleaning up old ones: Let CDN caches to expire
Do you reallyneed to store thumbnails at all? Care onlyfor originals.
Security and stability: it is separate fromyour main application
It handles image bombs, and other nastystuff, but even if some malicious code will be
executed, it will find itself in emptyDocker container without anything in it.
Recommended setup
Use direct-upload to cloud storage (S3, …)
No need to pass images through your application servers at all
Place a caching CDN in front of imgproxy
Take repetitive load off from imgproxy, save some CO₂
Migration pitfalls
Only back-end can construct signed URLs
No more guessing on front-end of what variants are available
But you can opt-out from signing URLs if you want
Couldn't recall any more 🌚
Open source imgproxy will cover you
But there are more goodies (and support) in PRO version!
Advanced per-image settings
Different resizing algirithms, watermarks, compression for individual images
Automagic selection of image format and quality settings
Maximum per-image compression using most modern format without visible qualityloss
Even smarter crop with object detection
Detect objects using ML algorithms to crop more accuratelyor blur them
SVG processing
Inject custom styles, minify
Videos, animated GIFs, PDFs support
Thumbnailing videos, GIF to video conversion, getting image info
OSS version has everything that most web applications need…
imgproxy.net/features
Read more
imgproxy is amazing
byJohn Nunemaker
heavilyinfluenced this talk plot (and title, yes)
imgproxy: Resize your images instantly and securely
bySergeyAlexandrovich (imgproxyauthor)
with more details on howimgproxyworks and howto use it
Decoding AVIF: Deep dive with cats and imgproxy
byPolina Gurtovaya
illustrated explanation of modern video and image format internals
and howto start using them with imgproxy!
Thank you!
@Envek
@Envek
@Envek
@Envek
github.com/Envek
@evilmartians
@evilmartians
@evil-martians
@evil.martians
evilmartians.com
Our awesome blog: evilmartians.com/chronicles!
See these slides at envek.github.io/owddm-imgproxy-is-amazing
Go get imgproxy!
imgproxy.net

imgproxy is amazing

  • 1.
    Handling user-uploaded images withease and confidence Andrey Novikov, Evil Martians Osaka Web Designers and Developers Meetup 22 July 2023
  • 2.
    That title isboring! Let’s change!
  • 3.
    imgproxy is amazing! AndreyNovikov, Evil Martians Osaka Web Designers and Developers Meetup 22 July 2023
  • 4.
    About me Back-end engineerat Evil Martians Writing Ruby, Go, and whatever SQL, Dockerfiles, TypeScript, bash… Love open-source software Created and maintaining a fewRuby gems Living in Japan for 1 year already Driving a moped And also a bicycle to get kids to kindergarten Hi, I’m Andrey
  • 5.
  • 6.
    Martian Open Source Yabeda:Rubyapplication instrumentation framework Lefthook:git hooks manager AnyCable:Polyglot replacement for ActionCable server PostCSS:A tool for transforming CSS with JavaScript Imgproxy:Fast and secure standalone server for resizing and converting remote images Logux:Client-server communication framework based on Optimistic UI, CRDT, and log Overmind:Process manager for Procfile-based applications and tmux Even more at evilmartians.com/oss Today's topic
  • 7.
    So, you needto handle user images Profile pictures Product photos Recipes Reviews Photos in feedback forms … Surprisingly often you need to do it in a web application!
  • 8.
    What you willdo with them? Generate thumbnails to save bandwidth Crop them to fit design Add watermarks to prevent theft Apply filters However, CSS can do it too Showthem in various places, of course!
  • 9.
    “Classic” way Upload imageto the server Probablyamong other form fields Store it somewhere Often on S3 or other cloud storage Generate all required thumbnails As manyasyour design requires Store them somewhere Again S3 or other cloud storage Serve them to the user CDN will help here
  • 10.
    “Classic” way visualized UserServer Storage JobQueue Job started Uploads Image Stores Image Queues Job Upload successful Requests thumbnail Retrieves Thumbnail There are no thumbnails yet! “Image is processing” Retrieve image Unpredictable latency here
  • 11.
    Generates thumbnail Stores Thumbnail Requests thumbnail RetrievesThumbnail Oh yes, of course, here it is Returns thumbnail User Server ImageStorage JobQueue
  • 12.
    Problems of “classic”approach Hard to predict latency These “image is processing” fallbacks are ugly Hard to add newvariants Need to reprocess all images before changing front-end And hard to clean up old ones Space is cheap, but not free Deployment gets complicated You need to install ImageMagick or something on all servers/containers Security also is your headache Processing images on your servers is a securityand stabilityrisk, e.g. PNG decompression bomb.
  • 13.
    Do we haveto do things this way? What if we could just generate thumbnails on the fly?
  • 14.
    Meet image processingservers There are many of them: imaginary, cloudinary, etc. And, of course, imgproxy! They do just one thing, but do it well User Server Storage imgproxy generate thumbnail on the fly Uploads Image Notifies about upload Thumbnail URL Requests thumbnail Retrieves image Respond with thumbnail User Server Storage imgproxy
  • 15.
    What the URL! Givenoriginal image URL: I need to get 300×150 thumbnail, but for Retina displays, smart cropped, and saturated, also with watermark in right bottom corner. Here is the result URL for such a thumbnail: See https://docs.imgproxy.net/generating_the_url The only thing you need to care about is constructing URLs https://www.nasa.gov/sites/default/files/thumbnails/image/pia22228.jpg https://imgproxy.evilmartians.com/ PeInr5PpUxqmfAQlYON_cPs2HC96QOoXik3UaDzIA6c/ rs:fill:300:150:1/dpr:2/g:ce/sa:1.4/ wm:0.5:soea:0:0:0.2/wmu:aHR0cHM6Ly9pbWdwcm94eS5uZXQvd2F0ZXJtYXJrLnN2Zw/ plain/ https:%2F%2Fwww.nasa.gov%2Fsites%2Fdefault%2Ffiles%2Fthumbnails%2Fimage%2Fpia22228.jpg Digital signature Processing options Original image URL
  • 16.
  • 17.
  • 18.
    imgproxy Written in Go Greatconcurrency, lowmemoryfootprint, squeezes everything from your servers CPU Uses libvips for image handling Along with speciallycrafted processing pipeline optimized for speed and concurrency Open source and open core Free to use OSS version that covers needs of 99% users, paid PRO version with more features and support for those who reallyneed it Easy to deploy Just spin up a Docker container and forget and it is readyto go. Easy to use Just construct a URL using one of the client libraries, send it to a browser, done! Secure and safe Uses signed URIs, handles image bombs, invalid images, and more.
  • 19.
    More on security SignedURLs No one can generate URLswithout knowing your secret keyand use your imgproxyto process their images for free. Or DDoS and cache-poison your CDN byrequesting your imageswith all possible sizes and options. Examples howto sign URL in different languages: https://github.com/imgproxy/imgproxy/tree/master/examples Image compression bombs imgproxywill check metadata and won’t process images that are too large bydimensions Authentication imgproxycan check for authentication headers, and will not process images if someone try to access it bypassing CDN Source restrictions imgproxycan be instructed to allowprocess images onlyfrom sources that you control.
  • 20.
    How it solves“classic” approach Latency: Dedicated servicethat do onlyimages processing Veryperformant per se, and you can scale it independentlyfrom your main application, also add CDN in front of it Adding newvariants: Just construct newURL Construct newURL, request it, done! Cleaning up old ones: Let CDN caches to expire Do you reallyneed to store thumbnails at all? Care onlyfor originals. Security and stability: it is separate fromyour main application It handles image bombs, and other nastystuff, but even if some malicious code will be executed, it will find itself in emptyDocker container without anything in it.
  • 21.
    Recommended setup Use direct-uploadto cloud storage (S3, …) No need to pass images through your application servers at all Place a caching CDN in front of imgproxy Take repetitive load off from imgproxy, save some CO₂
  • 22.
    Migration pitfalls Only back-endcan construct signed URLs No more guessing on front-end of what variants are available But you can opt-out from signing URLs if you want Couldn't recall any more 🌚
  • 23.
    Open source imgproxywill cover you But there are more goodies (and support) in PRO version! Advanced per-image settings Different resizing algirithms, watermarks, compression for individual images Automagic selection of image format and quality settings Maximum per-image compression using most modern format without visible qualityloss Even smarter crop with object detection Detect objects using ML algorithms to crop more accuratelyor blur them SVG processing Inject custom styles, minify Videos, animated GIFs, PDFs support Thumbnailing videos, GIF to video conversion, getting image info OSS version has everything that most web applications need… imgproxy.net/features
  • 24.
    Read more imgproxy isamazing byJohn Nunemaker heavilyinfluenced this talk plot (and title, yes) imgproxy: Resize your images instantly and securely bySergeyAlexandrovich (imgproxyauthor) with more details on howimgproxyworks and howto use it Decoding AVIF: Deep dive with cats and imgproxy byPolina Gurtovaya illustrated explanation of modern video and image format internals and howto start using them with imgproxy!
  • 25.
    Thank you! @Envek @Envek @Envek @Envek github.com/Envek @evilmartians @evilmartians @evil-martians @evil.martians evilmartians.com Our awesomeblog: evilmartians.com/chronicles! See these slides at envek.github.io/owddm-imgproxy-is-amazing Go get imgproxy! imgproxy.net