Signing Imgproxy Urls

September 24, 2025 Β· Tyler Yeager Β· 2 min reading time

Cloud Services

For some time now, I’ve been trying to find a reliable image processing service. I settled on a cloud offering a year ago, but their service was constantly going down, with no real guarantee that it would stay up. This was a problem since my services that used these images would fail on building. So my CI system would just crash and stop building.

I did like their system. They allowed the ability to route requests based on a custom domain name to a specific backend. For example, requests to img.tylery.com/image1.png would route to mycdn.cloud.tld/buckets/img.tylery.com/image1.png.

This worked really well for me, since it allowed me to store the images through both their service and a cdn. Alas.

I finally switched all my urls to the original source, bypassing the image processor (so my CI systems would work) but this lost a big benefit, the ability to resize or format images.

Imgproxy

I stumbled on imgproxy, and it seems reasonable enough for me to use. I’m losing that privacy I liked (where the original images were secure) but I may implement this functionality again.

However, a big problem is abuse to the service. What happens if you request an image resized to 400px, then 401px, 402px and so forth? This would cause a lot of CPU times and is an easy way to initiate a DOS attack on me.

Imgproxy has a feature calling signing_url which addresses this. Essentially, the request must be signed for it to go through. They have multiple examples in standard programming languages such as Python / Javascript when I checked. However, I just needed to build up an image, sign it and place it into a website! Did I really need to write a program to get this basic functionality?

Signing with Openssl / Bash

Anyway, I wrote up a bash script that does it as well.

sign_imgproxy.sh
#!/usr/bin/env bash
PLAIN_SALT="hello"
PLAIN_SECRET="secret"
URL_PATH="$(echo -n "$1" | cut -d '/' -f '5-')"
DOMAIN="$(echo -n "$1" | cut -d '/' -f '1-3')"
URL="$(echo -n "$PLAIN_SALT/$URL_PATH")"
ENCODED="$(echo -n "$URL" | openssl dgst -sha256 -hmac "$PLAIN_SECRET" -binary | openssl base64 | tr '/' '_' | tr '+' '-' | tr -d '=')"
echo "$DOMAIN/$ENCODED/$URL_PATH"

If you want to use this, your imgproxy should be configured with the SALT hexed.

Terminal window
echo -n hello | od -A n -t x1 | tr '\n' ' ' | tr -d ' '
# 68656c6c6f

You can then put this into the environment in the Docker environment.

docker-compose.yml
services:
imgproxy:
image: ghcr.io/imgproxy/imgproxy:latest
environment:
IMGPROXY_KEY: "${IMGPROXY_KEY}"
IMGPROXY_SALT: 68656c6c6f

Dev Signature

This introduces a problem, how do you even figure out the right parameters for your image without doing hundreds of signatures for every option? Also, what about server based rendering, where it pulls the image, caches it locally and sends that to the user? What’s the point of signatures here?

Well, you can use trusted signatures to address this

IMGPROXY_TRUSTED_SIGNATURES: mydevtoken

Now you can just call https://mydomain.tld/mydevtoken/options

Did you find this interesting?

Consider subscribing 😊

No AI-generated content or SEO garbage.

Unsubscribe anytime