Skip to content

hackclub/gh-proxy

Repository files navigation

gh-proxy

A lightweight Go service backed by Postgres that proxies the GitHub REST and GraphQL APIs. It provides:

  • Pooled “donated” tokens with automatic rotation by API category (core/search/code_search/graphql)
  • DB-backed caching of GET/HEAD responses with TTL and size limits
  • Per‑key rate limiting
  • A simple admin UI to create/disable API keys and view usage

Ports: the server listens on :8080.
Admin UI: http://localhost:8080/admin (HTTP Basic Auth, creds from env).
API docs: http://localhost:8080/docs.


Quick start (Docker Compose)

Prereqs: Docker + Docker Compose.

  1. Create a .env file in the project root. At minimum, set your GitHub OAuth app values if you want the “donate token” flow:
# --- required for token-donation login (/auth/github) ---
GITHUB_OAUTH_CLIENT_ID=your_client_id
GITHUB_OAUTH_CLIENT_SECRET=your_client_secret

# --- admin login (change in production) ---
ADMIN_USER=admin
ADMIN_PASS=admin

# --- optional tuning (see full list below) ---
MAX_CACHE_TIME=300
MAX_CACHE_SIZE_MB=100
DB_MAX_CONNS=20
MAX_PROXY_BODY_BYTES=1048576
# For local dev the compose file pins BASE_URL to http://localhost:8080

Tip: Create your GitHub OAuth App with Homepage URL: http://localhost:8080 Authorization callback URL: http://localhost:8080/auth/github/callback Scope used: read:user (read‑only).

  1. Start the stack (hot‑reload dev server + Postgres):
docker compose up --build
# in another terminal, view logs:
docker compose logs -f app
  1. Open the app:
  • Home: http://localhost:8080/ (donate a token with GitHub)
  • Admin: http://localhost:8080/admin (default admin / admin)
  • API Docs: http://localhost:8080/docs
  1. Create an API key in /admin. You’ll see the key once—copy it now.

  2. Make a request through the proxy:

# REST example (public repo)
curl -H "X-API-Key: YOUR_KEY" \
  "http://localhost:8080/gh/repos/zachlatta/sshtron"

# GraphQL example
curl -H "X-API-Key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"query":"{ viewer { login } }"}' \
  http://localhost:8080/gh/graphql

You’ll see helpful response headers like:

  • X-Gh-Proxy-Cache: hit|miss
  • X-Gh-Proxy-Category: core|search|code_search|graphql
  • X-Gh-Proxy-Client: <your key identifier>
  • X-Gh-Proxy-Donor: <github username> (when a donated token was used)

Postgres in dev is exposed on localhost:5433. The app in Docker connects to db:5432 internally.


Running without Docker (local Go)

  1. Start Postgres via Compose (for convenience):
docker compose up -d db
  1. Create .env (same as above). The default DATABASE_URL points to the dev DB on localhost:5433.

  2. Build & run:

go build -o ./bin/server ./cmd/server
./bin/server

Migrations run automatically at startup.


Environment configuration

gh-proxy reads environment variables and also loads a .env file from the working directory.

Variable Required Default What it does
DATABASE_URL Prod: yes (Dev: optional) Dev default: postgres://ghproxy:ghproxy@localhost:5433/ghproxy?sslmode=disable (Compose app uses postgres://ghproxy:ghproxy@db:5432/ghproxy?sslmode=disable) Postgres connection string. Migrations run automatically.
BASE_URL Yes http://localhost:8080 Public base URL of this service. Must match the external scheme+host (used for OAuth callback + WebSocket origin checks).
ADMIN_USER Yes admin HTTP Basic username for /admin.
ADMIN_PASS Yes admin HTTP Basic password for /admin.
GITHUB_OAUTH_CLIENT_ID Needed for token donation GitHub OAuth App client ID used by /auth/github.
GITHUB_OAUTH_CLIENT_SECRET Needed for token donation GitHub OAuth App client secret.
MAX_CACHE_TIME No 300 Cache TTL in seconds for cached responses (0 = unlimited; stored without expiry). GET/HEAD 200s only; respects public caching.
MAX_CACHE_SIZE_MB No 100 Approximate max size (in MB) of the cached_responses table. Oldest rows are trimmed periodically.
DB_MAX_CONNS No 20 Max connections in the Postgres pool.
MAX_PROXY_BODY_BYTES No 1048576 Max allowed request body to /gh/* in bytes (returns 413 if exceeded).

If GITHUB_OAUTH_CLIENT_ID/SECRET aren’t set, the server still runs, but token donation (the “Donate Token” button) will be disabled.


Endpoints

  • Homepage: / — explains the project and lets users donate a GitHub token.
  • API Docs: /docs — copy‑paste examples for REST/GraphQL.
  • Admin: /admin — create/disable API keys, view usage, recent activity.
  • REST proxy: /gh/{path} — proxies to https://api.github.com/{path}
  • GraphQL proxy: /gh/graphql — proxies to https://api.github.com/graphql

All API requests require X-API-Key: <your key>.


How it works (one‑minute version)

  • Token rotation: Donated tokens are stored (read‑only scope). The proxy rotates tokens and tracks category‑specific GitHub rate limits. Revoked/unauthorized tokens are marked and skipped automatically.
  • Caching: GET/HEAD successful responses are cached in Postgres with a TTL and size cap. Periodic jobs trim old cache rows and keep only recent request logs.
  • Rate limiting: Each API key has a per‑second limit (default 10 rps) configured when the key is created.

Production (container)

Build and run as a single container (provide your own Postgres):

# Build a minimal image
docker build -t gh-proxy:latest -f Dockerfile .

# Run (example)
docker run --rm -p 8080:8080 --env-file .env \
  -e DATABASE_URL="postgres://user:pass@host:5432/ghproxy?sslmode=disable" \
  gh-proxy:latest

In production, set BASE_URL to your public HTTPS URL (e.g., https://proxy.example.org) so OAuth and the admin WebSocket work correctly. Change ADMIN_USER/ADMIN_PASS.


Troubleshooting

  • OAuth login fails / admin live stats don’t update: Ensure BASE_URL exactly matches the public origin (scheme + hostname + port).
  • “missing X-API-Key” (401): Include your API key header on /gh/* requests.
  • 429 Too Many Requests: Your key hit its per‑second rate limit; lower concurrency or request fewer times per second.
  • 413 Request Entity Too Large: Increase MAX_PROXY_BODY_BYTES if you need to send larger GraphQL payloads.

Development notes

  • Hot‑reload is provided in the dev container via air.
  • Server logs include request lines, admin actions, OAuth events, cache activity, and errors.
  • See DEVELOPMENT.md for logging commands and tips.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published