Traefik doesn’t just proxy HTTP; it can route gRPC traffic, and it does it by treating gRPC as just another protocol, not a special case.

Let’s see Traefik routing a gRPC service, specifically a simple "echo" service. We’ll use grpcurl to interact with it.

First, we need a gRPC server. Here’s a minimal Go main.go:

package main

import (
	"context"
	"fmt"
	"log"
	"net"

	"google.golang.org/grpc"
	pb "google.golang.org/grpc/examples/helloworld/helloworld" // Using a standard example proto
)

const (
	port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

We’ll build this and run it:

go build -o grpc-server main.go
./grpc-server

Now, let’s set up Traefik. Traefik needs to be configured to listen for gRPC traffic and route it to our server. Traefik’s gRPC support is enabled by default if you have a grpc provider configured. The key is that Traefik doesn’t need a special "gRPC router" type; it uses standard HTTP routers but understands the grpc scheme for service discovery and the Content-Type: application/grpc header.

Here’s a traefik.yml configuration:

entryPoints:
  web:
    address: ":80"
  grpc:
    address: ":50052" # Traefik will listen for gRPC on this port

providers:
  docker:
    exposedByDefault: false
  file:
    filename: "/etc/traefik/dynamic_conf/routes.yml"

api:
  dashboard: true
  insecure: true

And the dynamic configuration routes.yml:

http:
  routers:
    my-grpc-router:
      rule: "Host(`grpc.example.com`)" # Or you can use PathPrefix
      entryPoints:
        - "grpc" # This router only listens on the 'grpc' entrypoint
      service: "my-grpc-service"

  services:
    my-grpc-service:
      loadBalancer:
        servers:
          - url: "grpc://127.0.0.1:50051" # The gRPC scheme tells Traefik it's a gRPC service

We’ll run Traefik with this configuration. If you’re using Docker, you’d mount these config files into the container. For simplicity, let’s assume Traefik is running locally with these files.

The crucial part is loadBalancer.servers using the grpc:// scheme. Traefik inspects this. When it receives a request on the grpc entrypoint (port 50052) with Host: grpc.example.com and Content-Type: application/grpc, it knows to forward it to the grpc://127.0.0.1:50051 backend. It doesn’t parse the gRPC protocol itself; it just forwards the raw TCP connection.

Now, let’s test it with grpcurl. We need to tell grpcurl to use the Traefik address and the correct host header.

grpcurl -plaintext -proto helloworld.proto -d '{"name": "World"}' grpc.example.com:50052

Make sure you have helloworld.proto available. If you don’t have it, you can get it from the gRPC Go examples or define a simple one:

syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

The grpcurl command sends a request to grpc.example.com:50052. Traefik, listening on port 50052, sees the Host header and the Content-Type: application/grpc. It matches my-grpc-router and forwards the request to 127.0.0.1:50051 using the grpc:// scheme. Your gRPC server receives it, processes it, and sends a reply back through Traefik.

The grpc:// scheme is the key indicator that Traefik should treat the backend as a gRPC service. This allows Traefik to correctly associate gRPC requests with the appropriate backend services, even though it doesn’t deeply inspect the gRPC payloads. It’s a transparent proxy for gRPC, just like it is for HTTP.

This setup is remarkably similar to HTTP routing, with the primary differences being the grpc:// scheme in the service definition and the grpc entrypoint configuration. Traefik’s ability to handle gRPC is more about correctly identifying and forwarding traffic based on standard HTTP/gRPC headers and schemes rather than implementing gRPC-specific logic.

The next step in managing gRPC services with Traefik would be to explore TLS termination for gRPC, which involves configuring Traefik to handle the TLS handshake before forwarding the decrypted gRPC traffic to your backend.

Want structured learning?

Take the full Traefik course →