800 字
4 分钟

CattoPic - Self-Hosted Image Hosting on Cloudflare

Image hosting is an unavoidable topic for content creators. Third-party services come with concerns about content moderation, service discontinuation, or access speed limitations. Self-hosting raises the bar somewhat, but offers a balance between data sovereignty and user experience. CattoPic is an image hosting solution built on the Cloudflare ecosystem that deserves attention.

Serverless version project address:

Yuri-NagaSaki
/
CattoPic
Waiting for api.github.com...
00K
0K
0K
Waiting...

Go version project address:

Yuri-NagaSaki
/
ImageFlow
Waiting for api.github.com...
00K
0K
0K
Waiting...

What is CattoPic#

CattoPic is a self-hosted image hosting service providing complete functionality for uploading, managing, and serving images. Its distinctive feature is that the entire backend runs on Cloudflare’s free tier services, while the frontend can be deployed on Vercel. For users who already have a Cloudflare account, this translates to near-zero operating costs.

Core features include:

  • Multi-format image upload supporting JPEG, PNG, GIF, WebP, and AVIF
  • Automatic conversion to WebP and AVIF formats after upload, saving storage and bandwidth
  • Tag system for organizing images
  • Image expiration time settings for temporary images
  • Public random image API, useful for blog backgrounds or other scenarios
  • Automatic landscape/portrait detection with API filtering by orientation

Technical Architecture#

CattoPic employs a modern technology stack:

Frontend

  • Next.js 16 with React 19
  • Tailwind CSS for styling
  • Static export deployment, no server-side rendering required

Backend

  • Cloudflare Workers as the compute layer, using the Hono framework for API construction
  • Cloudflare D1 as the database, storing image metadata and configuration
  • Cloudflare R2 as object storage for image files
  • Cloudflare KV for caching
  • Cloudflare Queues for asynchronous tasks
  • Cron Triggers for scheduled cleanup of expired images

The entire backend runs on Cloudflare’s edge network, ensuring good response times and reliability.

Deployment Guide#

Deploying CattoPic involves two steps: configuring the Cloudflare backend services and deploying the frontend application.

Prerequisites#

  • A Cloudflare account
  • A Vercel account (for frontend deployment)
  • Node.js and pnpm installed locally
  • Wrangler CLI installed: pnpm add -g wrangler

Backend Deployment#

First, log in to Wrangler:

Terminal window
wrangler login

Create the required Cloudflare resources:

Terminal window
# Create R2 bucket
wrangler r2 bucket create cattopic-r2
# Create D1 database
wrangler d1 create CattoPic-D1
# Create KV namespace
wrangler kv namespace create CACHE_KV
# Create message queue
wrangler queues create cattopic-delete-queue

Record the IDs returned by these commands and update the worker/wrangler.toml configuration file:

[[d1_databases]]
binding = "DB"
database_name = "CattoPic-D1"
database_id = "your-database-id"
[[r2_buckets]]
binding = "R2"
bucket_name = "cattopic-r2"
[[kv_namespaces]]
binding = "CACHE_KV"
id = "your-kv-namespace-id"
[[queues.producers]]
queue = "cattopic-delete-queue"
binding = "DELETE_QUEUE"
[[queues.consumers]]
queue = "cattopic-delete-queue"
[vars]
R2_PUBLIC_URL = "your-r2-public-url"
ENVIRONMENT = "production"

Initialize the database:

Terminal window
cd worker
wrangler d1 execute CattoPic-D1 --remote --file=schema.sql

Deploy the Worker:

Terminal window
wrangler deploy

Upon completion, you will receive a Worker URL like https://cattopic-worker.your-account.workers.dev.

Creating an API Key#

Create an API key via the D1 console or by executing SQL through Wrangler:

INSERT INTO api_keys (key, name, created_at)
VALUES ('your-secret-key', 'Admin Dashboard', datetime('now'));

Frontend Deployment#

Fork the project repository to your GitHub account and import it in Vercel.

Configure environment variables:

NEXT_PUBLIC_API_URL=your-worker-url
NEXT_PUBLIC_REMOTE_PATTERNS=your-r2-public-url,your-worker-url

After deployment, access the frontend URL and log in with your API key to start using the service.

R2 Public Access Configuration#

The R2 bucket needs public access configured for images to be accessible externally. In the Cloudflare dashboard, navigate to R2 settings, bind a custom domain or enable public access, and record the resulting public URL.

Key Advantages#

Cost Efficiency

Cloudflare’s free tier is quite generous:

  • Workers: 100,000 requests per day
  • D1: 5GB storage, 5 million row reads
  • R2: 10GB storage, 1 million Class A operations, 10 million Class B operations
  • KV: 100,000 reads per day

For personal blogs or small to medium sites, these quotas are sufficient for daily use.

Performance

Leveraging Cloudflare’s global edge network, image access latency is low. The automatic format conversion feature generates WebP and AVIF versions, allowing modern browsers to receive smaller file sizes and faster loading times.

Data Sovereignty

Images are stored in your own R2 bucket, with data entirely under your control. No need to worry about third-party content moderation or service termination.

Feature Completeness

The management dashboard supports drag-and-drop upload, paste upload, and batch operations. The tag system and expiration time features provide flexible image management. The random image API is a practical bonus feature.

Current Limitations#

CattoPic has some usage limitations to be aware of before deployment:

File Size Limit

The frontend upload component limits individual files to 20MB. This limit is hardcoded in app/components/UploadSection.tsx. While the backend theoretically supports 100MB (Cloudflare Workers’ request body limit), the frontend intercepts first. To upload larger images, you need to modify the MAX_FILE_SIZE constant in the frontend code.

GIF Handling

GIF files are stored in their original format without conversion to WebP or AVIF. This is a deliberate choice considering the complexity of animated image conversion. I will also pay attention to the update of worker, and may consider other solutions to improve it.

Conclusion#

CattoPic provides an image hosting solution built on the Cloudflare ecosystem. It leverages Cloudflare’s free service tier to construct a fully-featured image hosting system, suitable for users who require data sovereignty and want to control costs. The deployment process requires some technical background, but the documentation is reasonably complete. The 20MB upload limit is typically sufficient for web images, and can be adjusted by modifying the code if needed.

If you are looking for a controllable, low-cost image hosting solution with decent performance, CattoPic is worth considering.

CattoPic - Self-Hosted Image Hosting on Cloudflare
https://catcat.blog/en/2025/12/cattopic-self-hosted-image-hosting.html
作者
猫猫博客
发布于
2025-12-11
许可协议
CC BY-NC-SA 4.0