Deploying Flyimg
Introduction
Flyimg is a powerful, Dockerized image processing service that resizes, crops, and compresses images on the fly. Think of it as your own self-hosted Cloudinary or Imgix alternative. Built on top of ImageMagick, Flyimg delivers optimized images in modern formats like AVIF, WebP, JPEG XL (JXL), and MozJPEG, with an intelligent caching system that ensures lightning-fast response times for repeated requests.
Flyimg stands out for:
- Format Flexibility: Automatic format negotiation serves AVIF to supported browsers, with WebP and optimized JPEG fallbacks
- On-the-Fly Processing: No pre-processing needed—pass image URLs with transformation parameters and Flyimg handles the rest
- Smart Caching: Processed images are cached for instant delivery on subsequent requests
- Advanced Features: Face detection, smart cropping, automatic orientation correction, and more
- Modern Compression: MozJPEG for superior JPEG quality, AVIF for cutting-edge compression, and WebP for wide compatibility
- Simple API: URL-based image transformations with intuitive parameter syntax
Key capabilities include:
- Dynamic Resizing: Width, height, and aspect ratio control with multiple fit modes
- Smart Cropping: Intelligent cropping with face detection and focal point preservation
- Quality Control: Adjustable compression levels per format for optimal file size vs quality balance
- Format Conversion: Automatic output format selection or forced conversion
- Image Filters: Blur, sharpen, grayscale, and more through URL parameters
- Watermarking: Add text or image watermarks dynamically
- Metadata Stripping: Remove EXIF data for privacy and smaller file sizes
- JPEG XL Support: Latest generation image format with excellent compression
Deploying Flyimg on Klutch.sh gives you a production-ready image processing service with automatic scaling, persistent caching, and zero infrastructure management. This guide walks you through the complete setup process, from configuration to optimization.
Prerequisites
Before deploying Flyimg to Klutch.sh, ensure you have:
- A Klutch.sh account
- A GitHub account with a repository for your Flyimg project
- Docker installed locally for testing (optional but recommended)
- Basic understanding of image formats and web performance optimization
- Optional: A Redis instance for distributed rate limiting (recommended for production)
Understanding Flyimg Architecture
Flyimg consists of several key components:
- Web Server (Nginx): Handles incoming HTTP requests and serves cached images
- PHP-FPM: Processes image transformation requests
- ImageMagick: The underlying image processing engine
- Redis (Optional): Rate limiting and distributed caching
- File System Cache: Stores processed images for fast retrieval
When a request comes in, Flyimg:
- Checks if the transformed image exists in cache
- If cached, serves it immediately (extremely fast)
- If not cached, fetches the source image, applies transformations, caches the result, then serves it
- Subsequent requests for the same transformation are served from cache
Installation and Setup
Step 1: Create Your Project Directory
Create a new directory for your Flyimg deployment:
mkdir flyimg-klutchcd flyimg-klutchgit initStep 2: Create the Dockerfile
Flyimg provides an official Docker image, but we’ll create a custom Dockerfile that allows for configuration customization. Create a Dockerfile in your project root:
# Use the official Flyimg image as baseFROM flyimg/flyimg:latest
# Set environment variables for PHP and ImageMagickENV PHP_MEMORY_LIMIT=512M \ PHP_MAX_EXECUTION_TIME=120 \ PHP_POST_MAX_SIZE=50M \ PHP_UPLOAD_MAX_FILESIZE=50M
# Flyimg configuration will be mounted or set via environment variables# The application runs on port 80 internallyEXPOSE 80
# The base image already has the correct entrypoint# It starts both nginx and php-fpm via s6-overlayDockerfile Explanation:
- Base Image: Uses the official Flyimg image with all dependencies pre-installed
- PHP Configuration: Increases memory limits and upload sizes for handling large images
- Port 80: Flyimg serves HTTP traffic on port 80 (standard web server port)
- s6-overlay: The base image uses s6 to manage both Nginx and PHP-FPM processes
Step 3: Create Configuration File (Optional)
Create a parameters.yml file to customize Flyimg’s behavior:
# Flyimg Configuration# See https://docs.flyimg.io/configuration for all options
# Application Settingsapp_secret: 'your-secret-key-change-this-in-production'
# Default image quality settingsdefault_quality: 90mozjpeg_quality: 85webp_quality: 80avif_quality: 70
# Output format preferencesdefault_output: 'auto' # auto, jpg, png, webp, avif, gif, jxloutput_formats: - jpg - webp - avif - png - jxl
# Storage settingsstorage_system: 'local' # local or s3storage_path: '/var/www/html/web/uploads/'
# Cache settingscache_system: 'file' # file or redisfile_cache_path: '/var/www/html/web/cache/'cache_ttl: 86400 # 24 hours in seconds
# Redis settings (if using Redis for caching or rate limiting)redis_enabled: falseredis_host: 'redis'redis_port: 6379redis_password: ''redis_database: 0
# Rate limiting (requires Redis)rate_limit_enabled: falserate_limit_requests: 100rate_limit_per_seconds: 60
# Security settingsallowed_domains: - '*' # Restrict to specific domains in production
# Image processing limitsmax_image_size: 10485760 # 10MB in bytesmax_output_dimension: 4000 # Maximum width or height
# Face detection (requires OpenCV)face_detection_enabled: true
# Performance optimizationoptimize_memory_usage: trueextract_metadata: false # Strip EXIF data for smaller filesStep 4: Create .dockerignore File
Create a .dockerignore file to exclude unnecessary files:
.git.github.gitignoreREADME.md*.log.env.DS_Storenode_modulesweb/uploads/*web/cache/*Step 5: Test Locally (Optional)
Test your Flyimg setup locally before deploying:
# Build the Docker imagedocker build -t flyimg-klutch .
# Run with default configurationdocker run -d \ --name flyimg-test \ -p 8080:80 \ flyimg-klutch
# Or run with custom parameters.ymldocker run -d \ --name flyimg-test \ -p 8080:80 \ -v $(pwd)/parameters.yml:/var/www/html/config/parameters.yml \ flyimg-klutchTest the service by visiting:
http://localhost:8080/upload/w_300,h_250,q_90/https://flyimg.io/demo-images/Citroen-DS.jpgYou should see a resized and compressed version of the demo image.
Cleanup after testing:
docker stop flyimg-testdocker rm flyimg-testStep 6: Optional - Local Development with Docker Compose
For local development with Redis, create a docker-compose.yml file:
version: '3.8'
services: flyimg: build: . ports: - "8080:80" volumes: - ./parameters.yml:/var/www/html/config/parameters.yml - flyimg-cache:/var/www/html/web/cache - flyimg-uploads:/var/www/html/web/uploads environment: - REDIS_HOST=redis - REDIS_PORT=6379 depends_on: - redis
redis: image: redis:7-alpine command: redis-server --appendonly yes volumes: - redis-data:/data
volumes: flyimg-cache: flyimg-uploads: redis-data:Note: Docker Compose is only for local development. Klutch.sh doesn’t support Docker Compose deployments, but you can deploy Flyimg and Redis as separate applications.
Step 7: Push to GitHub
Commit your project files to GitHub:
git add Dockerfile .dockerignore parameters.ymlgit commit -m "Add Flyimg configuration for Klutch.sh deployment"git branch -M maingit remote add origin https://github.com/yourusername/flyimg-klutch.gitgit push -u origin mainDeploying to Klutch.sh
Now that your Flyimg project is ready on GitHub, let’s deploy it to Klutch.sh.
Deployment Steps
-
Log in to Klutch.sh
Navigate to klutch.sh/app and sign in to your account.
-
Create a New Project
Go to Create Project and name it something like “Image Processing Service” or “Flyimg CDN”.
-
Deploy Redis (Optional but Recommended)
For production deployments with rate limiting, deploy Redis first:
- Follow our Redis deployment guide
- Configure it with TCP traffic on internal port 6379
- Note the Redis connection details (e.g.,
redis-app.klutch.sh:8000) - Set a strong Redis password using
REDIS_PASSWORDenvironment variable
-
Create a New App for Flyimg
Navigate to Create App to configure your Flyimg deployment.
-
Select Your Repository
- Choose GitHub as your Git source
- Select the repository containing your Flyimg Dockerfile
- Choose the branch you want to deploy (typically
main)
Klutch.sh will automatically detect the Dockerfile in your repository root and use it for the build.
-
Configure Traffic Type
- Traffic Type: Select HTTP (Flyimg is a web application)
- Internal Port: Set to
80(the port Nginx serves on inside the container)
This configuration routes HTTP traffic from your Klutch.sh app URL to the Flyimg service.
-
Set Environment Variables
Configure the following environment variables in the Klutch.sh dashboard:
Required Environment Variables:
APP_SECRET: A random secret key for security (generate withopenssl rand -hex 32)
Redis Configuration (if using Redis):
REDIS_ENABLED: Set totrueREDIS_HOST: Your Redis app hostname (e.g.,redis-app.klutch.sh)REDIS_PORT:8000(Klutch.sh’s external TCP port)REDIS_PASSWORD: Your Redis passwordREDIS_DATABASE:0(default database number)
Rate Limiting (requires Redis):
RATE_LIMIT_ENABLED: Set totrueRATE_LIMIT_REQUESTS:100(number of requests allowed)RATE_LIMIT_PER_SECONDS:60(time window in seconds)
Image Processing Limits:
MAX_IMAGE_SIZE:10485760(10MB in bytes, adjust as needed)MAX_OUTPUT_DIMENSION:4000(maximum width or height in pixels)
PHP Configuration:
PHP_MEMORY_LIMIT:512M(increase for processing large images)PHP_MAX_EXECUTION_TIME:120(seconds, for slow image sources)
Quality Settings:
DEFAULT_QUALITY:90(general quality setting)MOZJPEG_QUALITY:85(JPEG compression quality)WEBP_QUALITY:80(WebP compression quality)AVIF_QUALITY:70(AVIF compression quality - lower values work well)
Security Tip: Never commit sensitive values like
APP_SECRETorREDIS_PASSWORDto your repository. Always set them as environment variables in Klutch.sh. -
Attach Persistent Volumes
Flyimg benefits greatly from persistent storage for caching processed images. Configure these volumes:
Volume 1 - Image Cache:
- Mount Path:
/var/www/html/web/cache - Size: 20GB or more (depending on your expected traffic and image diversity)
Volume 2 - Uploaded Images (if storing uploads):
- Mount Path:
/var/www/html/web/uploads - Size: 10GB or more (if you plan to allow image uploads)
Important: Persistent volumes ensure processed images remain cached across container restarts, significantly improving performance and reducing processing load.
- Mount Path:
-
Configure Additional Settings
- Region: Select the region closest to your users for optimal latency
- Compute Resources:
- Minimum: 1 CPU, 1GB RAM (for light usage)
- Recommended: 2 CPU, 2GB RAM (for moderate traffic)
- High Traffic: 4+ CPU, 4GB+ RAM (for heavy image processing workloads)
- Instances: Start with 1 instance; scale horizontally as traffic grows
-
Deploy Your Application
Click “Create” to start the deployment. Klutch.sh will:
- Automatically detect and build from your Dockerfile
- Install all dependencies (ImageMagick, PHP, Nginx)
- Attach persistent volumes to the specified mount paths
- Start the Flyimg service
- Assign a URL for accessing your image processing service
-
Verify Deployment
Once deployment completes, you’ll receive a URL like
example-app.klutch.sh. Test your Flyimg instance:-
Health Check: Visit
https://example-app.klutch.sh/- you should see “Hello from Flyimg!” -
Image Processing: Try resizing an image:
https://example-app.klutch.sh/upload/w_300,h_200,q_90/https://flyimg.io/demo-images/Citroen-DS.jpg
-
Getting Started with Flyimg
Now that Flyimg is deployed, let’s explore how to transform images using URL parameters.
Basic URL Structure
Flyimg uses a simple URL structure for image transformations:
https://example-app.klutch.sh/upload/{parameters}/{image-url}- Parameters: Comma-separated options (e.g.,
w_300,h_200,q_90) - Image URL: The source image URL (can be absolute or relative)
Common Image Transformations
Resize by Width:
<img src="https://example-app.klutch.sh/upload/w_500/https://example.com/image.jpg" />Resize by Width and Height:
<img src="https://example-app.klutch.sh/upload/w_500,h_300/https://example.com/image.jpg" />Resize with Quality Control:
<img src="https://example-app.klutch.sh/upload/w_500,h_300,q_85/https://example.com/image.jpg" />Force Output Format:
<!-- Force WebP output --><img src="https://example-app.klutch.sh/upload/w_500,o_webp/https://example.com/image.jpg" />
<!-- Force AVIF output --><img src="https://example-app.klutch.sh/upload/w_500,o_avif/https://example.com/image.jpg" />Automatic Format Selection:
<!-- Flyimg serves AVIF to supported browsers, WebP as fallback, then JPEG --><img src="https://example-app.klutch.sh/upload/w_500,o_auto/https://example.com/image.jpg" />Available Parameters
| Parameter | Description | Example |
|---|---|---|
w_ | Width in pixels | w_500 |
h_ | Height in pixels | h_300 |
q_ | Quality (1-100) | q_90 |
o_ | Output format | o_webp, o_avif, o_auto |
c_ | Crop mode (1=crop, 0=no crop) | c_1 |
r_ | Rotate degrees | r_90 |
bg_ | Background color (hex) | bg_FFFFFF |
blur_ | Blur radius | blur_5 |
sharpen_ | Sharpen amount | sharpen_80 |
f_ | Face detection crop | f_1 |
strip_ | Strip metadata | strip_1 |
mozjpeg_ | Use MozJPEG | mozjpeg_1 |
Advanced Use Cases
Responsive Images with srcset:
<img src="https://example-app.klutch.sh/upload/w_800,o_auto/https://example.com/hero.jpg" srcset=" https://example-app.klutch.sh/upload/w_400,o_auto/https://example.com/hero.jpg 400w, https://example-app.klutch.sh/upload/w_800,o_auto/https://example.com/hero.jpg 800w, https://example-app.klutch.sh/upload/w_1200,o_auto/https://example.com/hero.jpg 1200w, https://example-app.klutch.sh/upload/w_1600,o_auto/https://example.com/hero.jpg 1600w " sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px" alt="Hero image"/>Product Images with Smart Crop:
<!-- Square product thumbnail with face detection --><img src="https://example-app.klutch.sh/upload/w_300,h_300,c_1,f_1,o_auto/https://example.com/product.jpg" />Optimized Hero Images:
<!-- Large hero with aggressive AVIF compression --><img src="https://example-app.klutch.sh/upload/w_1920,h_1080,q_75,o_avif/https://example.com/hero.jpg" />Sample Code: Integrating Flyimg
Here are examples of how to integrate Flyimg into various applications:
Node.js/Express Example
const express = require('express');const app = express();
const FLYIMG_BASE_URL = 'https://example-app.klutch.sh';
// Helper function to generate image URLsfunction flyimgUrl(imageUrl, options = {}) { const { width = null, height = null, quality = 90, format = 'auto', crop = false, faceDetection = false } = options;
const params = []; if (width) params.push(`w_${width}`); if (height) params.push(`h_${height}`); if (quality) params.push(`q_${quality}`); if (format) params.push(`o_${format}`); if (crop) params.push('c_1'); if (faceDetection) params.push('f_1');
const paramString = params.join(','); return `${FLYIMG_BASE_URL}/upload/${paramString}/${imageUrl}`;}
// API endpoint that returns optimized image URLsapp.get('/api/images/:id', (req, res) => { const originalUrl = `https://storage.example.com/images/${req.params.id}.jpg`;
res.json({ thumbnail: flyimgUrl(originalUrl, { width: 200, height: 200, crop: true }), medium: flyimgUrl(originalUrl, { width: 800 }), large: flyimgUrl(originalUrl, { width: 1600 }), hero: flyimgUrl(originalUrl, { width: 1920, height: 1080, quality: 85 }) });});
app.listen(3000, () => { console.log('Server running on port 3000');});React Component Example
import React from 'react';
const FLYIMG_BASE_URL = 'https://example-app.klutch.sh';
function generateFlyimgUrl(imageUrl, options = {}) { const { width, height, quality = 90, format = 'auto', crop = false } = options;
const params = []; if (width) params.push(`w_${width}`); if (height) params.push(`h_${height}`); params.push(`q_${quality}`); params.push(`o_${format}`); if (crop) params.push('c_1');
return `${FLYIMG_BASE_URL}/upload/${params.join(',')}/${imageUrl}`;}
function OptimizedImage({ src, alt, width, height, className }) { const sizes = [400, 800, 1200, 1600];
const srcSet = sizes .map(w => `${generateFlyimgUrl(src, { width: w })} ${w}w`) .join(', ');
return ( <img src={generateFlyimgUrl(src, { width: 800 })} srcSet={srcSet} sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px" alt={alt} width={width} height={height} className={className} loading="lazy" /> );}
// Usagefunction ProductCard({ product }) { return ( <div className="product-card"> <OptimizedImage src={product.imageUrl} alt={product.name} width={300} height={300} /> <h3>{product.name}</h3> <p>${product.price}</p> </div> );}
export default ProductCard;Python/Flask Example
from flask import Flask, jsonifyfrom urllib.parse import quote
app = Flask(__name__)
FLYIMG_BASE_URL = 'https://example-app.klutch.sh'
def flyimg_url(image_url, width=None, height=None, quality=90, output_format='auto', crop=False, face_detection=False): """Generate Flyimg transformation URL""" params = []
if width: params.append(f'w_{width}') if height: params.append(f'h_{height}') if quality: params.append(f'q_{quality}') if output_format: params.append(f'o_{output_format}') if crop: params.append('c_1') if face_detection: params.append('f_1')
param_string = ','.join(params) encoded_url = quote(image_url, safe='')
return f'{FLYIMG_BASE_URL}/upload/{param_string}/{image_url}'
@app.route('/api/images/<image_id>')def get_image_urls(image_id): original_url = f'https://storage.example.com/images/{image_id}.jpg'
return jsonify({ 'thumbnail': flyimg_url(original_url, width=200, height=200, crop=True), 'medium': flyimg_url(original_url, width=800), 'large': flyimg_url(original_url, width=1600), 'optimized': flyimg_url(original_url, width=1200, quality=85, output_format='avif') })
@app.route('/api/responsive-image/<path:image_url>')def get_responsive_image(image_url): sizes = [400, 800, 1200, 1600]
srcset = [ { 'url': flyimg_url(image_url, width=size), 'width': size } for size in sizes ]
return jsonify({ 'src': flyimg_url(image_url, width=800), 'srcset': srcset })
if __name__ == '__main__': app.run(debug=True)PHP Example
<?php
class FlyimgHelper { private $baseUrl;
public function __construct($baseUrl = 'https://example-app.klutch.sh') { $this->baseUrl = rtrim($baseUrl, '/'); }
public function generateUrl($imageUrl, $options = []) { $defaults = [ 'width' => null, 'height' => null, 'quality' => 90, 'format' => 'auto', 'crop' => false, 'faceDetection' => false, 'blur' => null, 'sharpen' => null ];
$options = array_merge($defaults, $options); $params = [];
if ($options['width']) { $params[] = 'w_' . $options['width']; } if ($options['height']) { $params[] = 'h_' . $options['height']; } if ($options['quality']) { $params[] = 'q_' . $options['quality']; } if ($options['format']) { $params[] = 'o_' . $options['format']; } if ($options['crop']) { $params[] = 'c_1'; } if ($options['faceDetection']) { $params[] = 'f_1'; } if ($options['blur']) { $params[] = 'blur_' . $options['blur']; } if ($options['sharpen']) { $params[] = 'sharpen_' . $options['sharpen']; }
$paramString = implode(',', $params); return "{$this->baseUrl}/upload/{$paramString}/{$imageUrl}"; }
public function responsiveImageSet($imageUrl, $sizes = [400, 800, 1200, 1600]) { $srcset = []; foreach ($sizes as $width) { $url = $this->generateUrl($imageUrl, ['width' => $width]); $srcset[] = "{$url} {$width}w"; } return implode(', ', $srcset); }}
// Usage$flyimg = new FlyimgHelper('https://example-app.klutch.sh');
// Generate product thumbnail$thumbnail = $flyimg->generateUrl( 'https://example.com/product.jpg', ['width' => 300, 'height' => 300, 'crop' => true]);
// Generate responsive image set$srcset = $flyimg->responsiveImageSet('https://example.com/hero.jpg');
echo "<img src='{$thumbnail}' alt='Product' />";echo "<img srcset='{$srcset}' sizes='100vw' alt='Hero' />";Production Best Practices
Performance Optimization
1. Use Persistent Volumes
Ensure cache and upload volumes are properly configured. Cached images load instantly, while uncached images require processing time.
2. Leverage CDN
Place a CDN like Cloudflare in front of your Flyimg deployment:
- Set long cache TTLs for transformed images (they don’t change)
- Enable Cloudflare’s image optimization on top of Flyimg for double optimization
- Reduce load on your Flyimg instance
3. Optimize Quality Settings
Different formats have different optimal quality settings:
- AVIF: 65-75 quality provides excellent results
- WebP: 75-85 quality balances size and quality
- JPEG: 85-90 quality for photographic content
- PNG: Use for images requiring transparency only
4. Use Format Auto-Negotiation
Always use o_auto to let Flyimg serve the best format based on browser support:
/upload/w_800,o_auto/image.jpg5. Implement Lazy Loading
Use native lazy loading for images below the fold:
<img src="..." loading="lazy" />Security Recommendations
1. Restrict Allowed Domains
Update your parameters.yml to only allow images from trusted domains:
allowed_domains: - 'example.com' - 'cdn.example.com' - 'storage.example.com'2. Enable Rate Limiting
Deploy Redis and enable rate limiting to prevent abuse:
rate_limit_enabled: truerate_limit_requests: 100rate_limit_per_seconds: 603. Set Resource Limits
Limit maximum image dimensions and file sizes:
max_image_size: 10485760 # 10MBmax_output_dimension: 4000 # 4000px max width/height4. Use Environment Variables for Secrets
Never commit sensitive data. Use Klutch.sh environment variables for:
APP_SECRETREDIS_PASSWORD- S3 credentials (if using S3 storage)
5. Monitor Access Logs
Regularly review Nginx access logs for suspicious patterns:
- Excessive requests from single IPs
- Requests for very large images
- Unusual transformation parameters
Scaling Considerations
1. Horizontal Scaling
Increase the number of Flyimg instances in Klutch.sh as traffic grows. Flyimg is stateless (with file cache in persistent volumes), making horizontal scaling straightforward.
2. Vertical Scaling
For processing-intensive workloads:
- Increase CPU for faster image processing
- Increase RAM for handling larger images
- Monitor CPU and memory usage in Klutch.sh dashboard
3. Cache Volume Size
Monitor cache volume usage:
- Start with 20GB and adjust based on your image diversity
- Larger caches reduce processing load but increase storage costs
- Implement cache cleanup strategies for old or rarely-accessed images
4. Separate Storage from Processing
For very high traffic:
- Use S3-compatible storage for source images
- Let Flyimg cache processed images on local volumes
- This separates storage from processing concerns
Monitoring and Maintenance
Key Metrics to Monitor:
- Response Time: Average time to serve images (cached vs uncached)
- Cache Hit Rate: Percentage of requests served from cache
- Processing Time: Time to transform new images
- Error Rate: Failed image processing attempts
- Volume Usage: Cache and upload volume disk space
- CPU/Memory Usage: Resource utilization patterns
Maintenance Tasks:
- Cache Cleanup: Periodically remove old cached images to free space
- Log Rotation: Ensure Nginx and PHP logs don’t fill disk
- Dependency Updates: Update Flyimg to latest version for security patches
- Performance Testing: Load test your deployment before major traffic events
Backup and Recovery
What to Back Up:
- Configuration Files:
parameters.ymland custom settings - Uploaded Images: If storing uploads (mount
/var/www/html/web/uploads) - Environment Variables: Document all Klutch.sh environment variables
Cache Volumes: No need to back up cache volumes—they can be rebuilt on demand.
Recovery Process:
- Redeploy Flyimg from GitHub repository
- Restore environment variables in Klutch.sh
- Restore uploaded images to volume (if applicable)
- Cache will rebuild automatically as requests come in
Troubleshooting
Images Not Loading
Symptom: Requests return 404 or timeout
Solutions:
- Verify the source image URL is accessible from your Flyimg instance
- Check
allowed_domainsconfiguration if domain restrictions are enabled - Ensure the internal port is set to 80 in Klutch.sh
- Review deployment logs for errors during image fetching
Slow Image Processing
Symptom: First-time image requests are very slow
Solutions:
- Increase PHP memory limit (
PHP_MEMORY_LIMIT=1024M) - Increase execution time (
PHP_MAX_EXECUTION_TIME=180) - Reduce source image size before transformation
- Check if the source image server is slow to respond
- Consider upgrading to more CPU cores in Klutch.sh
Cache Not Working
Symptom: Every request processes the image again
Solutions:
- Verify persistent volume is attached at
/var/www/html/web/cache - Check volume has sufficient disk space
- Ensure file permissions allow write access (should be automatic)
- Review cache configuration in
parameters.yml
Out of Memory Errors
Symptom: Image processing fails with memory errors
Solutions:
- Increase
PHP_MEMORY_LIMITenvironment variable - Reduce
MAX_IMAGE_SIZEto reject very large source images - Upgrade to a plan with more RAM in Klutch.sh
- Enable
optimize_memory_usagein parameters.yml
Rate Limiting Not Working
Symptom: No rate limiting despite configuration
Solutions:
- Ensure Redis is deployed and accessible
- Verify
REDIS_ENABLED=truein environment variables - Check Redis connection details (
REDIS_HOST,REDIS_PORT,REDIS_PASSWORD) - Confirm
RATE_LIMIT_ENABLED=trueis set - Review Redis logs for connection errors
AVIF/WebP Not Working
Symptom: Modern formats not being served
Solutions:
- Verify ImageMagick has support for these formats (Flyimg image includes them)
- Check browser’s
Acceptheader includes the format - Use
o_aviforo_webpto force the format (for testing) - Review Flyimg logs for format conversion errors
Additional Resources
- Klutch.sh Documentation
- Official Flyimg Documentation
- Flyimg GitHub Repository
- Flyimg Docker Hub
- ImageMagick Documentation
- Deploying Redis on Klutch.sh
- Imagor Alternative (Go-based)
- Klutch.sh Volumes Guide
- Klutch.sh Networking Guide
Conclusion
Deploying Flyimg on Klutch.sh gives you a powerful, self-hosted image processing service that automatically optimizes images for modern web performance. With support for cutting-edge formats like AVIF and JPEG XL, intelligent caching, and a simple URL-based API, Flyimg is an excellent alternative to expensive commercial image CDNs. By following this guide, you’ve set up a production-ready deployment with persistent caching, optional Redis integration for rate limiting, and all the configuration needed to handle real-world traffic at scale.