In this post I’ll show you how to configure a Go gRPC client and server using Let’s Encrypt TLS certificates. This ended up being very simple thanks to the autocert package. Note that at this point that package is not stable, so you should vendor it in your code.

Autocert implements the tls.GetCertificate function and requires a directory to cache certificates in to avoid excessive calls to Let’s Encrypt.

package acme // import github.com/devoid/example/acme
import (
    "crypto/tls"

    "golang.org/x/crypto/acme/autocert"
)

const contactEmail = "yourname@example.com"

func GetTLS(host, cacheDir string) (*tls.Config, error) {
    manager := autocert.Manager{
        Prompt: autocert.AcceptTOS,
        Cache: autocert.DirCach(cacheDir),
        HostPolicy: autocert.HostWhitelist(host),
        Email: contactEmail,
    }
    return &tls.Config{ GetCertificate: manager.GetCertificate }, nil
}

On the gRPC server side, you simply use this *tls.Config as a transport credentials object. On the client side, the zero-initialized &tls.Config{} is sufficient since this defaults to the operating-system’s default root certificates.

grpc
  • server
  • client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package server

import(
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"

    "github.com/devoid/example/acme"
)

func NewServer(host, cacheDir string) error {

    tls, err := acme.GetTLS(host, cacheDir)
    if err != nil {
        return err
    }

    creds := credentials.NewTLS(tls)
    server := grpc.NewServer(Creds(creds))

    // Register your gRPC services now
    
    lis, err := net.Listen(":https")
    if err != nil {
        return err
    }

    return server.Serve(lis)
}