An image hosting service built with FastAPI. Upload images via URL or base64 data and serve them through simple HTTP endpoints.
This is made for Hoyo Buddy.
- Multiple Upload Methods: Upload via URL or base64 encoded data
- Flexible Storage: Local filesystem or S3-compatible storage (AWS S3, Cloudflare R2, etc.)
- Simple API: RESTful endpoints with JSON responses
- File Management: List, count, get total size, and delete uploaded files
- Health Monitoring: Built-in health check endpoint
- Secure: API key authentication for uploads and deletions
- Format Conversion: All uploads saved as PNG format
- Random Filenames: 16-character random filenames for privacy
- Upload Control: Can temporarily disable uploads via configuration
POST /upload
Authentication: Requires Authorization: Bearer <your-api-key> header
Request Body (JSON):
{
"source": "https://example.com/image.jpg"
}OR
{
"source": "base64-encoded-image-data..."
}Response:
{
"filename": "abcdef1234567890.png"
}GET /{filename}
Serves the uploaded image file directly (for local storage) or redirects to the S3 URL (for S3 storage).
DELETE /{filename}
Authentication: Requires Authorization: Bearer <your-api-key> header
Response:
{
"message": "File deleted"
}GET /files
Returns list of all files with their sizes.
GET /files/count # Get total file count
GET /files/size # Get total storage size
GET /health
Returns service health status.
- Python 3.12+
- uv (recommended) or pip
-
Clone the repository:
git clone <your-repo-url> cd image-host
-
Install dependencies:
# Using uv (recommended) uv sync # Or using pip pip install .
-
Set up environment variables:
# Create .env file echo "API_KEY=your-secret-api-key-here" > .env
-
Create storage directory (for local storage only):
mkdir -p files
# Using uv
uv run uvicorn main:app --reload --port 9078
# Or directly
uv run python main.pyOption 1: Using PM2 (recommended)
# Install PM2 globally
npm install -g pm2
# Start the service
pm2 start pm2.json
# Monitor logs
pm2 logs image-host
# Stop/restart
pm2 stop image-host
pm2 restart image-hostOption 2: Using Uvicorn directly
uv run uvicorn main:app --host 0.0.0.0 --port 9078Environment variables (set in .env file):
Required:
API_KEY: Secret key for upload authentication
Optional:
REPO_URL: Repository URL for redirect on root path (default: https://github.com/seriaati/image-host)UPLOADS_ENABLED: Whether uploading is enabled (default: true)FILESIZE_LIMIT: Maximum file size in bytes (default: 20MB / 20971520 bytes)
Storage Configuration:
STORAGE_TYPE: Storage backend - "local" (default) or "s3"
S3 Storage (required when STORAGE_TYPE=s3):
S3_ENDPOINT_URL: S3 endpoint URL (e.g., https://s3.amazonaws.com for AWS, https://[account-id].r2.cloudflarestorage.com for Cloudflare R2)S3_ACCESS_KEY_ID: S3 access key IDS3_SECRET_ACCESS_KEY: S3 secret access keyS3_BUCKET_NAME: S3 bucket nameS3_REGION: S3 region (default: "auto")S3_CUSTOM_DOMAIN: Custom domain for file URLs (optional, e.g., https://cdn.example.com)
Files are stored in the files/ directory on the local filesystem.
Supports AWS S3, Cloudflare R2, and other S3-compatible services. Configure using environment variables:
# Example for AWS S3
STORAGE_TYPE=s3
S3_ENDPOINT_URL=https://s3.amazonaws.com
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key
S3_BUCKET_NAME=your-bucket-name
S3_REGION=us-east-1
# Example for Cloudflare R2
STORAGE_TYPE=s3
S3_ENDPOINT_URL=https://[account-id].r2.cloudflarestorage.com
S3_ACCESS_KEY_ID=your-r2-access-key
S3_SECRET_ACCESS_KEY=your-r2-secret-key
S3_BUCKET_NAME=your-r2-bucket
S3_REGION=auto
S3_CUSTOM_DOMAIN=https://your-r2-custom-domain.comAll uploaded images are converted to PNG format with randomly generated 16-character filenames regardless of storage backend.
curl -X POST "http://localhost:9078/upload" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"source": "https://example.com/image.jpg"}'curl -X POST "http://localhost:9078/upload" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"source": "/9j/4AAQ..."}'curl "http://localhost:9078/files/count"
curl "http://localhost:9078/files/size"- Set a strong, unique
API_KEYin production - Consider running behind a reverse proxy (nginx, Cloudflare)
- Monitor file storage usage to prevent disk space issues
- Implement rate limiting for production deployments
For development setup, code style guidelines, and contribution instructions, see CONTRIBUTING.md.