A high-performance reverse proxy server for GitHub that provides HTTP and SSH access to GitHub resources with built-in caching, rate limiting, authentication, and SOCKS5/HTTP proxy support.
- HTTP Proxy: Access GitHub releases, raw files, archives, gists, and API endpoints
- SSH Proxy: Git operations via SSH with authentication support
- Full URL Support: Use complete GitHub URLs instead of path-based routing
- Path-Based Listening: Deploy on subpaths (e.g.,
/ghproxy) - Caching: Hybrid memory + disk caching with ARC eviction policy
- Rate Limiting: IP-based or token-based rate limiting with configurable limits
- Authentication: Token-based or basic authentication support
- Proxy Support: Route traffic through SOCKS5, HTTP, or HTTPS proxies
- Security: SSRF protection, request validation, and security headers
- Metrics: Prometheus metrics for monitoring
- Graceful Shutdown: Clean shutdown with configurable timeout
Prerequisites:
- Go 1.24 or higher
- Make (optional, for using Makefile)
Build:
# Clone the repository git clone https://github.com/kexi/github-reverse-proxy.git cd github-reverse-proxy # Install dependencies make install # Build the binary make build # The binary will be available at ./build/github-proxy
# Build Docker image make docker-build # Run with Docker make docker-run
Download pre-built binaries from the releases page.
# Linux AMD64
wget https://github.com/kexi/github-reverse-proxy/releases/download/v1.0.0/github-proxy-linux-amd64.tar.gz
tar -xzf github-proxy-linux-amd64.tar.gz
chmod +x github-proxy
sudo mv github-proxy /usr/local/bin/The application uses a YAML configuration file. By default, it looks for ./configs/config.yaml.
Create a configuration file at ./configs/config.yaml:
server: host: "" # Listen on all interfaces (0.0.0.0) - use "127.0.0.1" for localhost only http_port: 8080 base_path: "" # Optional: base path like "/ghproxy" read_timeout: 30s write_timeout: 300s idle_timeout: 120s proxy: enabled: true type: socks5 # Options: socks5, http, https address: 127.0.0.1:1080 cache: enabled: true type: hybrid max_memory_size: 104857600 # 100MB max_disk_size: 10737418240 # 10GB disk_path: /var/cache/github-proxy ratelimit: enabled: true requests_per_second: 100 burst: 200 auth: enabled: false allow_anonymous: true metrics: enabled: true port: 9090
See configs/config.yaml for a complete configuration example with all available options.
Configuration values can be overridden using environment variables with the GITHUB_PROXY_ prefix:
export GITHUB_PROXY_SERVER_HOST=127.0.0.1 # Listen on localhost only export GITHUB_PROXY_SERVER_HTTP_PORT=8080 export GITHUB_PROXY_PROXY_ENABLED=true export GITHUB_PROXY_PROXY_ADDRESS=127.0.0.1:1080 export GITHUB_PROXY_AUTH_ENABLED=true
| Section | Option | Description | Default |
|---|---|---|---|
server.host |
Listen address | Host/IP to bind to ("" or 0.0.0.0 for all, 127.0.0.1 for localhost) |
"" (all) |
server.http_port |
HTTP port | Port for HTTP server | 8080 |
server.base_path |
Base path | Base path for all routes (e.g., /ghproxy) |
"" (root) |
server.read_timeout |
Read timeout | Maximum duration for reading requests | 30s |
server.write_timeout |
Write timeout | Maximum duration for writing responses | 300s |
proxy.enabled |
Enable proxy | Route GitHub requests through proxy | false |
proxy.type |
Proxy type | Type of proxy: socks5, http, or https |
socks5 |
proxy.address |
Proxy address | Proxy server address | 127.0.0.1:1080 |
cache.enabled |
Enable caching | Enable response caching | true |
cache.type |
Cache type | Cache strategy: memory, disk, or hybrid |
hybrid |
ratelimit.enabled |
Enable rate limiting | Enable request rate limiting | true |
ratelimit.requests_per_second |
Requests per second | Maximum requests per second per IP | 100 |
auth.enabled |
Enable authentication | Require authentication for requests | false |
metrics.enabled |
Enable metrics | Enable Prometheus metrics | true |
metrics.port |
Metrics port | Port for metrics endpoint | 9090 |
# Run with default configuration ./build/github-proxy # Run with custom configuration file ./build/github-proxy -config /path/to/config.yaml # Using Make make run
The HTTP proxy provides access to various GitHub resources with two URL formats:
1. Traditional Path-Based URLs
Use the repository path structure:
# Download release asset curl http://localhost:8080/owner/repo/releases/download/v1.0.0/binary.tar.gz # Get raw file curl http://localhost:8080/owner/repo/raw/main/README.md
2. Full GitHub URLs
Use complete GitHub URLs directly:
# Download release asset with full URL curl http://localhost:8080/https://github.com/owner/repo/releases/download/v1.0.0/binary.tar.gz # Get raw file with full URL curl http://localhost:8080/https://github.com/ZhiShengYuan/inningbo-go/raw/refs/heads/main/ARCHITECTURE_REFACTORING.md # Works with all GitHub URL formats curl http://localhost:8080/https://raw.githubusercontent.com/owner/repo/main/file.md curl http://localhost:8080/https://api.github.com/repos/owner/repo curl http://localhost:8080/https://gist.github.com/user/gist-id/raw/file.txt
3. Path-Based Deployment
Deploy on a subpath by setting base_path in config:
server: base_path: /ghproxy
Then access via:
# Traditional paths under base path curl http://example.com/ghproxy/owner/repo/raw/main/README.md # Full URLs under base path curl http://example.com/ghproxy/https://github.com/owner/repo/raw/main/README.md
# Download a release binary curl http://localhost:8080/owner/repo/releases/download/v1.0.0/binary.tar.gz -o binary.tar.gz # With authentication curl -u username:ghp_token http://localhost:8080/owner/repo/releases/download/v1.0.0/binary.tar.gz -o binary.tar.gz
# Get a raw file from a repository curl http://localhost:8080/owner/repo/raw/main/README.md # Get file from a specific commit curl http://localhost:8080/owner/repo/raw/abc123/src/main.go
# Download tarball archive curl http://localhost:8080/owner/repo/archive/refs/tags/v1.0.0.tar.gz -o repo-v1.0.0.tar.gz # Download zipball archive curl http://localhost:8080/owner/repo/archive/refs/heads/main.zip -o repo-main.zip
# Clone via HTTP git clone http://localhost:8080/owner/repo.git # Clone with authentication git clone http://username:ghp_token@localhost:8080/owner/repo.git # Push to repository cd repo git remote set-url origin http://username:ghp_token@localhost:8080/owner/repo.git git push origin main
# Get gist content curl http://localhost:8080/gist/username/gist-id/raw/file.txt # Download gist archive curl http://localhost:8080/gist/username/gist-id/archive.tar.gz -o gist.tar.gz
# Access GitHub API endpoints curl http://localhost:8080/api/user # With authentication curl -u username:ghp_token http://localhost:8080/api/user # List repositories curl -u username:ghp_token http://localhost:8080/api/user/repos # Get repository information curl http://localhost:8080/api/repos/owner/repo
The SSH proxy allows Git operations over SSH protocol:
# Clone repository via SSH git clone ssh://username:ghp_token@localhost:2222/owner/repo.git # Configure SSH (add to ~/.ssh/config) Host github-proxy HostName localhost Port 2222 User username # Clone using SSH config git clone github-proxy:owner/repo.git # Push via SSH cd repo git remote set-url origin ssh://username:ghp_token@localhost:2222/owner/repo.git git push origin main
The SSH proxy supports two authentication methods:
- Password authentication: Use your GitHub personal access token as the password
- Public key authentication: Use your SSH key (any key is accepted in the current implementation)
# Password authentication (token as password) git clone ssh://username@localhost:2222/owner/repo.git # Enter your GitHub personal access token when prompted # Public key authentication ssh-add ~/.ssh/id_rsa git clone ssh://username@localhost:2222/owner/repo.git
When authentication is enabled, you can authenticate using:
curl -H "X-Auth-Token: your-secret-token" http://localhost:8080/api/usercurl -u username:token http://localhost:8080/api/user
# For HTTP Git operations git clone http://username:token@localhost:8080/owner/repo.git # For SSH Git operations git clone ssh://username:token@localhost:2222/owner/repo.git
| Endpoint | Description | Example |
|---|---|---|
/:owner/:repo/releases/download/:tag/:file |
Download release asset | /owner/repo/releases/download/v1.0.0/app.tar.gz |
/:owner/:repo/raw/:ref/*path |
Get raw file content | /owner/repo/raw/main/README.md |
/:owner/:repo/archive/*path |
Download repository archive | /owner/repo/archive/refs/tags/v1.0.0.tar.gz |
/:owner/:repo.git/*path |
Git HTTP operations | /owner/repo.git/info/refs |
/gist/:username/:gistid/*path |
Access gist content | /gist/user/abc123/raw/file.txt |
/api/*path |
GitHub API proxy | /api/user |
Prometheus metrics are available at:
http://localhost:9090/metrics
Available metrics:
github_proxy_requests_total- Total number of requestsgithub_proxy_request_duration_seconds- Request duration histogramgithub_proxy_cache_hits_total- Cache hit countergithub_proxy_cache_misses_total- Cache miss countergithub_proxy_active_connections- Current active connectionsgithub_proxy_bytes_transferred_total- Total bytes transferred
github-reverse-proxy/
├── cmd/
│ └── server/ # Main application entry point
│ └── main.go
├── internal/
│ ├── auth/ # Authentication system
│ ├── cache/ # Caching system (ARC + disk)
│ ├── config/ # Configuration management
│ ├── handler/ # HTTP request handlers
│ ├── metrics/ # Prometheus metrics
│ ├── middleware/ # HTTP middleware
│ ├── proxy/ # Proxy client (SOCKS5/HTTP)
│ ├── ratelimit/ # Rate limiting
│ ├── security/ # Security features (SSRF protection)
│ ├── server/ # HTTP server
│ ├── ssh/ # SSH proxy server
│ └── util/ # Utility functions
├── configs/
│ └── config.yaml # Configuration file
├── Makefile # Build automation
└── README.md # This file
# Install dependencies make install # Format code make fmt # Run linters make lint # Run tests make test # Build make build
# Run all tests make test # Run tests with coverage make test-coverage # Run specific package tests go test -v ./internal/cache/...
# Format code make fmt # Run linters make lint # Run go vet make vet
# Run all unit tests make test # Run with race detection go test -race ./... # Run with coverage make test-coverage
# Start the server make run # In another terminal, test endpoints curl http://localhost:8080/owner/repo/raw/main/README.md curl http://localhost:9090/metrics
# Using Apache Bench ab -n 1000 -c 10 http://localhost:8080/owner/repo/raw/main/README.md # Using wrk wrk -t4 -c100 -d30s http://localhost:8080/owner/repo/raw/main/README.md
Dockerfile:
FROM golang:1.24-alpine AS builder WORKDIR /app COPY . . RUN go mod download RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o github-proxy ./cmd/server FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/github-proxy . COPY --from=builder /app/configs/config.yaml ./configs/ EXPOSE 8080 2222 9090 CMD ["./github-proxy"]
Build and run:
# Build image docker build -t github-proxy:latest . # Run container docker run -d \ -p 8080:8080 \ -p 2222:2222 \ -p 9090:9090 \ -v /var/cache/github-proxy:/var/cache/github-proxy \ -e GITHUB_PROXY_PROXY_ENABLED=true \ -e GITHUB_PROXY_PROXY_ADDRESS=host.docker.internal:1080 \ --name github-proxy \ github-proxy:latest
docker-compose.yml:
version: '3.8' services: github-proxy: build: . ports: - "8080:8080" - "2222:2222" - "9090:9090" volumes: - cache-data:/var/cache/github-proxy - ./configs/config.yaml:/root/configs/config.yaml environment: - GITHUB_PROXY_PROXY_ENABLED=true - GITHUB_PROXY_PROXY_ADDRESS=socks5-proxy:1080 restart: unless-stopped socks5-proxy: image: serjs/go-socks5-proxy ports: - "1080:1080" restart: unless-stopped volumes: cache-data:
Create /etc/systemd/system/github-proxy.service:
[Unit] Description=GitHub Reverse Proxy After=network.target [Service] Type=simple User=github-proxy Group=github-proxy WorkingDirectory=/opt/github-proxy ExecStart=/opt/github-proxy/github-proxy -config /etc/github-proxy/config.yaml Restart=on-failure RestartSec=5s # Security settings NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/var/cache/github-proxy [Install] WantedBy=multi-user.target
Install and start:
# Create user sudo useradd -r -s /bin/false github-proxy # Create directories sudo mkdir -p /opt/github-proxy sudo mkdir -p /etc/github-proxy sudo mkdir -p /var/cache/github-proxy # Copy files sudo cp build/github-proxy /opt/github-proxy/ sudo cp configs/config.yaml /etc/github-proxy/ sudo chown -R github-proxy:github-proxy /opt/github-proxy sudo chown -R github-proxy:github-proxy /var/cache/github-proxy # Enable and start service sudo systemctl daemon-reload sudo systemctl enable github-proxy sudo systemctl start github-proxy sudo systemctl status github-proxy
deployment.yaml:
apiVersion: apps/v1 kind: Deployment metadata: name: github-proxy spec: replicas: 3 selector: matchLabels: app: github-proxy template: metadata: labels: app: github-proxy spec: containers: - name: github-proxy image: github-proxy:latest ports: - containerPort: 8080 name: http - containerPort: 2222 name: ssh - containerPort: 9090 name: metrics env: - name: GITHUB_PROXY_CACHE_DISK_PATH value: /cache volumeMounts: - name: cache mountPath: /cache resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" volumes: - name: cache persistentVolumeClaim: claimName: github-proxy-cache --- apiVersion: v1 kind: Service metadata: name: github-proxy spec: selector: app: github-proxy ports: - name: http port: 8080 targetPort: 8080 - name: ssh port: 2222 targetPort: 2222 - name: metrics port: 9090 targetPort: 9090 type: LoadBalancer
prometheus.yml:
scrape_configs: - job_name: 'github-proxy' static_configs: - targets: ['localhost:9090'] scrape_interval: 15s
Import the provided Grafana dashboard or create custom panels using metrics:
- Request rate:
rate(github_proxy_requests_total[5m]) - Error rate:
rate(github_proxy_requests_total{status=~"5.."}[5m]) - Cache hit rate:
rate(github_proxy_cache_hits_total[5m]) / (rate(github_proxy_cache_hits_total[5m]) + rate(github_proxy_cache_misses_total[5m])) - Request duration (p95):
histogram_quantile(0.95, rate(github_proxy_request_duration_seconds_bucket[5m]))
# config.yaml server: http_port: 8080 base_path: "" # Listen on root path proxy: enabled: false
Usage:
# Traditional path-based curl http://localhost:8080/torvalds/linux/raw/master/README # Full GitHub URL curl http://localhost:8080/https://github.com/torvalds/linux/raw/master/README # Raw GitHub User Content URL curl http://localhost:8080/https://raw.githubusercontent.com/torvalds/linux/master/README
# config.yaml server: http_port: 8080 base_path: /ghproxy # All routes under /ghproxy
Nginx configuration:
location /ghproxy/ { proxy_pass http://localhost:8080/ghproxy/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
Usage:
# Traditional path-based with base path curl http://example.com/ghproxy/owner/repo/raw/main/file.md # Full GitHub URL with base path curl http://example.com/ghproxy/https://github.com/owner/repo/raw/main/file.md # Works with all GitHub resources curl http://example.com/ghproxy/https://github.com/owner/repo/releases/download/v1.0.0/app.tar.gz
# config.yaml server: http_port: 8080 base_path: /ghproxy proxy: enabled: true type: http # Use HTTP proxy address: proxy.example.com:8080 username: proxy_user password: proxy_pass auth: enabled: true type: token tokens: - "secret-token-123"
Usage:
# With authentication token curl -H "X-Auth-Token: secret-token-123" \ http://localhost:8080/ghproxy/https://github.com/owner/repo/raw/main/file.md # With basic auth curl -u username:secret-token-123 \ http://localhost:8080/ghproxy/owner/repo/raw/main/file.md
# GitHub releases curl http://localhost:8080/https://github.com/owner/repo/releases/download/v1.0.0/binary.tar.gz # Raw files (multiple formats) curl http://localhost:8080/https://github.com/owner/repo/raw/main/README.md curl http://localhost:8080/https://github.com/owner/repo/raw/refs/heads/main/README.md curl http://localhost:8080/https://github.com/owner/repo/blob/main/README.md # Auto-converted to raw curl http://localhost:8080/https://raw.githubusercontent.com/owner/repo/main/README.md # Archives curl http://localhost:8080/https://github.com/owner/repo/archive/refs/tags/v1.0.0.tar.gz curl http://localhost:8080/https://github.com/owner/repo/archive/refs/heads/main.zip # Gists curl http://localhost:8080/https://gist.github.com/username/gist-id/raw/file.txt # API curl http://localhost:8080/https://api.github.com/repos/owner/repo curl http://localhost:8080/https://api.github.com/user/repos
1. Connection refused on port 8080
- Check if the server is running:
systemctl status github-proxy - Verify the port in configuration matches
- Check firewall rules:
sudo ufw status
2. Proxy connection failures
- Verify SOCKS5/HTTP proxy is running
- Check proxy address in configuration
- Test proxy connectivity:
curl --socks5 127.0.0.1:1080 https://api.github.com
3. Cache not working
- Check disk space:
df -h - Verify cache directory permissions
- Check cache configuration in config.yaml
4. Rate limiting issues
- Adjust
requests_per_secondin configuration - Check if rate limiting is enabled
- Review logs for rate limit events
MIT License - see LICENSE file for details
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
- GitHub Issues: https://github.com/kexi/github-reverse-proxy/issues
- Documentation: https://github.com/kexi/github-reverse-proxy/wiki
Built with: