Routes
24 single, failover, race, and round robinPublished Docker image. Built-in control plane. Protocols made explicit.
Install a real API gateway without adopting a platform.
NapiGate keeps the edge small and explicit: route-level protection, scoped clients, multiple auth methods, output profiles, response caching, trusted hooks, built-in monitor surfaces, and a published Docker image at napigate/napigate. It keeps HTTP ingress simple, supports HTTP and gRPC upstream execution today, and carries an explicit protocol catalog for services and routes so coverage does not collapse into one vague “HTTP-only” bucket.
Runtime surface
NapiGate operations
Protocols
7 / 5 service and route protocol catalogsState
RAM hot path never reads config from PostgresRoute contract
Protection, targets, output, and protocol stay explicit.
routes:
- slug: hello-grpc
protocol: http
gateway_path: /demo/grpc/hello
methods: [POST]
strategy: single
targets:
- service: greeter_grpc
endpoint: say_hello
services:
greeter_grpc:
protocol: grpc
target: localhost:50051
Published image
Use the Docker image directly.
mkdir -p napigate/{config,data,logs}
curl -L https://raw.githubusercontent.com/napigate/napigate/main/config/services.example.yaml -o napigate/config/services.yaml
curl -L https://raw.githubusercontent.com/napigate/napigate/main/config/security.example.yaml -o napigate/config/security.yaml
docker run -d --name napigate \
-p 8000:8000 -p 8001:8001 \
-v "$PWD/napigate/config:/code/config" \
-v "$PWD/napigate/data:/code/data" \
-v "$PWD/napigate/logs:/code/logs" \
-e NAPIGATE_ADMIN_USERNAME=admin \
-e NAPIGATE_ADMIN_PASSWORD=change-me \
napigate/napigate:latest
Overview
A gateway that stays understandable under real operational pressure.
NapiGate is designed for teams that want routing, auth, shaping, caching, and monitoring without dragging in a large control plane or opaque plugin ecosystem.
Route-centric exposure
Gateway paths, methods, strategies, and protection live on routes instead of being scattered across endpoint definitions.
Protocol-aware contract
Service and route protocol types stay explicit, so HTTP, gRPC, WebSocket, gRPC-Web, HTTP/3, TCP, and UDP are not flattened into one vague upstream shape.
Scoped clients
Attach multiple auth methods to each client and scope access to all services, selected services, or exact endpoints.
Output control
Shape responses with reusable output profiles, endpoint transforms, route envelopes, and safe custom logic.
Trusted hooks
Use pre_call and external_service to fetch tokens, validate requests, and enrich downstream calls.
Built-in operations
Live monitor, JSON logs, admin UI, audit trail, and daily rotating file logs ship as part of the product surface.
Optional backends
Keep config file-backed, or move state to Postgres. Add Redis only when distributed rate limiting and response caching matter.
Coverage
Broader protocol coverage, without pretending every transport is identical.
NapiGate now keeps an APISIX-inspired protocol catalog visible in config and admin. The runtime is deliberately honest: HTTP ingress is the stable edge today, and actual execution currently covers HTTP upstreams plus unary gRPC upstreams.
REST and JSON APIs
Match routes by method and path, inject headers and query values, shape output, and cache successful responses.
GraphQL over HTTP
Front GraphQL services like any other HTTP target when you need auth, monitoring, route scoping, or admin visibility at the edge.
Webhooks and callbacks
Accept inbound partner traffic and trigger downstream async success hooks or structured log forwarding after successful gateway responses.
Unary gRPC upstreams
Keep HTTP on the public side while calling gRPC services behind the route with reflection or descriptor-set backed method resolution.
SOAP, XML, and form-encoded flows
Keep the gateway contract readable while proxying legacy HTTP integrations that still rely on XML bodies, headers, cookies, or form fields.
Token brokers and auth facades
Use pre_call and external_service to fetch tokens, validate credentials, or bridge awkward auth flows.
WebSocket, gRPC-Web, and HTTP/3
These protocol types are already first-class in the config and admin contract so future runtime work does not start from a route model that only understood plain HTTP.
TCP and UDP upstream classes
Service protocol types also cover lower-level stream shapes. Unsupported transports fail loudly instead of being mislabeled as ordinary HTTP.
Protocol catalog
Keep protocol intent readable in the config itself.
Runtime truth
Support is explicit, and so are the gaps.
- Implemented: route=http -> service=http
- Implemented: route=http -> service=grpc
- Declared but not executed yet: WebSocket, gRPC ingress, gRPC-Web, HTTP/3, TCP, UDP
- Unsupported protocol matches return 501 instead of silently faking HTTP semantics.
Operational control
Keep admin and monitor surfaces close to the runtime.
- Separate public and admin listeners by default
- Live request visibility through HTML, JSON, and SSE monitor endpoints
- Admin audit log for service, route, client, and security changes
- File-backed or Postgres-backed state with in-memory runtime snapshots
- Protocol catalog visible in the same admin surface that operators already use
Request lifecycle
- Match the incoming method and path to a route.
- Resolve route targets and enforce route-level protection.
- Run trusted hook code, rate limits, and cache checks.
- Execute the configured upstream transport, shape output, and record monitor data.
Config model
Readable enough to review in a pull request, explicit enough to debug at 2 AM.
clients:
- slug: partner-ops
code: partner_ops
title: Partner Operations
access:
mode: endpoints
endpoints:
- service: protected_httpbin
endpoint: protected_headers
auth_methods:
- code: partner_oauth
type: oauth_client_credentials
client_id: demo-client-id
client_secret: demo-client-secret
routes:
- slug: hello-grpc
protocol: http
gateway_path: /demo/grpc/hello
auth: { required: true }
services:
greeter_grpc:
protocol: grpc
target: localhost:50051
What stays explicit
No service-local client blocks to hunt down later.
Auth requirements stay with the public gateway path that operators actually expose.
Service and route protocol types stay visible in admin and YAML instead of getting lost behind generic base_url fields.
Endpoint first, then service, then route, with optional Redis when the hot path grows beyond one process.
Trusted proxy IPs, separate admin URLs, and public versus admin listeners are all part of the runtime contract.
Declared but unimplemented protocol matches fail with a direct 501 instead of half-working under HTTP assumptions.
Install
Pick the install path that matches how your team already ships software.
The fastest path is the published Docker image. If you want the full repo workflow, NapiGate also ships a runtime Compose stack and a direct Python entrypoint.
Recommended
Run the published Docker image
Use the image directly from Docker Hub when you want the shortest path from download to a running gateway.
mkdir -p napigate/{config,data,logs}
curl -L https://raw.githubusercontent.com/napigate/napigate/main/config/services.example.yaml -o napigate/config/services.yaml
curl -L https://raw.githubusercontent.com/napigate/napigate/main/config/security.example.yaml -o napigate/config/security.yaml
docker run -d --name napigate \
-p 8000:8000 -p 8001:8001 \
-v "$PWD/napigate/config:/code/config" \
-v "$PWD/napigate/data:/code/data" \
-v "$PWD/napigate/logs:/code/logs" \
-e NAPIGATE_ADMIN_USERNAME=admin \
-e NAPIGATE_ADMIN_PASSWORD=change-me \
napigate/napigate:latest
Repo runtime
Use Docker Compose from source
Clone the main repo when you want the published runtime image plus the full local config, data, and logs layout.
git clone https://github.com/napigate/napigate.git
cd napigate
cp .env.example .env
cp config/services.example.yaml config/services.yaml
cp config/security.example.yaml config/security.yaml
docker compose pull
docker compose up -d
Source install
Run from Python
Install locally when you want to hack on the gateway itself, step through runtime behavior, or package your own image.
git clone https://github.com/napigate/napigate.git
cd napigate
pip install .
# Optional when you want local gRPC upstream support outside Docker:
# pip install ".[grpc]"
cp config/services.example.yaml config/services.yaml
cp config/security.example.yaml config/security.yaml
python3 -m gateway.main \
--host 0.0.0.0 \
--port 8000 \
--admin-host 0.0.0.0 \
--admin-port 8001 \
--config config/services.yaml \
--security-config config/security.yaml
Optional backends
Turn on Postgres, Redis, or source-side gRPC extras only when you need them
Keep the default install light, then add state, distributed caching, or local development extras when your operational footprint grows.
# Optional Postgres-backed state
docker compose --profile postgres up -d
# In .env
NAPIGATE_STATE_STORE=postgres
NAPIGATE_POSTGRES_DSN=postgresql://napigate:napigate@postgres:5432/napigate
# Optional Redis-backed cache and rate limiting
NAPIGATE_REDIS_URL=redis://localhost:6379/0
# Optional local source extras for gRPC upstream work
pip install ".[grpc]"
After boot
Know where each surface lives.
- Public health: http://127.0.0.1:8000/__health
- OAuth token endpoint: http://127.0.0.1:8000/__oauth/token
- Admin UI: http://127.0.0.1:8001/__admin
- Monitor UI: http://127.0.0.1:8001/__monitor
Why the split matters
Keep admin off the public port.
NapiGate does not expose /__admin, /__monitor, or /__logout on the public listener. That makes firewall and reverse-proxy isolation much simpler.
For teams that still read their own infrastructure