diff --git a/command/debug.go b/command/debug.go
index 5ea2c9f44a270cad9b7627398b0de1c97193181d..f3f2484b0baff382fc8d949196649fb32c0f3cd9 100644
--- a/command/debug.go
+++ b/command/debug.go
@@ -6,7 +6,6 @@ import (
 	"archive/tar"
 	"compress/gzip"
 	"context"
-	"encoding/hex"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -19,6 +18,10 @@ import (
 
 	"github.com/ethereum/go-ethereum/command/flagset"
 	"github.com/ethereum/go-ethereum/command/server/proto"
+	"github.com/golang/protobuf/jsonpb"
+	gproto "github.com/golang/protobuf/proto"
+	"github.com/golang/protobuf/ptypes/empty"
+	grpc_net_conn "github.com/mitchellh/go-grpc-net-conn"
 )
 
 type DebugCommand struct {
@@ -118,16 +121,35 @@ func (d *DebugCommand) Run(args []string) int {
 			req.Type = proto.PprofRequest_LOOKUP
 			req.Profile = profile
 		}
-		resp, err := clt.Pprof(ctx, req)
+		stream, err := clt.Pprof(ctx, req)
 		if err != nil {
 			return err
 		}
-		// write file
-		raw, err := hex.DecodeString(resp.Payload)
+		// wait for open request
+		msg, err := stream.Recv()
 		if err != nil {
 			return err
 		}
-		if err := ioutil.WriteFile(filepath.Join(tmp, filename+".prof"), raw, 0755); err != nil {
+		if _, ok := msg.Event.(*proto.PprofResponse_Open_); !ok {
+			return fmt.Errorf("expected open message")
+		}
+
+		// create the stream
+		conn := &grpc_net_conn.Conn{
+			Stream:   stream,
+			Response: &proto.PprofResponse_Input{},
+			Decode: grpc_net_conn.SimpleDecoder(func(msg gproto.Message) *[]byte {
+				return &msg.(*proto.PprofResponse_Input).Data
+			}),
+		}
+
+		file, err := os.OpenFile(filepath.Join(tmp, filename+".prof"), os.O_RDWR|os.O_CREATE, 0644)
+		if err != nil {
+			return err
+		}
+		defer file.Close()
+
+		if _, err := io.Copy(file, conn); err != nil {
 			return err
 		}
 		return nil
@@ -148,6 +170,25 @@ func (d *DebugCommand) Run(args []string) int {
 		}
 	}
 
+	// append the status
+	{
+		statusResp, err := clt.Status(ctx, &empty.Empty{})
+		if err != nil {
+			d.UI.Output(fmt.Sprintf("Failed to get status: %v", err))
+			return 1
+		}
+		m := jsonpb.Marshaler{}
+		data, err := m.MarshalToString(statusResp)
+		if err != nil {
+			d.UI.Output(err.Error())
+			return 1
+		}
+		if err := ioutil.WriteFile(filepath.Join(tmp, "status.json"), []byte(data), 0644); err != nil {
+			d.UI.Output(fmt.Sprintf("Failed to write status: %v", err))
+			return 1
+		}
+	}
+
 	// Exit before archive if output directory was specified
 	if d.output != "" {
 		d.UI.Output(fmt.Sprintf("Created debug directory: %s", tmp))
diff --git a/command/server/proto/server.pb.go b/command/server/proto/server.pb.go
index bfa0b7eaf99ceba0c3116b417929a60b5b0e7f2b..d1a5ed77b2b3b25a947df24c4c7cff9b30a6ba40 100644
--- a/command/server/proto/server.pb.go
+++ b/command/server/proto/server.pb.go
@@ -830,8 +830,11 @@ type PprofResponse struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Payload string            `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
-	Headers map[string]string `protobuf:"bytes,2,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	// Types that are assignable to Event:
+	//	*PprofResponse_Open_
+	//	*PprofResponse_Input_
+	//	*PprofResponse_Eof
+	Event isPprofResponse_Event `protobuf_oneof:"event"`
 }
 
 func (x *PprofResponse) Reset() {
@@ -866,20 +869,56 @@ func (*PprofResponse) Descriptor() ([]byte, []int) {
 	return file_command_server_proto_server_proto_rawDescGZIP(), []int{14}
 }
 
-func (x *PprofResponse) GetPayload() string {
-	if x != nil {
-		return x.Payload
+func (m *PprofResponse) GetEvent() isPprofResponse_Event {
+	if m != nil {
+		return m.Event
 	}
-	return ""
+	return nil
 }
 
-func (x *PprofResponse) GetHeaders() map[string]string {
-	if x != nil {
-		return x.Headers
+func (x *PprofResponse) GetOpen() *PprofResponse_Open {
+	if x, ok := x.GetEvent().(*PprofResponse_Open_); ok {
+		return x.Open
 	}
 	return nil
 }
 
+func (x *PprofResponse) GetInput() *PprofResponse_Input {
+	if x, ok := x.GetEvent().(*PprofResponse_Input_); ok {
+		return x.Input
+	}
+	return nil
+}
+
+func (x *PprofResponse) GetEof() *empty.Empty {
+	if x, ok := x.GetEvent().(*PprofResponse_Eof); ok {
+		return x.Eof
+	}
+	return nil
+}
+
+type isPprofResponse_Event interface {
+	isPprofResponse_Event()
+}
+
+type PprofResponse_Open_ struct {
+	Open *PprofResponse_Open `protobuf:"bytes,1,opt,name=open,proto3,oneof"`
+}
+
+type PprofResponse_Input_ struct {
+	Input *PprofResponse_Input `protobuf:"bytes,2,opt,name=input,proto3,oneof"`
+}
+
+type PprofResponse_Eof struct {
+	Eof *empty.Empty `protobuf:"bytes,3,opt,name=eof,proto3,oneof"`
+}
+
+func (*PprofResponse_Open_) isPprofResponse_Event() {}
+
+func (*PprofResponse_Input_) isPprofResponse_Event() {}
+
+func (*PprofResponse_Eof) isPprofResponse_Event() {}
+
 type StatusResponse_Fork struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1006,6 +1045,108 @@ func (x *StatusResponse_Syncing) GetCurrentBlock() int64 {
 	return 0
 }
 
+type PprofResponse_Open struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Headers map[string]string `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	Size    int64             `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
+}
+
+func (x *PprofResponse_Open) Reset() {
+	*x = PprofResponse_Open{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_command_server_proto_server_proto_msgTypes[17]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *PprofResponse_Open) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PprofResponse_Open) ProtoMessage() {}
+
+func (x *PprofResponse_Open) ProtoReflect() protoreflect.Message {
+	mi := &file_command_server_proto_server_proto_msgTypes[17]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use PprofResponse_Open.ProtoReflect.Descriptor instead.
+func (*PprofResponse_Open) Descriptor() ([]byte, []int) {
+	return file_command_server_proto_server_proto_rawDescGZIP(), []int{14, 0}
+}
+
+func (x *PprofResponse_Open) GetHeaders() map[string]string {
+	if x != nil {
+		return x.Headers
+	}
+	return nil
+}
+
+func (x *PprofResponse_Open) GetSize() int64 {
+	if x != nil {
+		return x.Size
+	}
+	return 0
+}
+
+type PprofResponse_Input struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+}
+
+func (x *PprofResponse_Input) Reset() {
+	*x = PprofResponse_Input{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_command_server_proto_server_proto_msgTypes[18]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *PprofResponse_Input) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PprofResponse_Input) ProtoMessage() {}
+
+func (x *PprofResponse_Input) ProtoReflect() protoreflect.Message {
+	mi := &file_command_server_proto_server_proto_msgTypes[18]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use PprofResponse_Input.ProtoReflect.Descriptor instead.
+func (*PprofResponse_Input) Descriptor() ([]byte, []int) {
+	return file_command_server_proto_server_proto_rawDescGZIP(), []int{14, 1}
+}
+
+func (x *PprofResponse_Input) GetData() []byte {
+	if x != nil {
+		return x.Data
+	}
+	return nil
+}
+
 var File_command_server_proto_server_proto protoreflect.FileDescriptor
 
 var file_command_server_proto_server_proto_rawDesc = []byte{
@@ -1093,47 +1234,60 @@ var file_command_server_proto_server_proto_rawDesc = []byte{
 	0x28, 0x03, 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x26, 0x0a, 0x04, 0x54,
 	0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x10, 0x00, 0x12,
 	0x07, 0x0a, 0x03, 0x43, 0x50, 0x55, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43,
-	0x45, 0x10, 0x02, 0x22, 0xa2, 0x01, 0x0a, 0x0d, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12,
-	0x3b, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e,
-	0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x3a, 0x0a, 0x0c,
-	0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
-	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xc4, 0x03, 0x0a, 0x03, 0x42, 0x6f, 0x72,
-	0x12, 0x32, 0x0a, 0x05, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64,
-	0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64,
-	0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
-	0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65,
-	0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x73,
-	0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65,
-	0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73,
-	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50,
-	0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53,
-	0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a,
-	0x0c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1a, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65,
-	0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
-	0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
-	0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
-	0x17, 0x5a, 0x15, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76,
-	0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x45, 0x10, 0x02, 0x22, 0xe1, 0x02, 0x0a, 0x0d, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f,
+	0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x48, 0x00,
+	0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70,
+	0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x70, 0x75,
+	0x74, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x2a, 0x0a, 0x03, 0x65, 0x6f,
+	0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x48,
+	0x00, 0x52, 0x03, 0x65, 0x6f, 0x66, 0x1a, 0x98, 0x01, 0x0a, 0x04, 0x4f, 0x70, 0x65, 0x6e, 0x12,
+	0x40, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64,
+	0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
+	0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+	0x04, 0x73, 0x69, 0x7a, 0x65, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
+	0x01, 0x1a, 0x1b, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61,
+	0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x07,
+	0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x32, 0xc6, 0x03, 0x0a, 0x03, 0x42, 0x6f, 0x72, 0x12,
+	0x34, 0x0a, 0x05, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64,
+	0x64, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41,
+	0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76,
+	0x65, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52,
+	0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72,
+	0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65,
+	0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72,
+	0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+	0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73,
+	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47,
+	0x0a, 0x0c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1a,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48,
+	0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x42, 0x17, 0x5a, 0x15, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x73, 0x65, 0x72,
+	0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x33,
 }
 
 var (
@@ -1149,7 +1303,7 @@ func file_command_server_proto_server_proto_rawDescGZIP() []byte {
 }
 
 var file_command_server_proto_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_command_server_proto_server_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
+var file_command_server_proto_server_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
 var file_command_server_proto_server_proto_goTypes = []interface{}{
 	(PprofRequest_Type)(0),         // 0: proto.PprofRequest.Type
 	(*PeersAddRequest)(nil),        // 1: proto.PeersAddRequest
@@ -1169,8 +1323,10 @@ var file_command_server_proto_server_proto_goTypes = []interface{}{
 	(*PprofResponse)(nil),          // 15: proto.PprofResponse
 	(*StatusResponse_Fork)(nil),    // 16: proto.StatusResponse.Fork
 	(*StatusResponse_Syncing)(nil), // 17: proto.StatusResponse.Syncing
-	nil,                            // 18: proto.PprofResponse.HeadersEntry
-	(*empty.Empty)(nil),            // 19: google.protobuf.Empty
+	(*PprofResponse_Open)(nil),     // 18: proto.PprofResponse.Open
+	(*PprofResponse_Input)(nil),    // 19: proto.PprofResponse.Input
+	nil,                            // 20: proto.PprofResponse.Open.HeadersEntry
+	(*empty.Empty)(nil),            // 21: google.protobuf.Empty
 }
 var file_command_server_proto_server_proto_depIdxs = []int32{
 	9,  // 0: proto.PeersListResponse.peers:type_name -> proto.Peer
@@ -1180,26 +1336,29 @@ var file_command_server_proto_server_proto_depIdxs = []int32{
 	17, // 4: proto.StatusResponse.syncing:type_name -> proto.StatusResponse.Syncing
 	16, // 5: proto.StatusResponse.forks:type_name -> proto.StatusResponse.Fork
 	0,  // 6: proto.PprofRequest.type:type_name -> proto.PprofRequest.Type
-	18, // 7: proto.PprofResponse.headers:type_name -> proto.PprofResponse.HeadersEntry
-	14, // 8: proto.Bor.Pprof:input_type -> proto.PprofRequest
-	1,  // 9: proto.Bor.PeersAdd:input_type -> proto.PeersAddRequest
-	3,  // 10: proto.Bor.PeersRemove:input_type -> proto.PeersRemoveRequest
-	5,  // 11: proto.Bor.PeersList:input_type -> proto.PeersListRequest
-	7,  // 12: proto.Bor.PeersStatus:input_type -> proto.PeersStatusRequest
-	10, // 13: proto.Bor.ChainSetHead:input_type -> proto.ChainSetHeadRequest
-	19, // 14: proto.Bor.Status:input_type -> google.protobuf.Empty
-	15, // 15: proto.Bor.Pprof:output_type -> proto.PprofResponse
-	2,  // 16: proto.Bor.PeersAdd:output_type -> proto.PeersAddResponse
-	4,  // 17: proto.Bor.PeersRemove:output_type -> proto.PeersRemoveResponse
-	6,  // 18: proto.Bor.PeersList:output_type -> proto.PeersListResponse
-	8,  // 19: proto.Bor.PeersStatus:output_type -> proto.PeersStatusResponse
-	11, // 20: proto.Bor.ChainSetHead:output_type -> proto.ChainSetHeadResponse
-	12, // 21: proto.Bor.Status:output_type -> proto.StatusResponse
-	15, // [15:22] is the sub-list for method output_type
-	8,  // [8:15] is the sub-list for method input_type
-	8,  // [8:8] is the sub-list for extension type_name
-	8,  // [8:8] is the sub-list for extension extendee
-	0,  // [0:8] is the sub-list for field type_name
+	18, // 7: proto.PprofResponse.open:type_name -> proto.PprofResponse.Open
+	19, // 8: proto.PprofResponse.input:type_name -> proto.PprofResponse.Input
+	21, // 9: proto.PprofResponse.eof:type_name -> google.protobuf.Empty
+	20, // 10: proto.PprofResponse.Open.headers:type_name -> proto.PprofResponse.Open.HeadersEntry
+	14, // 11: proto.Bor.Pprof:input_type -> proto.PprofRequest
+	1,  // 12: proto.Bor.PeersAdd:input_type -> proto.PeersAddRequest
+	3,  // 13: proto.Bor.PeersRemove:input_type -> proto.PeersRemoveRequest
+	5,  // 14: proto.Bor.PeersList:input_type -> proto.PeersListRequest
+	7,  // 15: proto.Bor.PeersStatus:input_type -> proto.PeersStatusRequest
+	10, // 16: proto.Bor.ChainSetHead:input_type -> proto.ChainSetHeadRequest
+	21, // 17: proto.Bor.Status:input_type -> google.protobuf.Empty
+	15, // 18: proto.Bor.Pprof:output_type -> proto.PprofResponse
+	2,  // 19: proto.Bor.PeersAdd:output_type -> proto.PeersAddResponse
+	4,  // 20: proto.Bor.PeersRemove:output_type -> proto.PeersRemoveResponse
+	6,  // 21: proto.Bor.PeersList:output_type -> proto.PeersListResponse
+	8,  // 22: proto.Bor.PeersStatus:output_type -> proto.PeersStatusResponse
+	11, // 23: proto.Bor.ChainSetHead:output_type -> proto.ChainSetHeadResponse
+	12, // 24: proto.Bor.Status:output_type -> proto.StatusResponse
+	18, // [18:25] is the sub-list for method output_type
+	11, // [11:18] is the sub-list for method input_type
+	11, // [11:11] is the sub-list for extension type_name
+	11, // [11:11] is the sub-list for extension extendee
+	0,  // [0:11] is the sub-list for field type_name
 }
 
 func init() { file_command_server_proto_server_proto_init() }
@@ -1412,6 +1571,35 @@ func file_command_server_proto_server_proto_init() {
 				return nil
 			}
 		}
+		file_command_server_proto_server_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*PprofResponse_Open); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_command_server_proto_server_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*PprofResponse_Input); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	file_command_server_proto_server_proto_msgTypes[14].OneofWrappers = []interface{}{
+		(*PprofResponse_Open_)(nil),
+		(*PprofResponse_Input_)(nil),
+		(*PprofResponse_Eof)(nil),
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
@@ -1419,7 +1607,7 @@ func file_command_server_proto_server_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_command_server_proto_server_proto_rawDesc,
 			NumEnums:      1,
-			NumMessages:   18,
+			NumMessages:   20,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
diff --git a/command/server/proto/server.proto b/command/server/proto/server.proto
index 96b14ccf750f57948800206a34c8c8d0b1d1f4fd..de4fb13dd403ee89201b59fac0579e2ed21fd30a 100644
--- a/command/server/proto/server.proto
+++ b/command/server/proto/server.proto
@@ -7,7 +7,7 @@ import "google/protobuf/empty.proto";
 option go_package = "/command/server/proto";
 
 service Bor {
-    rpc Pprof(PprofRequest) returns (PprofResponse);
+    rpc Pprof(PprofRequest) returns (stream PprofResponse);
 
     rpc PeersAdd(PeersAddRequest) returns (PeersAddResponse);
 
@@ -112,6 +112,18 @@ message PprofRequest {
 }
 
 message PprofResponse {
-    string payload = 1;
-    map<string, string> headers = 2;
+    oneof event {
+        Open open = 1;
+        Input input = 2;
+        google.protobuf.Empty eof = 3;
+    }
+
+    message Open {
+        map<string, string> headers = 1;
+        int64 size = 2;
+    }
+
+    message Input {
+        bytes data = 1;    
+    }
 }
diff --git a/command/server/proto/server_grpc.pb.go b/command/server/proto/server_grpc.pb.go
index e385a16968d2ffd579b9bdae49fcc18baa74826f..7c2540d772fc741e401c622cad6099e1767fc8e5 100644
--- a/command/server/proto/server_grpc.pb.go
+++ b/command/server/proto/server_grpc.pb.go
@@ -19,7 +19,7 @@ const _ = grpc.SupportPackageIsVersion7
 //
 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
 type BorClient interface {
-	Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (*PprofResponse, error)
+	Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (Bor_PprofClient, error)
 	PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error)
 	PeersRemove(ctx context.Context, in *PeersRemoveRequest, opts ...grpc.CallOption) (*PeersRemoveResponse, error)
 	PeersList(ctx context.Context, in *PeersListRequest, opts ...grpc.CallOption) (*PeersListResponse, error)
@@ -36,13 +36,36 @@ func NewBorClient(cc grpc.ClientConnInterface) BorClient {
 	return &borClient{cc}
 }
 
-func (c *borClient) Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (*PprofResponse, error) {
-	out := new(PprofResponse)
-	err := c.cc.Invoke(ctx, "/proto.Bor/Pprof", in, out, opts...)
+func (c *borClient) Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (Bor_PprofClient, error) {
+	stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[0], "/proto.Bor/Pprof", opts...)
 	if err != nil {
 		return nil, err
 	}
-	return out, nil
+	x := &borPprofClient{stream}
+	if err := x.ClientStream.SendMsg(in); err != nil {
+		return nil, err
+	}
+	if err := x.ClientStream.CloseSend(); err != nil {
+		return nil, err
+	}
+	return x, nil
+}
+
+type Bor_PprofClient interface {
+	Recv() (*PprofResponse, error)
+	grpc.ClientStream
+}
+
+type borPprofClient struct {
+	grpc.ClientStream
+}
+
+func (x *borPprofClient) Recv() (*PprofResponse, error) {
+	m := new(PprofResponse)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
 }
 
 func (c *borClient) PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error) {
@@ -103,7 +126,7 @@ func (c *borClient) Status(ctx context.Context, in *empty.Empty, opts ...grpc.Ca
 // All implementations must embed UnimplementedBorServer
 // for forward compatibility
 type BorServer interface {
-	Pprof(context.Context, *PprofRequest) (*PprofResponse, error)
+	Pprof(*PprofRequest, Bor_PprofServer) error
 	PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error)
 	PeersRemove(context.Context, *PeersRemoveRequest) (*PeersRemoveResponse, error)
 	PeersList(context.Context, *PeersListRequest) (*PeersListResponse, error)
@@ -117,8 +140,8 @@ type BorServer interface {
 type UnimplementedBorServer struct {
 }
 
-func (UnimplementedBorServer) Pprof(context.Context, *PprofRequest) (*PprofResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method Pprof not implemented")
+func (UnimplementedBorServer) Pprof(*PprofRequest, Bor_PprofServer) error {
+	return status.Errorf(codes.Unimplemented, "method Pprof not implemented")
 }
 func (UnimplementedBorServer) PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method PeersAdd not implemented")
@@ -151,22 +174,25 @@ func RegisterBorServer(s grpc.ServiceRegistrar, srv BorServer) {
 	s.RegisterService(&Bor_ServiceDesc, srv)
 }
 
-func _Bor_Pprof_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(PprofRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(BorServer).Pprof(ctx, in)
+func _Bor_Pprof_Handler(srv interface{}, stream grpc.ServerStream) error {
+	m := new(PprofRequest)
+	if err := stream.RecvMsg(m); err != nil {
+		return err
 	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.Bor/Pprof",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(BorServer).Pprof(ctx, req.(*PprofRequest))
-	}
-	return interceptor(ctx, in, info, handler)
+	return srv.(BorServer).Pprof(m, &borPprofServer{stream})
+}
+
+type Bor_PprofServer interface {
+	Send(*PprofResponse) error
+	grpc.ServerStream
+}
+
+type borPprofServer struct {
+	grpc.ServerStream
+}
+
+func (x *borPprofServer) Send(m *PprofResponse) error {
+	return x.ServerStream.SendMsg(m)
 }
 
 func _Bor_PeersAdd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -284,10 +310,6 @@ var Bor_ServiceDesc = grpc.ServiceDesc{
 	ServiceName: "proto.Bor",
 	HandlerType: (*BorServer)(nil),
 	Methods: []grpc.MethodDesc{
-		{
-			MethodName: "Pprof",
-			Handler:    _Bor_Pprof_Handler,
-		},
 		{
 			MethodName: "PeersAdd",
 			Handler:    _Bor_PeersAdd_Handler,
@@ -313,6 +335,12 @@ var Bor_ServiceDesc = grpc.ServiceDesc{
 			Handler:    _Bor_Status_Handler,
 		},
 	},
-	Streams:  []grpc.StreamDesc{},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "Pprof",
+			Handler:       _Bor_Pprof_Handler,
+			ServerStreams: true,
+		},
+	},
 	Metadata: "command/server/proto/server.proto",
 }
diff --git a/command/server/service.go b/command/server/service.go
index 30df05857de28c362ea30d403bbdddfbb11fddb9..fe70029aa9741b1eb4b520de3d037ba94a3f61fe 100644
--- a/command/server/service.go
+++ b/command/server/service.go
@@ -2,7 +2,6 @@ package server
 
 import (
 	"context"
-	"encoding/hex"
 	"fmt"
 	"math/big"
 	"reflect"
@@ -13,14 +12,17 @@ import (
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/p2p"
 	"github.com/ethereum/go-ethereum/p2p/enode"
+	gproto "github.com/golang/protobuf/proto"
 	"github.com/golang/protobuf/ptypes/empty"
+	grpc_net_conn "github.com/mitchellh/go-grpc-net-conn"
 )
 
-func (s *Server) Pprof(ctx context.Context, req *proto.PprofRequest) (*proto.PprofResponse, error) {
+func (s *Server) Pprof(req *proto.PprofRequest, stream proto.Bor_PprofServer) error {
 	var payload []byte
 	var headers map[string]string
 	var err error
 
+	ctx := context.Background()
 	switch req.Type {
 	case proto.PprofRequest_CPU:
 		payload, headers, err = pprof.CPUProfile(ctx, int(req.Seconds))
@@ -30,14 +32,42 @@ func (s *Server) Pprof(ctx context.Context, req *proto.PprofRequest) (*proto.Ppr
 		payload, headers, err = pprof.Profile(req.Profile, 0, 0)
 	}
 	if err != nil {
-		return nil, err
+		return err
 	}
 
-	resp := &proto.PprofResponse{
-		Payload: hex.EncodeToString(payload),
-		Headers: headers,
+	// open the stream and send the headers
+	err = stream.Send(&proto.PprofResponse{
+		Event: &proto.PprofResponse_Open_{
+			Open: &proto.PprofResponse_Open{
+				Headers: headers,
+				Size:    int64(len(payload)),
+			},
+		},
+	})
+	if err != nil {
+		return err
 	}
-	return resp, nil
+
+	// Wrap our conn around the response.
+	conn := &grpc_net_conn.Conn{
+		Stream:  stream,
+		Request: &proto.PprofResponse_Input{},
+		Encode: grpc_net_conn.SimpleEncoder(func(msg gproto.Message) *[]byte {
+			return &msg.(*proto.PprofResponse_Input).Data
+		}),
+	}
+	if _, err := conn.Write(payload); err != nil {
+		return err
+	}
+
+	// send the eof
+	err = stream.Send(&proto.PprofResponse{
+		Event: &proto.PprofResponse_Eof{},
+	})
+	if err != nil {
+		return err
+	}
+	return nil
 }
 
 func (s *Server) PeersAdd(ctx context.Context, req *proto.PeersAddRequest) (*proto.PeersAddResponse, error) {
diff --git a/go.mod b/go.mod
index c7718bbbbd81eef006840236c105b02feae452be..8ffc4d00d065832c12c36e8579b1a974e5a04f41 100644
--- a/go.mod
+++ b/go.mod
@@ -53,6 +53,7 @@ require (
 	github.com/mattn/go-colorable v0.1.8
 	github.com/mattn/go-isatty v0.0.12
 	github.com/mitchellh/cli v1.1.2
+	github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0 // indirect
 	github.com/mitchellh/go-homedir v1.1.0
 	github.com/naoina/go-stringutil v0.1.0 // indirect
 	github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
diff --git a/go.sum b/go.sum
index 96d83f3fcc925fd8f3034f8c4a49a7cbe5dcaca2..4fc75e79b09c93496ee4b6e9e91f61ac50d122ce 100644
--- a/go.sum
+++ b/go.sum
@@ -375,6 +375,8 @@ github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=
 github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
 github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
 github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
+github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0 h1:oZuel4h7224ILBLg2SlTxdaMYXDyqcVfL4Cg1PJQHZs=
+github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0/go.mod h1:ZCzL0JMR6qfm7VrDC8HGwVtPA8D2Ijc/edUSBw58x94=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
@@ -732,6 +734,7 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
diff --git a/scripts/tools-protobuf.sh b/scripts/tools-protobuf.sh
old mode 100644
new mode 100755
index 020639f9d9406760d14376afa7023bfdc7c1093a..fe03cab3cb4a1d746099c08368ae348d4cbf8927
--- a/scripts/tools-protobuf.sh
+++ b/scripts/tools-protobuf.sh
@@ -1,5 +1,16 @@
-curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v3.12.0/protoc-3.12.0-linux-x86_64.zip
-sudo unzip protoc-3.12.0-linux-x86_64.zip -d /usr/local/bin
+#!/bin/bash
 
+# Install protobuf
+PROTOC_ZIP=protoc-3.12.0-linux-x86_64.zip
+curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.12.0/$PROTOC_ZIP
+sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
+sudo unzip -o $PROTOC_ZIP -d /usr/local 'include/*'
+rm -f $PROTOC_ZIP
+
+# Change permissions to use the binary
+sudo chmod 755 -R /usr/local/bin/protoc
+sudo chmod 755 -R /usr/local/include
+
+# Install golang extensions (DO NOT CHANGE THE VERSIONS)
 go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.25.0
 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1