gRPC examples

With HTTP (h2c)

This section explains how to use Traefik as reverse proxy for gRPC application.

Traefik configuration

At last, we configure our Traefik instance to use both self-signed certificates.

  1. defaultEntryPoints = ["https"]
  2. [entryPoints]
  3. [entryPoints.http]
  4. address = ":80"
  5. [api]
  6. [file]
  7. [backends]
  8. [backends.backend1]
  9. [backends.backend1.servers.server1]
  10. # Access on backend with h2c
  11. url = "h2c://backend.local:8080"
  12. [frontends]
  13. [frontends.frontend1]
  14. backend = "backend1"
  15. [frontends.frontend1.routes.test_1]
  16. rule = "Host:frontend.local"

Warning

For provider with label, you will have to specify the traefik.protocol=h2c

Conclusion

We don't need specific configuration to use gRPC in Traefik, we just need to use h2c protocol, or use HTTPS communications to have HTTP2 with the backend.

With HTTPS

This section explains how to use Traefik as reverse proxy for gRPC application with self-signed certificates.

gRPC architecture

gRPC Server certificate

In order to secure the gRPC server, we generate a self-signed certificate for backend url:

  1. openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./backend.key -out ./backend.cert

That will prompt for information, the important answer is:

  1. Common Name (e.g. server FQDN or YOUR name) []: backend.local

gRPC Client certificate

Generate your self-signed certificate for frontend url:

  1. openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./frontend.key -out ./frontend.cert

with

  1. Common Name (e.g. server FQDN or YOUR name) []: frontend.local

Traefik configuration

At last, we configure our Traefik instance to use both self-signed certificates.

  1. defaultEntryPoints = ["https"]
  2. # For secure connection on backend.local
  3. rootCAs = [ "./backend.cert" ]
  4. [entryPoints]
  5. [entryPoints.https]
  6. address = ":4443"
  7. [entryPoints.https.tls]
  8. # For secure connection on frontend.local
  9. [[entryPoints.https.tls.certificates]]
  10. certFile = "./frontend.cert"
  11. keyFile = "./frontend.key"
  12. [api]
  13. [file]
  14. [backends]
  15. [backends.backend1]
  16. [backends.backend1.servers.server1]
  17. # Access on backend with HTTPS
  18. url = "https://backend.local:8080"
  19. [frontends]
  20. [frontends.frontend1]
  21. backend = "backend1"
  22. [frontends.frontend1.routes.test_1]
  23. rule = "Host:frontend.local"

Warning

With some backends, the server URLs use the IP, so you may need to configure insecureSkipVerify instead of the rootCAS to activate HTTPS without hostname verification.

A gRPC example in go (modify for https)

We use the gRPC greeter example in grpc-go

Warning

In order to use this gRPC example, we need to modify it to use HTTPS

So we modify the "gRPC server example" to use our own self-signed certificate:

  1. // ...
  2. // Read cert and key file
  3. BackendCert, _ := ioutil.ReadFile("./backend.cert")
  4. BackendKey, _ := ioutil.ReadFile("./backend.key")
  5. // Generate Certificate struct
  6. cert, err := tls.X509KeyPair(BackendCert, BackendKey)
  7. if err != nil {
  8. log.Fatalf("failed to parse certificate: %v", err)
  9. }
  10. // Create credentials
  11. creds := credentials.NewServerTLSFromCert(&cert)
  12. // Use Credentials in gRPC server options
  13. serverOption := grpc.Creds(creds)
  14. var s *grpc.Server = grpc.NewServer(serverOption)
  15. defer s.Stop()
  16. pb.RegisterGreeterServer(s, &server{})
  17. err := s.Serve(lis)
  18. // ...

Next we will modify gRPC Client to use our Traefik self-signed certificate:

  1. // ...
  2. // Read cert file
  3. FrontendCert, _ := ioutil.ReadFile("./frontend.cert")
  4. // Create CertPool
  5. roots := x509.NewCertPool()
  6. roots.AppendCertsFromPEM(FrontendCert)
  7. // Create credentials
  8. credsClient := credentials.NewClientTLSFromCert(roots, "")
  9. // Dial with specific Transport (with credentials)
  10. conn, err := grpc.Dial("frontend.local:4443", grpc.WithTransportCredentials(credsClient))
  11. if err != nil {
  12. log.Fatalf("did not connect: %v", err)
  13. }
  14. defer conn.Close()
  15. client := pb.NewGreeterClient(conn)
  16. name := "World"
  17. r, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: name})
  18. // ...