Universal proxy for Docker registry and PyPI mirrors with automatic failover
Project description
Hyper Mirror
Universal proxy for Docker registry and PyPI mirrors with automatic failover.
Features
- Docker Registry Proxy: Transparent mirror for Docker Hub with fallback
- PyPI Proxy: Python package index mirror with automatic retry
- Health Monitoring: Automatic mirror health checks and degradation
- Dynamic Configuration: Add/remove mirrors via API
- Swagger UI: Built-in API documentation
Installation
git clone https://github.com/yourusername/hyper-mirror.git
cd hyper-mirror
uv sync
Quick Start
# Run with default configuration
uv run hyper-mirror
# Or run directly
uv run python -m hyper_mirror.main
Server starts on http://localhost:8080
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
HOST |
0.0.0.0 |
Server bind address |
PORT |
8080 |
Server port |
PYPI_OFFICIAL_URL |
https://pypi.org/simple |
Official PyPI index |
PYPI_MIRRORS |
(built-in) | Comma-separated PyPI mirrors |
DOCKER_OFFICIAL_URL |
https://registry-1.docker.io |
Official Docker registry |
DOCKER_MIRRORS |
(built-in) | Comma-separated Docker mirrors |
Examples
# Use custom PyPI index
PYPI_OFFICIAL_URL=https://pypi.company.internal/simple uv run hyper-mirror
# Custom mirrors only
PYPI_MIRRORS="https://mirror1.com/simple,https://mirror2.com/simple" \
DOCKER_MIRRORS="https://docker-mirror1.com,https://docker-mirror2.com" \
uv run hyper-mirror
Docker Setup
Configure Docker to use the proxy:
sudo tee /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["http://127.0.0.1:8080"],
"insecure-registries": ["127.0.0.1:8080"]
}
EOF
sudo systemctl restart docker
Now use Docker normally:
docker pull hello-world
docker pull nginx
PyPI Setup
Configure pip to use the proxy:
# Global config
pip config set global.index-url http://127.0.0.1:8080/simple
pip config set global.trusted-host 127.0.0.1
# Or per-command
pip install --index-url http://127.0.0.1:8080/simple --trusted-host 127.0.0.1 requests
Or use environment variables:
export PIP_INDEX_URL=http://127.0.0.1:8080/simple
export PIP_TRUSTED_HOST=127.0.0.1
pip install requests
API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Service info |
/docs |
GET | Swagger UI |
/redoc |
GET | ReDoc documentation |
/health |
GET | Mirror health status |
/v2/ |
GET/HEAD | Docker registry root |
/v2/{path} |
GET/HEAD/POST | Docker registry proxy |
/simple/{package}/ |
GET | PyPI package proxy |
/mirrors/{type} |
POST | Add mirror dynamically |
/config/{type}/official |
PUT | Update official URL |
API Usage Examples
# Check health
curl http://localhost:8080/health
# Add mirror dynamically
curl -X POST "http://localhost:8080/mirrors/pypi?url=https://new.mirror.com/simple&name=newmirror&priority=5"
# Update official PyPI URL
curl -X PUT "http://localhost:8080/config/pypi/official?url=https://test.pypi.org/simple"
Project Structure
src/hyper_mirror/
├── __init__.py # Package init
├── main.py # FastAPI application
├── cli.py # CLI entry point
├── config.py # Configuration management
├── base.py # Base classes and utilities
├── mirrors.py # Mirror registry and initialization
├── docker.py # Docker registry routes
└── pypi.py # PyPI proxy routes
Adding New Mirror Types
- Create new file
src/hyper_mirror/npm.py:
from fastapi import APIRouter
from .mirrors import registry
router = APIRouter(tags=["NPM"])
@router.get("/npm/{package}")
async def npm_proxy(package: str):
# Implementation
pass
- Add mirrors to
mirrors.py:
NPM_MIRRORS = [
("https://registry.npmmirror.com", "npmmirror", 0),
]
- Register in
init_mirrors():
npm_mgr = BaseMirrorManager("npm")
npm_mgr.official_url = "https://registry.npmjs.org"
for url, name, priority in NPM_MIRRORS:
npm_mgr.add_mirror(url, name, priority)
registry.register("npm", npm_mgr)
- Include router in
main.py:
from . import npm
app.include_router(npm.router)
Development
# Run in development mode with auto-reload
uv run --reload hyper-mirror
# Or with Python directly
cd src
PYTHONPATH=. uvicorn hyper_mirror.main:create_app --factory --reload
Docker Compose
version: '3.8'
services:
hyper-mirror:
build: .
ports:
- "8080:8080"
environment:
- PYPI_OFFICIAL_URL=https://pypi.org/simple
- PYPI_MIRRORS=https://mirror1.com/simple,https://mirror2.com/simple
restart: unless-stopped
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mirava-0.1.0.tar.gz.
File metadata
- Download URL: mirava-0.1.0.tar.gz
- Upload date:
- Size: 6.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e53034662b3d3d0dfc94052f2b69089719c9f0b50de9a3509876eceb0488bcc
|
|
| MD5 |
62514cfa6638a83ae15201c2f3e17dee
|
|
| BLAKE2b-256 |
5f082b2ccfe704c335d6dbd7fac5b01c6a3308aef5cd1aa9af99ead83e9dabdd
|
File details
Details for the file mirava-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mirava-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07eb48cdcfda40b731ade794e2741a6d586464196e94cb5dc6dca15553b7a9ac
|
|
| MD5 |
ec28171e7fc2df3d78c90f519c4f4496
|
|
| BLAKE2b-256 |
9670040250024a78f8e9a68eea5250bfadbba06f359902a53e33f4b4bc89cda0
|