Skip to content

BlockG-ws/akkoproxy

Repository files navigation

Akkoma Media Proxy

A fast caching and optimization media proxy for Akkoma/Pleroma, built in Rust.

Features

  • Caching Reverse Proxy: Caches media and proxy requests to reduce load on upstream servers
  • Header Preservation: Preserves all upstream headers by default, including redirects (302) with Location headers
  • Image Format Conversion: Automatically converts images to modern formats (AVIF, WebP) based on client Accept headers
  • Path Filtering: Only handles /media and /proxy endpoints for security
  • Performance: Built with Tokio async runtime for high concurrency
  • Flexible Configuration: TOML-based configuration with environment variable and CLI overrides
  • Out-of-the-box: Works with just an upstream URL, no complex setup needed

Quick Start

Using Environment Variable

The simplest way to start:

UPSTREAM_URL=https://your-akkoma-instance.com ./akkoproxy

Using Configuration File

Create a config.toml file:

[upstream]
url = "https://your-akkoma-instance.com"

Then run:

./akkoproxy

See config.example.toml for all available options.

Installation

From Binary

Download the latest release from the releases page.

Using Docker

docker run -p 3000:3000 \
  -e UPSTREAM_URL=https://your-akkoma-instance.com \
  ghcr.io/blockg-ws/akkoma-media-proxy:latest

With configuration file:

docker run -p 3000:3000 \
  -v $(pwd)/config.toml:/app/config.toml \
  ghcr.io/blockg-ws/akkoma-media-proxy:latest

From Source

Requirements:

  • Rust 1.84 or later (for edition2024 support required by dependencies)
cargo build --release
./target/release/akkoproxy

Configuration

Configuration is loaded with the following priority (highest to lowest):

  1. Environment Variables (highest priority)
  2. Command-line Options
  3. Configuration File (lowest priority)

This means environment variables will override command-line options, which will override settings in the config file.

Upstream Configuration

[upstream]
url = "https://your-akkoma-instance.com"  # Required: Your Akkoma/Pleroma instance
timeout = 30                              # Request timeout in seconds

Server Configuration

[server]
bind = "0.0.0.0:3000"                          # Bind address
via_header = "akkoma-media-proxy/0.1.0"        # Via header value
preserve_upstream_headers = true               # Preserve all headers from upstream (default: true)
behind_cloudflare_free = false                 # Enable Cloudflare Free plan compatibility (default: false)

Cloudflare Free Plan Compatibility

When using Cloudflare's Free plan (which doesn't support Vary on cached content based on headers), you can enable behind_cloudflare_free = true to make the proxy work better with Cloudflare's Transform Rules.

How it works:

  1. Set behind_cloudflare_free = true in your config
  2. The proxy will look for a format query parameter in the URL
    • If format=avif is present, the image will be converted to AVIF
    • If format=webp is present, the image will be converted to WebP
  3. The format parameter is stripped from the upstream request
  4. A Vary: Accept header is added to responses
  5. The Access-Control-Allow-Origin header from upstream is preserved (not replaced)

Cloudflare Transform Rule Setup:

Create a Transform Rule in Cloudflare to add the format query parameter based on the Accept header:

  1. Go to your domain in Cloudflare Dashboard → Rules → Transform Rules → Modify Request URL
  2. Add a new rule:

Rule 1: Add format=avif for AVIF support

  • If: (http.request.uri.path matches "^/(media|proxy)" and http.request.headers["accept"][*] contains "image/avif")
  • Then: Query → Add → format = avif

Rule 2: Add format=webp for WebP support (with lower priority)

  • If: (http.request.uri.path matches "^/(media|proxy)" and http.request.headers["accept"][*] contains "image/webp" and not http.request.headers["accept"][*] contains "image/avif")
  • Then: Query → Add → format = webp

This setup allows Cloudflare to cache different formats separately based on the query parameter, working around the Free plan's limitation on Vary header support.

Cache Configuration

[cache]
max_capacity = 10000      # Maximum number of cached items
ttl = 3600               # Cache TTL in seconds (1 hour)
max_item_size = 10485760  # Maximum cacheable item size (10MB)

Image Processing Configuration

[image]
enable_avif = true        # Enable AVIF conversion
enable_webp = true        # Enable WebP conversion
quality = 85             # JPEG quality (1-100)
max_dimension = 4096     # Maximum image dimension

How It Works

  1. Request Filtering: Only /media and /proxy paths are allowed
  2. Cache Check: Looks for cached response with the requested format
  3. Upstream Fetch: If not cached, fetches from upstream server
  4. Header Preservation: All upstream headers (including Location for redirects) are preserved by default
  5. Image Conversion: For images, converts to the best format based on Accept header:
    • Prefers AVIF if image/avif is accepted
    • Falls back to WebP if image/webp is accepted
    • Otherwise returns original or JPEG
  6. Caching: Stores the converted response for future requests
  7. Response: Returns the optimized content with appropriate headers

Format Negotiation

The proxy respects the Accept header for image format selection:

Accept: image/avif,image/webp,image/*;q=0.8

Priority order:

  1. AVIF (if enabled and accepted)
  2. WebP (if enabled and accepted)
  3. JPEG (fallback)

Endpoints

  • GET /media/* - Proxied media requests with caching and conversion
  • GET /proxy/* - Proxied proxy requests with caching and conversion
  • GET /health - Health check endpoint
  • GET /metrics - Cache metrics (Prometheus-compatible)

Security

  • Path Restriction: Only /media and /proxy paths are allowed
  • No Directory Traversal: Path validation prevents directory traversal attacks
  • Timeout Protection: Upstream requests have configurable timeouts
  • Size Limits: Configurable maximum cache item size
  • TLS: Uses rustls for secure HTTPS connections to upstream

Performance

  • Async I/O: Built on Tokio for efficient concurrent request handling
  • Smart Caching: LRU cache with TTL and size-based eviction
  • Connection Pooling: Reuses HTTP connections to upstream
  • Efficient Image Processing: Uses optimized image libraries

Development

Building

cargo build

Testing

cargo test

Running in Development

UPSTREAM_URL=https://example.com cargo run

Environment Variables

Environment variables have the highest priority and will override both command-line options and config file settings:

  • UPSTREAM_URL: Upstream server URL (overrides config file and CLI option)
  • BIND_ADDRESS: Server bind address (e.g., 0.0.0.0:3000)
  • PRESERVE_HEADERS: Preserve upstream headers (true or false)
  • RUST_LOG: Logging level (e.g., debug, info, warn, error)

Command-line Options

Command-line options have medium priority and will override config file settings:

akkoproxy [OPTIONS]

Options:
  -c, --config <FILE>          Path to configuration file
  -u, --upstream <URL>         Upstream server URL
  -b, --bind <ADDR>            Address to bind the server to
  --enable-avif                Enable AVIF conversion
  --disable-avif               Disable AVIF conversion
  --enable-webp                Enable WebP conversion
  --disable-webp               Disable WebP conversion
  --preserve-headers           Preserve all headers from upstream
  -h, --help                   Print help
  -V, --version                Print version

Configuration Precedence Example

# Config file: config.toml
[upstream]
url = "https://config-url.com"

# Command line
./akkoproxy --upstream https://cli-url.com

# Environment variable
UPSTREAM_URL=https://env-url.com ./akkoproxy --upstream https://cli-url.com

# Result: https://env-url.com (environment has highest priority)

License

Licensed under either of:

at your option.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

About

[experimental] A fast caching and optimized media proxy for pleroma/akkoma

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors 2

  •  
  •