Let’s be honest: you’re tired of uploading your sensitive screenshots, product mockups, or family photos to some web app that swears it deletes them after processing—but you have zero proof. You’ve tried ImageMagick CLI gymnastics, wrestled with Python scripts that break on macOS, and stared blankly at the “upload to Cloudinary” button one too many times. What if you could run 32 image tools—background removal, OCR, smart upscaling, EXIF stripping, PDF conversion, batch resizing—on your own machine, in one container, with zero internet calls, and zero telemetry? That’s stirling-image (272 GitHub stars as of May 2024, TypeScript, MIT licensed), and it’s not vaporware—it’s running on my homelab right now.
What Is Stirling-Image? (And Why It’s Not Just “Another Image Tool”)
Stirling-Image is the spiritual sibling of the well-known stirling-pdf — but laser-focused on images. While Stirling-PDF handles PDF manipulation in a clean, modular, self-hosted web UI, stirling-image extends that philosophy to raster and vector formats: JPEG, PNG, WEBP, SVG, HEIC (via libheif), TIFF, and even multi-page TIFFs. It bundles 32+ tools, all accessible from a single responsive web interface — no CLI required, but CLI is supported if you prefer curl or scripting.
Here’s the kicker: every operation runs locally. No image data ever hits a remote server — not for background removal, not for OCR, not for AI upscaling. The AI models (like realesrgan-x4plus for upscaling or u2net for background removal) are downloaded once on first run and cached in /app/models. Your CPU or GPU does the work — not some API endpoint in Singapore.
Unlike photopea.com, remove.bg, or TinyPNG, there’s no account, no watermark, no “free tier limits”, and no hidden data harvesting. Unlike gmic-qt or krita plugins, you don’t need to install desktop software or learn a new UI paradigm. It’s just a web app — http://localhost:8080 — served from Docker.
And yes — it even does OCR offline, using Tesseract 5.3.4 (bundled) with language packs you choose at runtime. No Google Vision API key needed. No tesseract binary to compile yourself.
Installation & Docker Setup (Spoiler: It’s Stupid Simple)
You don’t need Node, Python, or Rust toolchains. You just need Docker (24.0.0+ recommended, though it works fine on 20.10+). The image is multi-arch (amd64, arm64), built nightly, and published to GitHub Container Registry.
Here’s how I got it running on my Intel NUC (16GB RAM, Ubuntu 22.04):
docker run -d \
--name stirling-image \
-p 8080:8080 \
-v $(pwd)/stirling-image-data:/app/data \
-v $(pwd)/stirling-image-models:/app/models \
--restart unless-stopped \
ghcr.io/stirling-image/stirling-image:latest
That’s it. Visit http://localhost:8080, and you’re greeted with the clean, dark-mode-friendly UI. Your uploads go to /app/data, models cache to /app/models, and both persist across restarts.
Docker Compose for Production (with Reverse Proxy)
I run it behind Nginx (with basic auth) on my homelab. Here’s my docker-compose.yml with real-world hardening:
version: '3.8'
services:
stirling-image:
image: ghcr.io/stirling-image/stirling-image:v0.6.2
container_name: stirling-image
ports:
- "127.0.0.1:8080:8080"
volumes:
- ./data:/app/data
- ./models:/app/models
- ./config:/app/config
environment:
- TZ=Europe/Berlin
- STIRLING_IMAGE_MAX_UPLOAD_SIZE=104857600 # 100MB
- STIRLING_IMAGE_ENABLE_AI_TOOLS=true
- STIRLING_IMAGE_TESSDATA_DIR=/app/models/tessdata
- STIRLING_IMAGE_DEFAULT_LANGUAGE=eng+deu
restart: unless-stopped
# Optional GPU support (if you have NVIDIA)
# runtime: nvidia
# environment:
# - NVIDIA_VISIBLE_DEVICES=all
💡 Pro tip: I set
STIRLING_IMAGE_MAX_UPLOAD_SIZE=104857600because my NAS serves PNGs from camera raw exports — some hit 80MB. Default is 25MB, and yes, it does handle them. I’ve tested 120MB HEICs — it chugs (45 sec on my i5-1135G7), but it finishes.
The config volume is optional but useful: drop a config.json there to override defaults like theme, default tool, or UI labels. The config schema is well-documented — no guesswork.
How It Compares to Alternatives (Spoiler: It Wins on Privacy & Scope)
If you've been cobbling together tools like this, here’s how stirling-image stacks up:
vs.
convert/mogrify(ImageMagick):
Yes, IM is fast and scriptable — but no UI, no background removal, no OCR, no model management. You can script background removal withu2net+ Python, but you’re managing 5 repos, 3 Python venvs, and praying Tesseract finds its data dir. Stirling-image bundles and orchestrates all that — and adds a progress bar.vs.
gmic+gmic-qt:
Powerful, yes — but it’s a desktop app. No headless mode. No web API. No batch processing UI. And good luck runninggmicon ARM64 without compiling half of GNU.vs.
PhotopeaorPixlr:
Web-based, feature-rich, but your images do leave your machine — and you’re trusting a for-profit SaaS with raw product screenshots or medical imaging (yes, people use it for that). Stirling-image doesn’t even have an outbound HTTP client. The network interface is read-only.vs.
stirling-pdf:
They share the same design language and auth model (optional basic auth), but stirling-image has more tools — 32 vs. 22 in Stirling-PDF v0.10.0. And critically: it supports AI tools out-of-the-box, while Stirling-PDF’s AI features (like PDF summarization) are still experimental and require separate model setup.vs.
LunaorImageMagick Web(self-hosted web UIs):
Most are unmaintained, lack AI features, or are single-purpose (e.g., only compression). Stirling-image is modular: disable background removal if you don’t need it, but keep OCR and EXIF stripping.
Here’s the real differentiator: it’s the only self-hosted image suite that treats AI models as first-class citizens — without asking you to git clone Hugging Face repos or manage ONNX runtimes yourself. It downloads, validates, and caches them automatically — and shows clear model sizes in the UI (u2net: 121MB, realesrgan-x4plus: 283MB, etc.).
Why Self-Host This? (And Who Actually Needs It)
Let’s cut the fluff: this is not for your grandma who just wants to email a resized JPEG.
Stirling-image is for people who:
- Run a privacy-first homelab and treat “cloud API” like a swear word
- Process internal design assets (Figma exports, mockups, wireframes) and can’t risk sending them to remove.bg
- Work with medical, legal, or financial imaging (scanned documents, lab reports) where data residency is non-negotiable
- Are developers or DevOps folks who want a
/tools/imageendpoint for internal tooling — and yes, it has a documented REST API (POST /api/tools/resize,POST /api/tools/ocr, etc.) - Run Raspberry Pi 5 or ROCK 5B and need a lightweight, ARM64-native image processor (yes — it works on Pi 5 with 8GB RAM, though AI tools crawl without GPU)
Hardware-wise, here’s what I’ve tested:
| Hardware | CPU | RAM | AI Tools Work? | Notes |
|---|---|---|---|---|
| Intel NUC 11 (i5-1135G7) | 4c/8t | 16GB | ✅ Yes | Background removal: ~3s (1080p), upscaling (2x): ~12s |
| Raspberry Pi 5 (8GB) | ARM64 | 8GB | ⚠️ Limited | u2net works. realesrgan takes >3min (CPU-only). Disable AI in config if needed. |
| MacBook M1 Pro | ARM64 | 16GB | ✅ Yes (Metal) | Enable --platform linux/arm64 and set STIRLING_IMAGE_USE_METAL=true. 2x faster than Intel. |
It uses WebAssembly for lighter tools (resize, rotate, format convert) and Python + ONNX Runtime for AI-heavy ones. Memory usage spikes to ~1.2GB during upscaling (on my NUC), but idles at ~180MB. No swap thrashing observed — even with 4 concurrent uploads.
The Rough Edges (Because Nothing’s Perfect)
I’ve run stirling-image daily for 19 days. It’s stable — but here’s what’s not polished yet:
No user accounts or RBAC
It supports basic auth (viaSTIRLING_IMAGE_BASIC_AUTH_USERNAME), but there’s no role-based permissions. If you expose it internally, anyone with credentials can run OCR on any uploaded file. Fine for a single-user homelab — not for a 50-person engineering team.OCR language packs must be pre-downloaded
You can addfra,spa,chi_sim, etc., but you have tocurlthem into/app/models/tessdatamanually — the UI doesn’t auto-fetch them. I wrote a quick script:mkdir -p ./models/tessdata curl -L https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata \ -o ./models/tessdata/eng.traineddata curl -L https://github.com/tesseract-ocr/tessdata_best/raw/main/deu.traineddata \ -o ./models/tessdata/deu.traineddataHEIC support is “best effort”
It useslibheif— works for iPhone HEICs, but some Canon or DJI HEICs fail withheif_decode_image: invalid input. Not a dealbreaker (just convert withsips -s format jpeg input.HEICfirst), but worth knowing.No EXIF editing
You can strip EXIF, but you can’t inject or modify tags (e.g., add copyright or GPS). For that, you’ll still needexiftool. Not a bug — just scope.Docker image is ~1.8GB
Yeah, it includes Python 3.11, ONNX Runtime, Tesseract, FFmpeg, ImageMagick, and 5 AI models. You can prune unused models (deleterealesrgan-x4plus.onnxif you don’t upscale), but the base image stays chunky. On my 1Gbps LAN, pull time is ~90 sec.
Final Verdict: Should You Deploy It?
Yes — if you value privacy, control, and consolidation over “lightweight”.
I replaced three separate tools with stirling-image:
- A
convertscript that resized marketing banners → now a/tools/resizeAPI call - A
backgroundremoverPython CLI I maintained for client work → replaced with/tools/remove-bg - A
tesseractDocker wrapper for OCR-ing scanned invoices → gone. Now it’s one UI click.
It’s not perfect — but it’s shippable, well-documented, MIT-licensed, and the maintainer (a single dev, @stirling-tools) replies to issues within 24 hours. With 272 stars in <4 months, this project has real momentum.
The TL;DR:
✅ Runs entirely offline, zero telemetry
✅ 32 tools — including real AI (not just “smart” filters)
✅ Docker-first, ARM64 + x86_64, GPU optional
✅ Actively maintained (v0.6.2 released 3 days ago)
❌ No RBAC, no EXIF editing, HEIC edge cases, big image
If you’re already running docker-compose for other self-hosted apps — add stirling-image. It’ll be the most-used image tool in your stack. And when your CEO asks, “Where do our product screenshots go when we resize them?” — you can point to localhost:8080 and say, “They never leave this machine.”
I’m keeping it. And I’m not looking back.
Comments