6

I dont seem to be able to connect to Heroku Redis using TLS on Node.

These docs arent really much help: https://devcenter.heroku.com/articles/securing-heroku-redis

Does anyone have a working example? Should I be using REDIS_URL or REDIS_TLS_URL?

Im using node_redis v3

mikeysee
  • 1,613
  • 1
  • 18
  • 31

6 Answers6

12

I found the Redis 6 add-on by Heroku generated an Error: self signed certificate in certificate chain error when when connecting to REDIS_URL without any parameters with ioredis on Node. You can avoid this error by passing in TLS options with rejectUnauthorized set to false.

The rejectUnauthorized of false allows for self-signed certificates, which would be an issue if concerned about MITM attacks. See TLS options for more background.

This is working for me with the latest ioredis package with rediss:// and redis:// URL's...

  const REDIS_URL = process.env.REDIS_URL;
  const redis_uri = url.parse(REDIS_URL);
  const redisOptions = REDIS_URL.includes("rediss://")
    ? {
        port: Number(redis_uri.port),
        host: redis_uri.hostname,
        password: redis_uri.auth.split(":")[1],
        db: 0,
        tls: {
          rejectUnauthorized: false,
        },
      }
    : REDIS_URL;
  const redis = new Redis(redisOptions);
Dharman
  • 30,962
  • 25
  • 85
  • 135
Tom McLellan
  • 136
  • 4
1

Here's my approach. It's easier to pass URL and TLS options separately.

const redisUrl = process.env.REDIS_TLS_URL ? process.env.REDIS_TLS_URL : process.env.REDIS_URL;
const redisDefaults = {
  tls: {
  // Heroku uses self-signed certificate, which will cause error in connection, unless check is disabled
  rejectUnauthorized: false,
  },
};
const defaultClient = redis.createClient(redisUrl, redisDefaults);

If you have test env running with hobby version, the TLS is URL is set in REDIS_TLS_URL, while production normally runs with premium and the env is REDIS_URL. So, to be compatible with the both, I first look for REDIS_TLS_URL and after that REDIS_URL to support both test and prod env.

Perttu T
  • 561
  • 1
  • 5
  • 7
1

For devs using node-redis, you'll need to set TLS to true when initializing your client.

redis.createClient({
        url: REDIS_URL,
        socket: {
          tls: true,
          rejectUnauthorized: false,
        },
      }
Mehdi Fracso
  • 448
  • 2
  • 16
0

I don't know why you can't connect to this Redis Add-on unfortunately.

In the event you want to test on another Add-On, I have developped a Redis Add-On that is in the "alpha" phrase (free) on Heroku. I'll be able to provide you some support if you can't connect to it.

If you are interested, give me your Heroku email in private and I'll send you an invitation :)

Adrien
  • 1
  • 2
  • Thats very kind, but I would rather use the official heroku offering if possible. Do you have a working node_redis example of how to connect to your instance tho? – mikeysee Dec 18 '20 at 01:19
  • I totally understand. If you change your mind, don't hesitate to send me a private message. And yes, I do have documentation about connecting to it using Node.js (the documentation is not published on Heroku yet as the add-on is not visibled but I'll can send it to you). – Adrien Dec 18 '20 at 14:49
  • that would be awesome: mike.cann@gmail.com :) – mikeysee Dec 18 '20 at 22:06
  • Invitation and documentation sent :) – Adrien Dec 19 '20 at 07:52
0

For people using Bull, this implementation worked for me. Thanks @Tom McLellan.

const Queue = require('bull');
const redisUrlParse = require('redis-url-parse');

const REDIS_URL = process.env.REDIS_URL || 'redis://127.0.0.1:6379';
const redisUrlParsed = redisUrlParse(REDIS_URL);
const { host, port, password } = redisUrlParsed;
const bullOptions = REDIS_URL.includes('rediss://')
  ? {
      redis: {
        port: Number(port),
        host,
        password,
        tls: {
          rejectUnauthorized: false,
        },
      },
    }
  : REDIS_URL;

const workQueue = new Queue('work', bullOptions);
yeoman
  • 359
  • 2
  • 6
0

This worked for me using node-redis v3.0.0

const opts = config.REDIS_URL.includes('rediss://') ? {
  url: config.REDIS_URL,
  tls: {
    rejectUnauthorized: false
  }
} : config.REDIS_URL;

const client = redis.createClient(opts);

Use tls not socket. Thanks to this.

roboli
  • 1,418
  • 20
  • 24