Credentials
gRPC runs over HTTP/2, so TLS is a natural fit. By default gRPCity does not require certificates and traffic flows in plaintext — fine for trusted internal links, risky on shared networks. Turn on TLS when you need confidentiality, integrity, or peer authentication.
TLS adds CPU cost on both ends. For very-high-QPS internal services, weigh that against the threat model.
Generating certificates
Use OpenSSL to mint a self-signed CA plus a server and client certificate signed by it. The shell snippets below stash common parameters in a few variables and produce the certs in a certs/ directory.
# Create the certs directory
mkdir -p certs && cd certs
# Set password variable
password="grpcity"
# Set certificate validity period variable
days=365CA certificate
# Set CA-related variables
ca_key="ca.key"
ca_crt="ca.crt"
ca_subject="/C=CN/ST=GD/L=Guangzhou/O=gRPCity/OU=gRPCity/CN=ca"
# Generate CA key and certificate
openssl genrsa -passout pass:$password -des3 -out $ca_key 4096
openssl req -passin pass:$password -new -x509 -days $days -key $ca_key -out $ca_crt -subj "$ca_subject"Server certificate
# Set server-related variables
server_key="server.key"
server_csr="server.csr"
server_crt="server.crt"
server_subject="/C=CN/ST=GD/L=Guangzhou/O=gRPCity/OU=Server/CN=localhost"
# Generate server key and certificate
openssl genrsa -passout pass:$password -des3 -out $server_key 4096
openssl req -passin pass:$password -new -key $server_key -out $server_csr -subj "$server_subject"
openssl x509 -req -passin pass:$password -days $days -in $server_csr -CA $ca_crt -CAkey $ca_key -set_serial 01 -out $server_crt
openssl rsa -passin pass:$password -in $server_key -out $server_keyClient certificate
# Set client-related variables
client_key="client.key"
client_csr="client.csr"
client_crt="client.crt"
client_subject="/C=CN/ST=GD/L=Guangzhou/O=gRPCity/OU=Client/CN=localhost"
# Generate client key and certificate
openssl genrsa -passout pass:$password -des3 -out $client_key 4096
openssl req -passin pass:$password -new -key $client_key -out $client_csr -subj "$client_subject"
openssl x509 -passin pass:$password -req -days $days -in $client_csr -CA $ca_crt -CAkey $ca_key -set_serial 01 -out $client_crt
openssl rsa -passin pass:$password -in $client_key -out $client_keyIn the end, we have the following certificate directory:
.
└── certs
├── ca.crt
├── ca.key
├── client.crt
├── client.csr
├── client.key
├── server.crt
├── server.csr
└── server.keyBuilding credentials manually
loader.makeServerCredentials() and loader.makeClientCredentials() cover the common path. When you need finer control — createFromSecureContext, Google ADC, composed credentials — gRPCity also re-exports the credentials namespace and the ChannelCredentials / ServerCredentials types, so you don’t have to depend on @grpc/grpc-js:
import { credentials } from 'grpcity'
const insecure = credentials.createInsecure()Server configuration
Use loader.makeServerCredentials() to wire up certificates on the server side.
The parameters for loader.makeServerCredentials(rootCerts, keyCertPairs, checkClientCertificate) are as follows:
rootCerts: Root certificate, usually the CA certificate;keyCertPairs: Certificate pair, key and crt, must be an array;checkClientCertificate: Whether to check the client certificate;
Example:
import fs from 'node:fs'
import loader from './loader.js'
const credentials = loader.makeServerCredentials(
fs.readFileSync(path.resolve(__dirname, 'certs/ca.crt')), [{
private_key: fs.readFileSync(path.resolve(__dirname, 'certs/server.key')),
cert_chain: fs.readFileSync(path.resolve(__dirname, 'certs/server.crt'))
}], true)Certificates can be loaded into the server in two ways:
- During initialization
const server = await loader.initServer({ credentials })- During listening startup
await server.listen(addr, credentials)Priority: listen() takes precedence over initServer()
After using certificates, the server cannot be started using an IP address; you can use localhost or a domain name instead.
Client configuration
Let’s start the client certificate configuration. Use loader.makeCredentials() to load the certificates.
import fs from 'node:fs'
import path from 'node:path'
const credentials = loader.makeClientCredentials(
fs.readFileSync(path.resolve(__dirname, 'certs/ca.crt')),
fs.readFileSync(path.resolve(__dirname, 'certs/client.key')),
fs.readFileSync(path.resolve(__dirname, 'certs/client.crt'))
)After obtaining credentials, there are two ways to load them, as shown below:
- Loading during
initClients()
const clients = await loader.initClients({
services: {
'test.helloworld.Greeter': addr,
'test.helloworld.Hellor': addr
},
credentials
})- Loading during
get()orgetReal()
const greeterClient = clients.get('test.helloworld.Greeter', { credentials })
const result = await greeterClient.sayHello({ name: 'greeter' })initClients()is suitable for scenarios where all servers use the same certificate.get()is suitable for scenarios where different servers have different certificates.