Skip to content

grpc api

Thomas Mangin edited this page Apr 11, 2026 · 2 revisions

Pre-Alpha. This page describes behavior that may change.

The gRPC API is the typed-RPC counterpart to the REST API. Both transports share the same API engine, so a command executed over gRPC returns the same data as the same command over REST. The difference is the wire format (protobuf instead of JSON), the discovery mechanism (gRPC reflection instead of OpenAPI), and the client ergonomics (generated typed stubs instead of hand-rolled HTTP calls).

Proto definitions live at api/proto/ze.proto, package ze.api.v1.

Enabling the server

environment {
    api-server {
        grpc {
            enabled true;
            server { ip 0.0.0.0; port 50051; }
        }
    }
}

Or via environment variable:

ze.api-server.grpc.enabled=true
ze.api-server.grpc.listen=0.0.0.0:50051

Environment variables override YANG. Default listen is 0.0.0.0:50051.

Services

The proto exposes two services.

ZeService

Generic command execution and discovery. This is the gRPC equivalent of the REST /api/v1/execute and /api/v1/commands endpoints.

RPC Type Purpose
Execute unary Run a command, receive the result.
Stream server-stream Run a streaming command (e.g. peer monitor, subscribe).
ListCommands unary Enumerate every command registered with the dispatcher.
DescribeCommand unary Metadata for a single command.
Complete unary Tab completion (future).

CommandResponse.data is JSON-encoded bytes, so the payload content matches what REST would return for the same command. Typed access comes from the command metadata returned by DescribeCommand, not from per-command protobuf messages.

ZeConfigService

Typed config-session management. Same session semantics as the REST config endpoints: enter, set, delete, diff, commit, discard.

RPC Purpose
GetRunningConfig Return the current running config.
EnterSession Start a candidate session and return its ID.
SetConfig Set a value in the candidate.
DeleteConfig Delete a path from the candidate.
DiffSession Preview pending changes.
CommitSession Apply pending changes.
DiscardSession Throw away the candidate.

Sessions are owned by the authenticated user — another user cannot touch a session they did not create. Idle sessions expire after 30 minutes.

Authentication

Same Bearer model as REST. Pass the token in the authorization metadata key on every RPC. A minimal Python client (with stubs generated from ze.proto):

import grpc
import ze_pb2, ze_pb2_grpc     # from protoc output

channel = grpc.insecure_channel("localhost:50051")
stub = ze_pb2_grpc.ZeServiceStub(channel)

metadata = [("authorization", "Bearer alice:password123")]
resp = stub.Execute(
    ze_pb2.CommandRequest(command="bgp summary"),
    metadata=metadata,
)

The exact import path for ze_pb2 depends on how you run protoc--python_out=. puts it at the repo root, --python_out=gen/ puts it under gen/, and so on. Generated names come from the proto filename (ze.protoze_pb2), not from the ze.api.v1 proto package.

Three auth modes, in precedence order:

Mode How to enable How clients authenticate
Per-user (recommended) ze init creates the zefs user database. authorization: Bearer username:password
Single token ze.api-server.token=<secret> or YANG api-server { token "secret"; }. authorization: Bearer <secret>
No auth Leave both unset. No header required.

Do not run with no auth on any network-reachable port.

Reflection

gRPC server reflection is enabled by default, so you can discover the schema with grpcurl without a proto file on disk:

# List available services
grpcurl -plaintext localhost:50051 list

# Describe one service
grpcurl -plaintext localhost:50051 describe ze.api.v1.ZeService

# Execute a command
grpcurl -plaintext \
    -H "authorization: Bearer alice:password123" \
    -d '{"command":"bgp summary"}' \
    localhost:50051 ze.api.v1.ZeService/Execute

For clients that want generated stubs, copy api/proto/ze.proto out of the source tree and run protoc against it.

TLS

TLS is configured via YANG. Both cert and key must be set:

environment {
    api-server {
        grpc {
            enabled true;
            tls-cert "/etc/ze/server.pem";
            tls-key  "/etc/ze/server.key";
        }
    }
}

Minimum TLS version is 1.2. Unlike REST, gRPC's TLS is transport-native — no reverse proxy is needed.

Streaming commands

Stream is a server-stream RPC. The server sends one CommandResponse message per chunk until the command completes or the client closes the stream. Use this for peer monitor, rib watch, or any other command that produces output over time.

req = ze_pb2.CommandRequest(command="peer monitor")
for chunk in stub.Stream(req, metadata=metadata):
    print(chunk.data)

The equivalent over REST is the Server-Sent Events endpoint.

Input validation

The gRPC server applies the same command-string validation as REST: path-segment checks, whitespace rejection in params, and hex-format session IDs. These prevent tokenizer confusion when user input flows into dispatcher command strings.

Generating clients

To generate client stubs from the proto:

# Go
protoc --go_out=. --go-grpc_out=. api/proto/ze.proto

# Python
python -m grpc_tools.protoc -I api/proto \
    --python_out=. --grpc_python_out=. api/proto/ze.proto

# Rust (with tonic)
# Add to build.rs: tonic_build::compile_protos("api/proto/ze.proto")?;

You need protoc, protoc-gen-go, and protoc-gen-go-grpc for the Go targets. See building for the dev-tool setup.

See also

  • REST API for the HTTP/JSON counterpart.
  • Web UI for the interactive browser surface.
  • MCP for an AI-assistant typed-tool surface.
  • Building for protoc setup if you want to regenerate proto stubs.

Adapted from main/docs/guide/api.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally