# HubProxy: a self-hosted Docker and GitHub acceleration proxy in one Go binary

> HubProxy is a self-hosted proxy server that speeds up Docker image pulls, GitHub file downloads and Hugging Face model transfers from a single Go binary. It is aimed at operators who want one service instead of several third-party mirrors, and it ships as a Docker image, a script installer or deb, rpm and apk packages.

**sky22333/hubproxy** — 多功能加速服务，支持Docker 镜像加速、GitHub 加速、下载离线镜像等功能。轻量级，不占用存储空间。

- Repository: https://github.com/sky22333/hubproxy
- Website: http://docs.52013120.xyz/
- Stars: 2,886 · Forks: 387
- Language: Go
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/sky22333-hubproxy

## What HubProxy replaces, and for whom

Pulling a container image from Docker Hub or fetching a release asset from GitHub from a network with poor routing to those origins is slow in a way that has nothing to do with your own bandwidth. The usual workaround is a public mirror, and the usual cost is that you have no control over who runs it, what it caches, or when it disappears. HubProxy takes the other route: you run the proxy yourself, on your own host, and point Docker and your download commands at it.

The README frames it as a multi-purpose acceleration server covering Docker image acceleration, GitHub file acceleration, offline image packaging and online Docker image search. The audience is therefore operations people and self-hosters who already have a machine with a domain name, not end users looking for a browser extension. The project is written in Go and licensed under MIT, and the top-level repository layout includes src/, web/, docs/, packaging/ and install.sh, which matches the claim of a single binary plus a bundled Vue front end.

## How the proxy handles registry and GitHub traffic

The README states that the Docker side is compatible with the Registry API v2 and covers Docker Hub, GHCR, Quay, GCR and registry.k8s.io. That is the mechanism worth understanding: HubProxy is not a cache of image layers on disk. It streams responses through and caches manifests and tokens. The README describes the transfer as streaming, and it lists Manifest / Token caching separately from layer transfer, so the expensive blob traffic is passed through rather than stored. This is consistent with the project description saying it is lightweight and does not occupy storage space.

GitHub traffic is handled through URL rewriting. You request a path that begins with the GitHub URL you want, and the proxy fetches it. The README lists Release assets, Raw files, git clone and api.github.com as covered targets, and notes that URLs inside .sh and .ps1 scripts are rewritten automatically. Hugging Face model files and LFS large-file downloads go through the same service.

Two operational features shape deployment more than the acceleration itself. Rate limiting is a token bucket keyed on the real client IP, with IPv6 treated per /64, and both the period and the quota are configurable. Repository access control combines IP allow and deny lists (with rate-limit exemption or blocking) and image or GitHub repository allow and deny lists that accept wildcards. An optional upstream SOCKS5 proxy is available for outbound traffic, which matters on hosts that cannot reach the origins directly.

## Installing HubProxy with Docker and pulling your first image

The README calls the Docker deployment the recommended path. The image is published at ghcr.io/sky22333/hubproxy, and the command below maps port 5000 and restarts the container automatically:

```bash
docker run -d \
  --name hubproxy \
  -p 5000:5000 \
  --restart always \
  ghcr.io/sky22333/hubproxy
```

After the container starts, the README's verification step is a request to the readiness endpoint. A successful response means the service is listening and ready to proxy:

```bash
curl http://127.0.0.1:5000/ready
```

The repository also ships a docker-compose.yml that mounts a configuration file read-only and caps log growth. Note the mount path on the right side of the volume line, which is where the container expects the file:

```yaml
services:
  hubproxy:
    image: ghcr.io/sky22333/hubproxy
    container_name: hubproxy
    restart: always
    ports:
      - "5000:5000"
    volumes:
      - ./src/config.toml:/app/config.toml:ro
```

For a host without Docker, the install script detects amd64 or arm64 and the available package manager. The README says the resulting configuration lives at /etc/hubproxy/config.toml and that the service starts automatically:

```bash
curl -fsSL https://raw.githubusercontent.com/sky22333/hubproxy/main/install.sh | sh
```

With the service running, the first real use is a Docker pull. Replace yourdomain.com with the address of your HubProxy instance:

```bash
docker pull yourdomain.com/nginx
```

The same prefix pattern applies to downloads. The README's examples prepend the proxy address to a full GitHub URL for a release asset and for git clone:

```bash
wget "https://yourdomain.com/https://github.com/owner/repo/releases/download/v1.0.0/app.tar.gz"
git clone https://yourdomain.com/https://github.com/sky22333/hubproxy.git
```

The README adds a production note: bind your own domain, put Caddy or Nginx in front with HTTPS, and do not leave a bare http://IP:5000 exposed long term. That is not decoration. Docker's registry client and your download tools will be sending every request through this endpoint, so the transport in front of it is part of the setup.

## Offline image packaging without a local Docker daemon

The feature that distinguishes HubProxy from a plain pull-through mirror is offline image packaging. The README says you can package a single image or a batch into tar files online, with no local Docker required, and that the transfer is streamed with a debounce design. The practical consequence is that a machine which cannot run Docker at all can still produce an image archive, and a machine that can run Docker does not need to pull layers first and then save them.

The README does not document how the debounce behaves under concurrent requests, nor does it state a size limit for a batch archive. If you plan to package multi-gigabyte images, that is the first thing to measure on your own host rather than assume. The web interface, described as a built-in Vue SPA, exposes image search, offline package download and tag browsing, so the packaging flow is reachable without touching the API directly.

## Where HubProxy is the wrong tool

HubProxy is a proxy, not a cache. Because layer traffic is streamed and only manifests and tokens are cached, repeated pulls of the same large image still traverse the network between your host and the upstream registry. If your goal is to cut egress from the upstream or to serve many identical pulls from local storage, a registry with an on-disk cache is the better fit, and the README's own emphasis on not occupying storage space tells you which trade-off the project chose.

Second, the README's production guidance assumes you can terminate HTTPS yourself. If you cannot put a reverse proxy with a certificate in front of it, the documentation's advice is to avoid exposing port 5000 directly, and there is no bundled TLS story described in the README. Third, the rate limiter keys on the real client IP, with IPv6 grouped by /64. Behind a reverse proxy that does not forward the original address, that key collapses and the quota applies to the proxy's own address instead of individual clients. The README does not spell out which header the service reads, so this is something to confirm against the documentation site before relying on per-client quotas.

Finally, the access control lists are configuration, not a security boundary you inherit. Wildcard entries in the image and repository lists are convenient and easy to get wrong, and the README does not describe an audit or preview mode for them.

## How it differs from a pull-through registry mirror

The closest alternative in practice is a registry mirror such as the registry:2 image run with proxy configuration, which Docker itself supports through the registry-mirrors setting. The difference in approach is structural. A registry mirror speaks only the registry protocol, stores layers on disk, and does nothing for GitHub release assets, git clone or Hugging Face downloads. HubProxy covers those additional protocols through URL prefixing and script rewriting, and it keeps the storage footprint near zero by streaming layers.

That means the two are not substitutes for the same job. If all your traffic is docker pull against Docker Hub and you have disk to spare, a pull-through registry cache is simpler and Docker talks to it natively. If your traffic is mixed, Docker plus GitHub plus model files, and disk is the constraint, HubProxy is the one that covers the set. The README also states that HubProxy does not depend on third-party free CDN proxies, which is the argument for self-hosting it rather than using a public mirror at all.

## Maintenance, releases and licence

The repository is not archived, and the last push was on 2026-08-02. The most recent release listed is v1.2.5 on 2026-07-12, preceded by v1.2.4 on 2026-05-06 and v1.2.3 on 2026-02-02. The cadence visible in the release list is roughly every two to three months, with patch releases in between, so upgrades are an occasional task rather than a continuous one.

Upgrade cost depends on how you installed it. The Docker path is a new image tag and a container restart; the docker-compose.yml in the repository pins no version, so a pull takes whatever the tag points to. The script path installs packages in deb, rpm or apk format and places configuration at /etc/hubproxy/config.toml. The README does not document rollback, so keeping a copy of your config.toml before an upgrade is the only recovery step the README supports. Configuration is described as a single config.toml with environment variable overrides, which means an upgrade that changes a key can be worked around without editing the file.

The licence is MIT. That permits commercial and private use and modification, with the usual requirement to keep the copyright and permission notice. The README carries a disclaimer stating the program is for learning and exchange, that users must follow local laws and regulations, and that the author accepts no liability for user actions. MIT governs the code; that disclaimer is a separate statement about intended use, and neither is legal advice for your jurisdiction.

## Conclusion

HubProxy fits operators who already run a server with a domain and want Docker, GitHub and Hugging Face traffic to leave through one endpoint they control, and who are willing to read config.toml rather than rely on defaults. Skip it if you need a managed service with an SLA, if you cannot terminate HTTPS in front of it, or if your only need is a single public Docker Hub mirror. Before rolling it out, verify that /ready answers on port 5000, that your reverse proxy forwards the real client IP so the token-bucket limiter keys on the right address, and that the repository and IP allow and deny lists in config.toml match your policy.

## FAQ

### How do I install HubProxy with Docker?

The README's recommended path is to run the ghcr.io/sky22333/hubproxy image, mapping port 5000 and setting a restart policy, then check the service by requesting http://127.0.0.1:5000/ready. A docker-compose.yml is also included in the repository.

### Does HubProxy need a local Docker installation to package images offline?

No. The README states that offline image packaging works online for a single image or a batch into tar files without a local Docker installation, using streamed transfer with a debounce design.

### Where does HubProxy store its configuration file?

The README says the script installer places the configuration at /etc/hubproxy/config.toml, and the docker-compose.yml in the repository mounts ./src/config.toml to /app/config.toml inside the container as a read-only volume.

### Can HubProxy be exposed directly on port 5000?

The README advises against leaving a bare http://IP:5000 exposed long term for production and recommends binding your own domain and putting Caddy or Nginx in front with HTTPS enabled.

## Sources

- [License: MIT](https://github.com/sky22333/hubproxy/blob/main/LICENSE)
- [Project website](http://docs.52013120.xyz/)
- [README](https://github.com/sky22333/hubproxy/blob/main/README.md)
- [Releases](https://github.com/sky22333/hubproxy/releases)
- [sky22333/hubproxy on GitHub](https://github.com/sky22333/hubproxy)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sky22333-hubproxy
