Wharf

May 6, 2026 · View on GitHub

og-image

English 简体中文 Русский Español 한국어 العربية Türkçe

A lightweight Docker image proxy service, designed to solve the problem of restricted access to Docker Hub in mainland China.

📢 Blog Tutorial: Say Goodbye to Docker Hub Connection Timeouts! Build Your Exclusive Image Accelerator with Wharf

Core Features

  • 🚀 One-Click Deployment: Provides an install.sh automation script for one-click environment setup, certificate application (Let's Encrypt), and service deployment, requiring no manual intervention.

  • 📦 Multiple Deployment Modes:

    • Standalone: Built-in TLS functionality, directly provides HTTPS service.
    • Nginx Proxy: Can work with Nginx as a backend service.
    • CDN Origin: Supports HTTP mode, convenient for CDN integration.
  • ⚡ Login for Increased Pull Rate: Allows users to authenticate with their personal Docker Hub accounts via docker login, increasing the pull rate limit from anonymous users (10 pulls/hour/IP) to authenticated users (100 pulls/hour/account).

  • 💎 Completely Transparent Proxy: Fully compatible with Docker Registry V2 API. Clients only need to modify the mirror source address, with no additional learning curve or changes in usage habits.

  • 🛡️ High Performance & Security: Built with Rust and Actix Web, offering excellent performance and memory safety. Uses streaming for image transfer, with minimal overhead.

Installation and Deployment

We provide a one-click installation script to simplify the deployment process. Before starting, please ensure your domain name is resolved to the target host.

bash <(curl -Ls https://raw.githubusercontent.com/harrisonwang/wharf/main/install.sh)

The script will guide you through the installation and offers the following three deployment modes:


Mode One: Standalone (HTTPS)

This is the simplest and most recommended mode. Wharf will directly listen on ports 80 and 443, providing a complete HTTPS proxy service.

Features:

  • No need for additional web server configuration.
  • Automatically handles HTTP to HTTPS redirection.
  • Option to automatically apply for Let's Encrypt certificates or use your own certificates.

Installation Process:

  1. Run the one-click installation script.
  2. When prompted for mode selection, enter 1 or simply press Enter.
  3. Follow the prompts to enter your domain name and choose the certificate handling method.
  4. The script will automatically complete all configurations and start the service.

Mode Two: Nginx Reverse Proxy (Advanced)

Mode Two: Nginx Reverse Proxy

This mode is suitable if you already have Nginx and wish to manage web services centrally through it.

Features:

  • Nginx handles HTTPS encryption and certificate management, with Wharf running as a plain HTTP backend.
  • Wharf runs as a backend HTTP service on a specified port (e.g., 9000).
  • Convenient for integration with other services.

Installation Process:

  1. Run the one-click installation script.
  2. When prompted for mode selection, enter 2.
  3. Follow the prompts to enter your domain name, Wharf backend listening port, and certificate information.
  4. The script will automatically generate an example Nginx configuration file for you. You will need to manually add it to your Nginx configuration and reload the Nginx service.

Mode Three: CDN Origin (HTTP) (Advanced)

Mode Three: CDN Origin (HTTP)

This mode is suitable if you want to use Wharf as the origin for a CDN to achieve better global acceleration.

Features:

  • Wharf only listens on HTTP ports.
  • The CDN provider handles HTTPS requests and certificates.
  • Wharf trusts and processes X-Forwarded-* headers to correctly identify client IP and protocol.

Installation Process:

  1. Run the one-click installation script.
  2. When prompted for mode selection, enter 3.
  3. Follow the prompts to enter the HTTP port Wharf should listen on.
  4. Configure your CDN service to point its origin to the Wharf service address and port.

Docker Client Usage

Configure your Docker client to use your proxy service.

Method One: Anonymous Usage (Basic Configuration)

This is the basic configuration, pointing Docker's default requests to your proxy service.

  1. Configure Docker Daemon

    Edit the /etc/docker/daemon.json file (create if it doesn't exist) and add the following content. Replace your-domain.com with your domain name.

    {
      "registry-mirrors": ["https://your-domain.com"]
    }
    
  2. Restart Docker Service

    sudo systemctl restart docker
    

    Now, docker pull will pull images through your proxy.

Multi-Registry Proxy

Wharf can proxy multiple upstream registries in the same service process. Docker Hub can still use registry-mirrors; GHCR, Quay.io, and other non-Docker Hub registries should be pulled through their configured proxy hostnames.

Example configuration:

[registry]
default = "dockerhub"

[[registry.upstreams]]
name = "dockerhub"
hosts = ["docker.example.com"]
upstream_registry = "https://registry-1.docker.io"
auth_realm = "https://auth.docker.io/token"
auth_service = "registry.docker.io"
auto_library_prefix = true
public_base_url = "https://docker.example.com"

[[registry.upstreams]]
name = "ghcr"
hosts = ["ghcr.example.com"]
upstream_registry = "https://ghcr.io"
auth_realm = "https://ghcr.io/token"
auth_service = "ghcr.io"
auto_library_prefix = false
public_base_url = "https://ghcr.example.com"

[[registry.upstreams]]
name = "quay"
hosts = ["quay.example.com"]
upstream_registry = "https://quay.io"
auth_realm = "https://quay.io/v2/auth"
auth_service = "quay.io"
auto_library_prefix = false
public_base_url = "https://quay.example.com"

Usage examples:

docker pull ghcr.example.com/owner/image:tag
docker pull quay.example.com/organization/image:tag
docker login ghcr.example.com
docker login quay.example.com
Method Two: Login Usage (Increased Pull Rate)

This method allows you to get a higher image pull rate by logging in with your Docker Hub account, in addition to anonymous usage.

  1. Complete Basic Configuration

    Please ensure you have completed all steps in Method One.

  2. Login to Proxy Service

    Use the docker login command and enter your Docker Hub username and password.

    docker login your-domain.com
    
  3. Synchronize Authentication Information

    After successful login, you need to manually edit the ~/.docker/config.json file. Copy the auth information generated for your-domain.com and paste it for https://index.docker.io/v1/.

    Before modification:

    {
        "auths": {
            "your-domain.com": {
                "auth": "aBcDeFgHiJkLmNoPqRsTuVwXyZ..."
            }
        }
    }
    

    After modification:

    {
        "auths": {
            "your-domain.com": {
                "auth": "aBcDeFgHiJkLmNoPqRsTuVwXyZ..."
            },
            "https://index.docker.io/v1/": {
                "auth": "aBcDeFgHiJkLmNoPqRsTuVwXyZ..."
            }
        }
    }
    

    After saving the file, your docker pull requests will be sent as an authenticated user, thus enjoying higher rate limits.

Development

Note

For detailed technical background, system architecture, and implementation principles, please refer to the Technical Architecture & Principles Document.

  1. Clone Repository

    git clone https://github.com/harrisonwang/wharf.git
    cd wharf
    
  2. Modify Configuration File Open config/default.toml.example, copy it to config/default.toml, then update the config. For local development, run Wharf on local HTTP (8080) and expose an HTTPS public domain via a tunnel.

    cp config/default.toml.example config/default.toml
    

    Then edit config/default.toml:

    # config/default.toml
    
    [server]
    http_port = 8080      # Use non-privileged port
    https_port = 8443
    http_enabled = true   # Enable HTTP
    https_enabled = false # Disable HTTPS
    behind_proxy = true
    public_base_url = "https://your-dev-domain.example" # Must match the tunnel's public URL
    
    [registry]
    default = "dockerhub"
    upstream_registry = "https://registry-1.docker.io"
    auth_realm = "https://auth.docker.io/token"
    auth_service = "registry.docker.io"
    auto_library_prefix = true
    
    [tls]
    cert_path = "/tmp/wharf-dev.crt"
    key_path = "/tmp/wharf-dev.key"
    

    Notes:

    • public_base_url must exactly match the real external URL (scheme/domain/port).
    • When https_enabled = false, local cert files are not loaded; however, the current config schema still requires the [tls] section, so placeholder paths are fine.
  3. Run Project Now, you can directly run the project with cargo.

    cargo run
    

    The service will start and listen on http://0.0.0.0:8080.

  4. Expose a Public Domain with a Tunnel (for local integration tests) Start a tunnel in another terminal to forward public traffic to local 8080. Commands below are examples; check each provider's docs for exact syntax.

    # ngrok
    ngrok http 8080
    
    # tunnl.gg (example)
    ssh -N -R <subdomain>:80:127.0.0.1:8080 <tunnl-endpoint>
    
    # localhost.run
    ssh -N -R 80:127.0.0.1:8080 nokey@localhost.run
    

    Example with a fixed subdomain example.com:

    • set public_base_url to https://example.com
    • run tunnel command: ssh -N -R dev:80:127.0.0.1:8080 ssh.edge.ng
  5. Verify End-to-End Behavior

    curl -i https://your-dev-domain.example/health
    curl -i https://your-dev-domain.example/v2/
    curl -i http://127.0.0.1:8080/v2/ -H 'Host: evil.test'
    

    Expected: the realm in WWW-Authenticate is fixed to public_base_url and is not influenced by the incoming Host header.

  6. Build Release Version

    cargo build --release
    

License

This project is licensed under the MIT License. See LICENSE for more information.