|
| 1 | +p:ine-gate |
| 2 | + |
| 3 | +Open-source, K8s-deployable AI Gateway for local & remote LLMs with quotas, streaming, routing, and observability. |
| 4 | + |
| 5 | +## Features |
| 6 | +- Backends: Echo, Ollama (local), vLLM (OpenAI-compatible), OpenRouter, OpenAI, Anthropic |
| 7 | +- Routing: static rules + canary weighted splits |
| 8 | +- SSE streaming end-to-end |
| 9 | +- Rate limiting per API key (in-mem or Redis) |
| 10 | +- Usage counters and admin endpoint |
| 11 | +- Prometheus metrics with backend labels |
| 12 | +- OTel tracing (OTLP exporter) |
| 13 | +- Docker + Helm (ServiceMonitor + HPA) |
| 14 | + |
| 15 | +## Quickstart (Local) |
| 16 | +``` |
| 17 | +cp .env.example .env # optional, or create your own |
| 18 | +CONFIG_FILE=./configs/config.example.yaml make run |
| 19 | +curl -i http://localhost:8080/healthz |
| 20 | +curl -s -H 'x-api-key: dev-key' -H 'Content-Type: application/json' -X POST http://localhost:8080/v1/completions -d '{"model":"echo","prompt":"hello"}' |
| 21 | +``` |
| 22 | + |
| 23 | +### Enable OpenRouter |
| 24 | +``` |
| 25 | +PINE_GATE_BACKENDS_OPENROUTER_ENABLED=true \ |
| 26 | +PINE_GATE_BACKENDS_OPENROUTER_APIKEY=<YOUR_KEY> \ |
| 27 | +CONFIG_FILE=./configs/config.example.yaml make run |
| 28 | +curl -s -H 'x-api-key: dev-key' -H 'Content-Type: application/json' -X POST \ |
| 29 | + http://localhost:8080/v1/completions -d '{"model":"openrouter:mistralai/mistral-7b-instruct:free","prompt":"hello"}' |
| 30 | +``` |
| 31 | + |
| 32 | +### Enable Ollama (local) |
| 33 | +``` |
| 34 | +PINE_GATE_BACKENDS_OLLAMA_ENABLED=true \ |
| 35 | +PINE_GATE_BACKENDS_OLLAMA_HOST=http://localhost:11434 \ |
| 36 | +CONFIG_FILE=./configs/config.example.yaml make run |
| 37 | +curl -s -H 'x-api-key: dev-key' -H 'Content-Type: application/json' -X POST \ |
| 38 | + http://localhost:8080/v1/completions -d '{"model":"ollama:llama3","prompt":"hello"}' |
| 39 | +``` |
| 40 | + |
| 41 | +### vLLM (OpenAI-compatible) |
| 42 | +``` |
| 43 | +PINE_GATE_BACKENDS_VLLM_ENABLED=true \ |
| 44 | +PINE_GATE_BACKENDS_VLLM_BASE_URL=http://localhost:8000/v1 \ |
| 45 | +CONFIG_FILE=./configs/config.example.yaml make run |
| 46 | +``` |
| 47 | + |
| 48 | +### OpenAI |
| 49 | +``` |
| 50 | +PINE_GATE_BACKENDS_OPENAI_ENABLED=true \ |
| 51 | +PINE_GATE_BACKENDS_OPENAI_APIKEY=<OPENAI_KEY> \ |
| 52 | +CONFIG_FILE=./configs/config.example.yaml make run |
| 53 | +``` |
| 54 | + |
| 55 | +### Anthropic |
| 56 | +``` |
| 57 | +PINE_GATE_BACKENDS_ANTHROPIC_ENABLED=true \ |
| 58 | +PINE_GATE_BACKENDS_ANTHROPIC_APIKEY=<ANTHROPIC_KEY> \ |
| 59 | +CONFIG_FILE=./configs/config.example.yaml make run |
| 60 | +``` |
| 61 | + |
| 62 | +## Redis Rate Limit + Usage |
| 63 | +``` |
| 64 | +docker run --rm -p 6379:6379 redis:7 |
| 65 | +PINE_GATE_REDIS_ENABLED=true PINE_GATE_REDIS_ADDR=localhost:6379 \ |
| 66 | +PINE_GATE_AUTH_ADMIN_KEY=admin CONFIG_FILE=./configs/config.example.yaml make run |
| 67 | +curl -s -H 'x-admin-key: admin' 'http://localhost:8080/v1/usage?key=dev-key' |
| 68 | +``` |
| 69 | + |
| 70 | +## Tracing (Jaeger all-in-one) |
| 71 | +``` |
| 72 | +docker run --rm -p 16686:16686 -p 4318:4318 -e COLLECTOR_OTLP_ENABLED=true jaegertracing/all-in-one:1.57 |
| 73 | +OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4318 CONFIG_FILE=./configs/config.example.yaml make run |
| 74 | +
|
| 75 | +## .env Support |
| 76 | +- pine-gate automatically loads a `.env` file from the working directory. |
| 77 | +- Put any configuration env vars in `.env` instead of prefixing commands, for example: |
| 78 | +
|
| 79 | +``` |
| 80 | +# .env |
| 81 | +PINE_GATE_BACKENDS_OLLAMA_ENABLED=true |
| 82 | +PINE_GATE_BACKENDS_OLLAMA_HOST=http://localhost:11434 |
| 83 | +PINE_GATE_BACKENDS_OPENROUTER_ENABLED=false |
| 84 | +PINE_GATE_BACKENDS_OPENROUTER_APIKEY= |
| 85 | +PINE_GATE_BACKENDS_OPENAI_ENABLED=false |
| 86 | +PINE_GATE_BACKENDS_VLLM_ENABLED=false |
| 87 | +OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4318 |
| 88 | +PINE_GATE_LIMITS_RATE_RPS=5 |
| 89 | +PINE_GATE_LIMITS_BURST=10 |
| 90 | +``` |
| 91 | +
|
| 92 | +With `.env` present, simply run: |
| 93 | +
|
| 94 | +``` |
| 95 | +make run |
| 96 | +# or |
| 97 | +./bin/pinectl serve --config ./configs/config.example.yaml |
| 98 | +``` |
| 99 | +``` |
| 100 | + |
| 101 | +## Helm Install |
| 102 | +``` |
| 103 | +helm install pine-gate charts/pine-gate --set auth.apiKey=dev-key |
| 104 | +# Optional extras: |
| 105 | +# --set backends.openrouter.enabled=true --set backends.openrouter.apiKey=$OPENROUTER_API_KEY |
| 106 | +# --set redis.enabled=true --set auth.adminKey=admin |
| 107 | +# --set monitoring.enabled=true --set otel.enabled=true |
| 108 | +kubectl port-forward deploy/pine-gate 8080:8080 |
| 109 | +``` |
| 110 | + |
| 111 | +## Security |
| 112 | +- Container: distroless non-root, read-only FS, dropped capabilities, seccomp RuntimeDefault |
| 113 | +- K8s: security contexts set via Helm values |
| 114 | + |
| 115 | +## See Also |
| 116 | +- docs/RUNBOOK.md |
| 117 | +- docs/SLOs.md |
0 commit comments