Migrating from Cloudflare Images
This page covers how to move from Cloudflare Images (imagedelivery.net) to zimgx. It maps Cloudflare's URL parameters to zimgx equivalents and outlines the differences between the two.
URL mapping
Cloudflare Images:https://imagedelivery.net/<account-id>/<image-id>/<variant-or-options>https://your-domain.com/<image-path>/<transforms>The zimgx URL scheme is compatible with Cloudflare's path structure. A request for /<account-id>/<image-id>/<transforms> works out of the box — zimgx treats everything before the last =-containing segment as the image path. Set ZIMGX_ORIGIN_PATH_PREFIX to your account ID so zimgx strips it when fetching from origin.
Parameter translation
| Cloudflare | zimgx | Notes |
|---|---|---|
width=400 | w=400 | Shorter syntax |
height=300 | h=300 | |
quality=85 | q=85 | |
format=webp | f=webp | |
format=auto | f=auto (default) | Auto-negotiation is on by default |
fit=cover | fit=cover | Same values |
gravity=auto | g=smart or g=attention | Content-aware crop via libvips |
sharpen=1 | sharpen=1.0 | |
blur=5 | blur=5.0 |
Feature comparison
| Feature | Cloudflare Images | zimgx |
|---|---|---|
| Image upload | Required (via API) | Not needed — reads from your origin |
| Storage | Managed by Cloudflare | Your S3/R2 bucket or HTTP server |
| CDN | Built-in global CDN | Place any CDN in front (Cloudflare, Fastly, and others) |
| Format negotiation | Automatic | Automatic (via Accept header) |
| Caching | CDN cache | In-memory LRU with optional R2 tier |
| Named variants | Yes (dashboard/API) | No — transforms live in the URL |
| Pricing | Per-image stored and delivered | Self-hosted — your infrastructure costs |
| Animation | Native GIF/AVIF support | GIF/WebP with frame control |
| Self-hosted | No (managed service) | Yes (single binary) |
Migration steps
1. Keep your images where they are
If your images already live in R2 or S3, point zimgx at that bucket directly. You do not need to move anything.
2. Deploy zimgx
docker run -p 8080:8080 \
-e ZIMGX_ORIGIN_TYPE=r2 \
-e ZIMGX_R2_ENDPOINT=https://<account>.r2.cloudflarestorage.com \
-e ZIMGX_R2_ACCESS_KEY_ID=... \
-e ZIMGX_R2_SECRET_ACCESS_KEY=... \
-e ZIMGX_R2_BUCKET_ORIGINALS=my-images \
ghcr.io/officialunofficial/zimgx:latest3. Strip the account ID prefix
Cloudflare Images URLs include your account ID as the first path segment: /<account-id>/<image-id>/<transforms>. Your origin storage stores images by <image-id> alone.
Set ZIMGX_ORIGIN_PATH_PREFIX to your Cloudflare account ID so zimgx strips it before fetching from origin:
docker run -p 8080:8080 \
-e ZIMGX_ORIGIN_TYPE=r2 \
-e ZIMGX_ORIGIN_PATH_PREFIX=abc123 \
-e ZIMGX_R2_ENDPOINT=https://<account>.r2.cloudflarestorage.com \
-e ZIMGX_R2_ACCESS_KEY_ID=... \
-e ZIMGX_R2_SECRET_ACCESS_KEY=... \
-e ZIMGX_R2_BUCKET_ORIGINALS=my-images \
ghcr.io/officialunofficial/zimgx:latestWith this setting, a request for /abc123/photo-id/w=400 fetches origin key photo-id instead of abc123/photo-id.
4. Update your image URLs
Replace Cloudflare Image URLs in your app:
# Before (Cloudflare)
https://imagedelivery.net/abc123/photo-id/w=400,format=auto
# After (with ZIMGX_ORIGIN_PATH_PREFIX=abc123, keep the same path)
https://your-zimgx-host.com/abc123/photo-id/w=400
# Or without the prefix
https://your-zimgx-host.com/photo-id/w=400Format auto-negotiation is on by default. You do not need to specify f=auto.
5. Place a CDN in front
For production, put a CDN or reverse proxy in front of zimgx:
Client → CDN (Cloudflare, Fastly, nginx) → zimgx → R2/S3zimgx sets Cache-Control and ETag headers automatically. The CDN caches responses at the edge. zimgx's internal cache handles the origin layer.