Building a Real-Time On-the-Fly Image Optimization CDN with Imgproxy and Caddy Server on a VPS
Introduction: The Business Case for Real-Time Image Optimization
In modern web development and digital commerce, performance directly impacts the bottom line. Images often account for more than 60% of a webpage's total payload. Slow-loading visual assets degrade the user experience, increase bounce rates, and negatively impact search engine optimization (SEO) rankings. Traditionally, businesses addressed this challenge by pre-rendering multiple variations of a single image to support various device breakpoints and formats. However, this approach rapidly scales storage costs and complicates development workflows.
A more sophisticated, scalable alternative is On-the-Fly Image Optimization. By generating optimized images dynamically at the moment of request, businesses eliminate the need for redundant storage. This technical guide explores how to build a robust, production-grade real-time image CDN using Imgproxy and Caddy Server deployed on a Virtual Private Server (VPS).
Why Choose Imgproxy and Caddy Server?
Selecting the right open-source stack requires balancing performance, security, and ease of maintenance. The combination of Imgproxy and Caddy Server offers a highly efficient architecture tailored for modern business applications.
Imgproxy: High-Performance Visual Processing
Imgproxy is a fast, secure, and memory-efficient standalone server for resizing and converting images on the fly. Built in Go and powered by the libvips image processing library, it delivers exceptional speed while maintaining a minimal memory footprint.
- Speed and Efficiency: libvips is significantly faster and consumes less memory than traditional alternatives like ImageMagick.
- Security-First Architecture: Imgproxy mitigates remote code execution vulnerabilities by strictly validating incoming requests, supporting URL signature verification, and avoiding heavy execution wrappers.
- Format Adaptation: It automatically converts images to modern, high-compression formats like WebP and AVIF based on the client browser's capabilities.
Caddy Server: Enterprise-Grade Simplicity
Caddy serves as the entry point of our infrastructure, acting as a reverse proxy, load balancer, and caching layer in front of Imgproxy.
- Automated TLS/SSL: Caddy handles Let's Encrypt certificate issuance and renewals out-of-the-box, ensuring zero-maintenance HTTPS compliance.
- HTTP/3 Support: It natively supports modern protocols, reducing latency for mobile clients and unstable networks.
- Declarative Configuration: The human-readable Caddyfile simplifies complex routing, header manipulations, and caching rules.
Architecture Overview
Before proceeding to deployment, it is vital to understand the request lifecycle within this architecture:
- The client browser requests an image via a formatted URL from Caddy Server.
- Caddy checks its internal cache. If a cached version exists, it serves the asset instantly.
- If a cache miss occurs, Caddy proxies the request to the Imgproxy container.
- Imgproxy fetches the original asset from a remote origin (e.g., AWS S3, a persistent storage folder, or a primary web application server).
- Imgproxy processes the image in memory (resizing, compressing, converting format), returns it to Caddy, and Caddy caches and delivers the optimized asset to the client.
Security Note: In production environments, Imgproxy URLs should always be signed with a cryptographic key to prevent Denial of Service (DoS) attacks via arbitrary parameter manipulation.
Step-by-Step Deployment Guide
Step 1: Preparing the VPS Environment
Ensure your Linux VPS is updated and has the necessary dependencies installed. We will use Docker and Docker Compose to isolate and manage the Imgproxy service seamlessly.
sudo apt update && sudo apt upgrade -y
sudo apt install docker.io docker-compose -yStep 2: Configuring Imgproxy via Docker Compose
Create a dedicated directory for the infrastructure and define the docker-compose.yml file. This configuration initializes Imgproxy and secures it using signature keys.
version: '3.8'
services:
imgproxy:
image: darthsim/imgproxy:latest
container_name: imgproxy
restart: always
ports:
- "127.0.0.1:8081:8080"
environment:
- IMGPROXY_KEY=00000000000000000000000000000000
- IMGPROXY_SALT=00000000000000000000000000000000
- IMGPROXY_USE_ETAG=true
- IMGPROXY_AUTO_WEBP=true
- IMGPROXY_AUTO_AVIF=true
- IMGPROXY_MAX_SRC_RESOLUTION=50
volumes:
- ./cache:/tmpIn this snippet, IMGPROXY_KEY and IMGPROXY_SALT must be replaced with strong, hex-encoded cryptographic strings to enforce signature verification. The IMGPROXY_AUTO_WEBP and IMGPROXY_AUTO_AVIF flags instruct the server to serve highly optimized formats if the user's browser sends the appropriate Accept headers.
Step 3: Configuring Caddy Server as a Secure Reverse Proxy
Install Caddy on the host system or deploy it alongside Docker. Below is an optimized enterprise Caddyfile configuration that maps a custom domain, sets up proxying, handles header propagation, and implements long-term caching headers.
cdn.yourcompany.com {
# Compression
encode gzip zstd
# Security Headers
header {
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
Cache-Control "public, max-age=31536000, immutable"
}
# Proxy traffic to Imgproxy container
reverse_proxy 127.0.0.1:8081 {
header_up Host {http.reverse_proxy.upstream.hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}Run sudo systemctl reload caddy to apply changes. Caddy automatically negotiates SSL certificates via Let's Encrypt for cdn.yourcompany.com.
Performance Optimization and Caching Strategies
While dynamic generation saves disk space, processing thousands of images simultaneously can saturate CPU resources during high-traffic intervals. Implementing an effective caching strategy is paramount to ensure low latency.
Leveraging Edge Caching
To reduce infrastructure load, place a global Content Delivery Network (CDN) like Cloudflare or Fastly in front of your Caddy Server. By setting the Cache-Control header to public, max-age=31536000, immutable, edge nodes cache the optimized output indefinitely. Your VPS will only process an image once per unique variation, ensuring consistent millisecond delivery globally.
Conclusion
Building a self-hosted, on-the-fly image optimization system combines the financial efficiency of open-source software with enterprise-grade performance control. By pairing Imgproxy’s rapid visual processing engine with Caddy Server’s robust routing and automatic TLS layer, businesses can deploy an agile media CDN that minimizes data payloads, lowers infrastructure overhead, and maximizes site speed. As your traffic scales, this architecture scales alongside it, providing a dependable backbone for modern digital assets.
