Connecting to IBM Cloud Databases for Redis from Node.js
Tags: node, redis, ibmcloud
Published: 2019-07-22 14:48:13

---
title: "Connecting to IBM Cloud Databases for Redis from Node.js"
published: true
description: "How to use self-signed TLS certificates with the Redis library on Node.js with IBM Cloud Databases."
canonical_url: http://jamesthom.as/blog/2019/07/22/connecting-to-ibm-cloud-databases-for-redis-from-node-dot-js/
tags: node.js, redis, ibmcloud
---


This blog post explains how to connect to an [IBM Cloud Databases for Redis](https://www.ibm.com/cloud/databases-for-redis) instance from a [Node.js](https://nodejs.org/en/) application. There is a (small) difference between the connection details needed for an IBM Cloud Databases for Redis instance compared to a local instance of the open-source database. This is due to all IBM Cloud Databases using [secured TLS connections](https://cloud.ibm.com/docs/services/databases-for-redis?topic=databases-for-redis-external-app#driver-tls-and-self-signed-certificate-support) with [self-signed certificates](https://en.wikipedia.org/wiki/Self-signed_certificate).

*I keep running into this issue (and forgetting how to fix it* 🤦‍♂️*), so I'm documenting the solution here to help myself (and others) who might run into it…* 🦸‍♂️

## Connecting to Redis (without TLS connections)

Most Node.js application use the `redis` [NPM library](https://www.npmjs.com/package/redis) to interact with an instance of the database. This library has a `createClient` [method]() which returns an instance of the client. The Node.js application passes a connection string into the `createClient` method. This string contains the hostname, port, username and password for the database instance.

```javascript
const redis = require("redis"),
const url = 'redis://user:secret@localhost:6379/'
const client = redis.createClient(url);
```

The client fires a `connect` event once the [connection is established](https://github.com/NodeRedis/node_redis#connection-and-other-events) or an `error` event if [issues are encountered](https://github.com/NodeRedis/node_redis#connection-and-other-events).

## IBM Cloud Databases for Redis Service Credentials

IBM Cloud Databases for Redis provide service credentials through the [instance management console](https://cloud.ibm.com/docs/services/databases-for-redis?topic=databases-for-redis-connection-strings#the-_service-credentials_-panel). Service credentials are JSON objects with connection properties for client libraries, the CLI and other tools. Connection strings for the Node.js client library are available in the `connection.rediss.composed` field.

***So, I just copy this field value and use with the `redis.createClient` method? Not so fast...***

IBM Cloud Databases for Redis uses TLS to secure all connections to the Redis instances. This is denoted by the connection string using the `rediss://` URL prefix, rather than `redis://`. Using that connection string (without further connection properties), will lead to the following error being thrown by the Node.js application.

```
Error: Redis connection to <id>.databases.appdomain.cloud:port failed - read ECONNRESET
  at TCP.onread (net.js:657:25) errno: 'ECONNRESET', code: 'ECONNRESET', syscall: 'read'
```

If the `createClient` forces a TLS connection to be used `createClient(url, { tls: {} })`, this error will be replaced with a different one about self-signed certificates.

```
Error: Redis connection to <id>.databases.appdomain.cloud:port failed failed - self signed certificate in certificate chain
    at TLSSocket.onConnectSecure (_tls_wrap.js:1055:34)
    at TLSSocket.emit (events.js:182:13)
    at TLSSocket._finishInit (_tls_wrap.js:635:8) code: 'SELF_SIGNED_CERT_IN_CHAIN'
```

*Hmmmm, how to fix this?* 🤔

## Connecting to Redis (with TLS connections)

All connections to IBM Cloud Databases are secured with TLS using self-signed certificates. Public certificates for the signing authorities are provided as Base64 strings in the service credentials. These certificates can be provided in the client constructor to support self-signed TLS connections.

***Here are the steps needed to use those self-signed certificates with the client library...***

- Extract the `connection.rediss.certificate.certificate_base64` value from the service credentials.

![Redis Service Credentials](https://thepracticaldev.s3.amazonaws.com/i/ecu7eduv9u6f343kkurn.png)


- Decode the Base64 string in Node.js to extract the PEM certificate string.

```javascript
const ca = Buffer.from(cert_base64, 'base64').toString('utf-8')
```

- Provide the certificate file string as the `ca` property in the `tls` object for the client constructor.

```javascript
const tls = { ca };
const client = redis.createClient(url, { tls });
```

- …Relax! 😎

*The `tls` property is passed through to the `tls.connect` [method](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback) in Node.js, which is used to setup the TLS connection. This method supports a `ca` parameter to extend the trusted CA certificates pre-installed in the system. By providing the self-signed certificate using this property, the errors above will not be seen.*

## Conclusion

It took me a while to [work out](https://compose.com/articles/ssl-connections-arrive-for-redis-on-compose/) how to connect to TLS-secured Redis instances from a Node.js application. [Providing the self-signed certificate](https://stackoverflow.com/questions/10888610/ignore-invalid-self-signed-ssl-certificate-in-node-js-with-https-request/39099130#39099130) in the client constructor is a much better solution than having to [disable  all unauthorised TLS connections](https://stackoverflow.com/a/21961005/1427084)!

Since I don't write new Redis client code very often, I keep forgetting the correct constructor parameters to make this work. Turning this solution into a blog post will (hopefully) embed it in my brain (or at least provide a way to find the answer instead of having to grep through old project code). This might even be useful to others Googling for a solution to those error messages...