Wharf
May 6, 2026 · View on GitHub
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.shautomation 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:
- Run the one-click installation script.
- When prompted for mode selection, enter
1or simply press Enter. - Follow the prompts to enter your domain name and choose the certificate handling method.
- 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:
- Run the one-click installation script.
- When prompted for mode selection, enter
2. - Follow the prompts to enter your domain name, Wharf backend listening port, and certificate information.
- 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:
- Run the one-click installation script.
- When prompted for mode selection, enter
3. - Follow the prompts to enter the HTTP port Wharf should listen on.
- 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.
-
Configure Docker Daemon
Edit the
/etc/docker/daemon.jsonfile (create if it doesn't exist) and add the following content. Replaceyour-domain.comwith your domain name.{ "registry-mirrors": ["https://your-domain.com"] } -
Restart Docker Service
sudo systemctl restart dockerNow,
docker pullwill 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.
-
Complete Basic Configuration
Please ensure you have completed all steps in Method One.
-
Login to Proxy Service
Use the
docker logincommand and enter your Docker Hub username and password.docker login your-domain.com -
Synchronize Authentication Information
After successful login, you need to manually edit the
~/.docker/config.jsonfile. Copy theauthinformation generated foryour-domain.comand paste it forhttps://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 pullrequests 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.
-
Clone Repository
git clone https://github.com/harrisonwang/wharf.git cd wharf -
Modify Configuration File Open
config/default.toml.example, copy it toconfig/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.tomlThen 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_urlmust 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.
-
Run Project Now, you can directly run the project with
cargo.cargo runThe service will start and listen on
http://0.0.0.0:8080. -
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.runExample with a fixed subdomain
example.com:- set
public_base_urltohttps://example.com - run tunnel command:
ssh -N -R dev:80:127.0.0.1:8080 ssh.edge.ng
- set
-
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
realminWWW-Authenticateis fixed topublic_base_urland is not influenced by the incomingHostheader. -
Build Release Version
cargo build --release
License
This project is licensed under the MIT License. See LICENSE for more information.