NyaProxy
A lightweight API gateway for services that authenticate with API keys, bearer tokens, or custom request headers.
Centralize credential injection, quota-aware routing, rate limiting, retries, and observability for any HTTP API that uses keys or tokens.
Overview
NyaProxy sits between your applications and upstream APIs. Applications call NyaProxy with an internal proxy key; NyaProxy forwards each request to the configured upstream with the correct upstream credentials, rotating across a pool of keys while enforcing rate limits, retries, and path policies.
It is useful when a team needs one place to manage access to external or internal APIs such as AI providers, image generation APIs, SaaS APIs, data vendors, or private services.
Use NyaProxy only with credentials and traffic patterns that are allowed by the upstream service terms.
Features
| Feature | Description | Config |
|---|---|---|
| Credential injection | Add upstream credentials through headers without exposing them to clients | headers, variables |
| Credential pooling | Route traffic across multiple upstream keys or tokens | variables.<name> |
| Load balancing | round_robin, random, least_requests, fastest_response, and weighted selection |
load_balancing_strategy, key_weights |
| Rate limiting | Endpoint, upstream key, client IP, and proxy user limits | rate_limit |
| Queueing | Hold requests until configured quota becomes available | queue |
| Retry and failover | Retry selected status codes, cool down the failing key, and rotate to the next one | retry |
| Key quarantine | Temporarily remove credentials that return configured upstream error statuses | key_blocking |
| Request policy | Allow or block paths and methods before forwarding | allowed_paths, allowed_methods |
| Body transformation | Set or remove JSON fields with conditional JMESPath rules | request_body_substitution |
| Observability | Web dashboard plus a Prometheus /metrics endpoint |
dashboard |
| Outbound proxy | Send upstream traffic through an optional HTTP/SOCKS proxy | server.proxy |
Quick Start
Install From PyPI
pip install nya-proxy
nyaproxy
On first run, NyaProxy creates a starter config.yaml in the current directory and listens on 127.0.0.1:8080.
Important: the starter config has no
server.api_key, so authentication is disabled. This is safe only while bound to loopback. Setserver.api_keybefore using--host 0.0.0.0or otherwise exposing the service.
Then open:
http://<host>:8080/config— configuration UI with validationhttp://<host>:8080/dashboard— metrics, request history, and queue statushttp://<host>:8080/info— configured API list and service status
Run With Your Own Config
nyaproxy --config config.yaml
Config changes made through the /config UI (or to the file, once you re-save through the UI) trigger an automatic restart so they take effect immediately. Pass --no-reload to disable the file-watch supervisor for production setups where restarts should be explicit.
Install From Source
git clone https://github.com/Nya-Foundation/nyaproxy.git
cd nyaproxy
pip install -e .
nyaproxy # or: python -m nya
Docker
mkdir -p data
cp configs/openai.yaml data/config.yaml # then replace every placeholder key
docker run -d \
-p 8080:8080 \
-v ${PWD}/data:/app \
--user "$(id -u):$(id -g)" \
k3scat/nya-proxy:latest --config /app/config.yaml --host 0.0.0.0
Mount the directory, not config.yaml itself. Saving from the /config UI writes a temporary file and renames it over the target, and that rename fails with EBUSY against a bind-mounted file, so every save returns a 500. The mount must also be writable — a read-only mount blocks saves for the same reason.
--user runs the container as you, since the image runs as uid 100 and could not otherwise write a directory you own. Docker Desktop on macOS and Windows maps ownership for you, so you can drop that flag there.
The directory holds config.yaml and .nya_state.json, which carries rate-limit windows and key cool-downs across restarts so a config change does not reset your quotas. Edit configuration on the host or through the /config UI; either way NyaProxy restarts itself to apply it. Do not publish the port until server.api_key is set.
CLI Reference
| Flag | Description |
|---|---|
--config, -c |
Path to the configuration file |
--host, -H / --port, -p |
Bind address and port (defaults: 127.0.0.1 / 8080; environment: SERVER_HOST / SERVER_PORT) |
--no-reload |
Disable the config file-watch supervisor; config changes then require a manual restart |
--check-config |
Validate schema and cross-field configuration, then exit |
--remote-url, -r / --remote-api-key, -k / --remote-app-name, -a |
Pull configuration from a remote config server instead of a local file (disables the local /config UI) |
--version |
Print the version and exit |
Configuration
NyaProxy is configured with a single YAML file, validated against a bundled JSON schema. Ready-made examples live in configs/.
Settings under default_settings apply to every API; any API block can override them. For IDE autocomplete and inline validation, keep this modeline as the first line of your config (the shipped examples already include it):
# yaml-language-server: $schema=https://raw.githubusercontent.com/Nya-Foundation/NyaProxy/main/nya/schema.json
A minimal working config:
server:
api_key:
- your_admin_proxy_key # first key = master key (dashboard + config UI)
- your_application_proxy_key # additional keys for regular proxy traffic
logging:
enabled: true
level: info
log_file: app.log
dashboard:
enabled: true
default_settings:
key_variable: keys
load_balancing_strategy: round_robin
queue:
max_size: 200
max_workers: 10
expiry_seconds: 300
rate_limit:
enabled: true
endpoint_rate_limit: 1000/h
key_rate_limit: 60/m
ip_rate_limit: 5000/d
user_rate_limit: 5000/d
retry:
enabled: true
attempts: 3
retry_after_seconds: 1
retry_status_codes: [429, 500, 502, 503, 504]
key_blocking:
enabled: true
status_codes: [401, 403]
duration_seconds: 300
timeouts:
request_timeout_seconds: 300
apis:
example_service:
name: Example Service
endpoint: https://api.example.com/v1
aliases:
- example
key_variable: keys
headers:
Authorization: "Bearer ${{keys}}"
variables:
keys:
- upstream_key_1
- upstream_key_2
Request Format
Requests are forwarded through /api/<api_name>/<path> — or /api/<alias>/<path> for an alias. Aliases are route segments such as example, not paths such as /example.
With the config above, this proxy request:
POST http://localhost:8080/api/example_service/messages
is forwarded to:
POST https://api.example.com/v1/messages
with Authorization: Bearer <one of your upstream keys> injected, chosen by the load balancer.
Load Balancing
Five strategies are available per API via load_balancing_strategy:
round_robin(default) — cycle through keys in orderrandom— pick a key at randomleast_requests— pick the key that has served the fewest requestsfastest_response— pick the key with the lowest average response timeweighted— distribute according tokey_weights
For weighted, weights align with the order of the key list:
apis:
example_service:
load_balancing_strategy: weighted
key_weights: [3, 1, 1] # first key gets 3x the traffic of the others
variables:
keys: [key_a, key_b, key_c]
Rate Limiting
Four independent limiter scopes:
endpoint_rate_limit— total request rate for one upstream APIkey_rate_limit— request rate for each upstream credentialip_rate_limit— request rate per client IPuser_rate_limit— request rate per proxy API key
Formats: 10/s, 60/m, 1000/h, 5000/d, 1/15s (one request per 15 seconds), or "0" for unlimited. Requests over the limit wait in a per-API queue (bounded by queue.max_size) until quota frees up or queue.expiry_seconds passes; clients that exceed the IP/user quota get 429 with a Retry-After header. rate_limit_paths restricts which paths count against the limits (prefix match with a trailing *).
Retries and Failover
When an upstream response matches retry_status_codes (and the method is in retry_request_methods), NyaProxy cools the failing key down for retry_after_seconds, rotates to the next available key, and retries up to attempts times — without blocking other traffic on the same API. If every attempt fails, the client receives 429; upstream connection failures and timeouts surface as 502 and 504 respectively.
Key Quarantine
key_blocking can temporarily remove a credential from selection when the upstream returns any configured HTTP error status. It is disabled by default; a common setup enables it for 401 and 403 so an expired or revoked credential is not selected again for duration_seconds. This policy is independent of retries: add the same status to retry.retry_status_codes only when the current request should also fail over to another credential.
API Examples
Generic Bearer Token API
apis:
data_vendor:
name: Data Vendor API
endpoint: https://api.vendor.example/v2
key_variable: tokens
headers:
Authorization: "Bearer ${{tokens}}"
variables:
tokens:
- vendor_token_1
- vendor_token_2
rate_limit:
enabled: true
endpoint_rate_limit: 5000/d
key_rate_limit: 60/m
Custom Header API
apis:
internal_service:
name: Internal Service
endpoint: https://internal.example.com
key_variable: service_tokens
headers:
X-Service-Token: "${{service_tokens}}"
X-Client-Name: "nyaproxy"
variables:
service_tokens:
- service_token_1
- service_token_2
OpenAI-Compatible API
apis:
openai_compatible:
name: OpenAI-Compatible Provider
endpoint: https://api.provider.example/v1
key_variable: keys
headers:
Authorization: "Bearer ${{keys}}"
variables:
keys:
- provider_key_1
- provider_key_2
allowed_paths:
enabled: true
mode: whitelist
paths:
- "/chat/*"
- "/images/*"
request_body_substitution:
enabled: true
rules:
- name: "Remove unsupported field"
operation: remove
path: "frequency_penalty"
conditions:
- field: "frequency_penalty"
operator: "exists"
Streaming responses (SSE and chunked transfer) are forwarded transparently, so OpenAI-style stream: true requests work as-is.
Request Body Substitution
Substitution rules can set or remove JSON fields before forwarding — useful for provider compatibility, default values, and policy enforcement:
request_body_substitution:
enabled: true
rules:
- name: "Cap temperature"
operation: set
path: "temperature"
value: 0.7
conditions:
- field: "temperature"
operator: "gt"
value: 0.7
See Request Body Substitution for the full rule syntax.
Endpoints
| Endpoint | Auth | Purpose |
|---|---|---|
/api/<api_name>/<path> |
proxy key | Proxy requests to configured upstream APIs |
/config |
master key | Edit and validate configuration in the browser |
/dashboard |
master key | Metrics, request history, key usage, and queue state; queues can be cleared and metrics reset |
/health |
none | Liveness check for load balancers and orchestrators |
/info |
none | Configured API list and service status |
/metrics |
none | Prometheus exposition endpoint |
Operations
- Logging — configured under
server.logging;enabled: falsedisables both console and file sinks. The log file rotates at 10 MB with the last 5 files retained.debuglogs request/response metadata (with secrets redacted). - Config reload — a config change triggers a full process restart via the file-watch supervisor. In-flight requests are dropped and in-memory state (queues, rate-limit windows, metrics) resets. Use
--no-reloadif you'd rather restart explicitly. - State — all rate limiting, queueing, and metrics state is in-memory and per-process. Run a single instance per credential pool; running replicas would give each its own independent limits.
Security Notes
- If
server.api_keyis not set, authentication is disabled entirely — every endpoint (including the config UI) is open to anyone who can reach the port. The default bind is loopback; always set a key before selecting a public bind with--hostorSERVER_HOST. server.trusted_proxiescontrols which proxy IPs or CIDR networks may supply client-IP forwarding headers. Leave it empty unless NyaProxy is behind a proxy you control.- The first key in
server.api_keyis the master key, required for the dashboard and configuration UI. Additional keys can be handed to applications for proxy traffic only. - Do not share upstream provider credentials with clients — keep them in the NyaProxy config or your deployment's secret manager.
- Restrict
server.cors.allow_originsto trusted origins when browsers call the proxy with credentials. - Use
allowed_pathsandallowed_methodsto limit what clients can call.
Deployment Guides
Project Status
NyaProxy is in active development. Configuration and behavior may change between releases. Pin a tested version for production deployments and review the changelog before upgrading.
Community
- Issues: GitHub Issues
- Discord: Nya Foundation
- Contact: k3scat@gmail.com
License
NyaProxy is released under the MIT License.
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 nya_proxy-0.8.1.tar.gz.
File metadata
- Download URL: nya_proxy-0.8.1.tar.gz
- Upload date:
- Size: 162.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66ca9c5450914fbbad1bf5976af2c86c095fad24fb0f3dd153c301e2fa6650a8
|
|
| MD5 |
3813db643a738b0b66dc9d9c730a7a0e
|
|
| BLAKE2b-256 |
7560685fa49849388dbe503acf7861802e6b85187b35bf3c8a7fe71c5d08f64f
|
Provenance
The following attestation bundles were made for nya_proxy-0.8.1.tar.gz:
Publisher:
publish.yml on Nya-Foundation/NyaProxy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nya_proxy-0.8.1.tar.gz -
Subject digest:
66ca9c5450914fbbad1bf5976af2c86c095fad24fb0f3dd153c301e2fa6650a8 - Sigstore transparency entry: 2206697351
- Sigstore integration time:
-
Permalink:
Nya-Foundation/NyaProxy@8448c3118b7891f6472fa626ba5692f08f8a185f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Nya-Foundation
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8448c3118b7891f6472fa626ba5692f08f8a185f -
Trigger Event:
push
-
Statement type:
File details
Details for the file nya_proxy-0.8.1-py3-none-any.whl.
File metadata
- Download URL: nya_proxy-0.8.1-py3-none-any.whl
- Upload date:
- Size: 170.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8261e950022d1ea84ceae2ddd4dd3ad118fd12fe447c3b32502e229c1342b6d
|
|
| MD5 |
5b9adb6088510a5181826e76aa10c9df
|
|
| BLAKE2b-256 |
cef82b26c819c08654d0ca434b72ade968d8847804fb00ac90a79e2525ff28d7
|
Provenance
The following attestation bundles were made for nya_proxy-0.8.1-py3-none-any.whl:
Publisher:
publish.yml on Nya-Foundation/NyaProxy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nya_proxy-0.8.1-py3-none-any.whl -
Subject digest:
c8261e950022d1ea84ceae2ddd4dd3ad118fd12fe447c3b32502e229c1342b6d - Sigstore transparency entry: 2206697364
- Sigstore integration time:
-
Permalink:
Nya-Foundation/NyaProxy@8448c3118b7891f6472fa626ba5692f08f8a185f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Nya-Foundation
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8448c3118b7891f6472fa626ba5692f08f8a185f -
Trigger Event:
push
-
Statement type: