Configuring Redis TLS

Transport Layer Security (TLS) is a cryptographic protocol that ensures the secure delivery of data between applications and their Redis databases. With Redis 6 now having built-in TLS support and Heroku with optional support for Hobby-dev tier, it was time to utilize TLS with minimal effort!

Related Tech Stack

Docker-compose
Redis 6
Heroku-Redis
Bull – Arena
– React – NodeJS
Ioredis

Three Easy Steps to Setting Up Heroku-Redis TLS for Production

1. Check Heroku App’s Configuration

The first thing to do is double-check that TLS is supported given your Heroku app’s tier and Redis version. You can do so in Settings > Config Vars. As long as there’s a generated variable called REDIS_TLS_URL, it means your app does have TLS support.

2. Set Up Environment Variables

Now that we have the generated environment variable, we need to make sure our app is pointing to the correct URL in the config file. The `secure` boolean variable will be useful for other configuration needs.


	redis: {
    url: process.env.REDIS_TLS_URL ?? process.env.REDIS_URL,
    secure: !!process.env.REDIS_TLS_URL,
    prefix: process.env.REDIS_PREFIX || "",
  },

3. Connect to the Client

To connect this to our client, we need to specify whether to include a second parameter indicating the TLS options. Since Heroku has self-signing certificates, we don’t need to pass along any generated cert of keys at this point. Heroku will figure it all out for you!


   import Redis from "ioredis";
   const isTLS = config.get("redis.secure");
   if (isTLS) {
     _redis = new Redis(REDIS_URL, {
       tls: {
         rejectUnauthorized: false,
       },
     });
   } else {
     _redis = new Redis(REDIS_URL);
   }
   

That’s it! There are only three easy steps to getting Redis TLS running in production with Heroku-Redis.

Before we move on to setting up TLS locally, ask yourself a question. Is it most pertinent that we are not exposing test data in plain text? For most projects, the answer is no. However, if you find that your project needs that extra layer of security, read on.

Three Steps to Redis TLS Locally

1. Generating Certificates and Keys

Run this script, from Redis, in your terminal to generate the needed cert and keys.


   sh gen-test-cert.sh
   

2. Configuring Docker Redis

To get Redis TLS turned on at build, the `redis.conf` needs to be set to enable TLS. This means un-commenting the following lines from the default `redis.conf`. You can grab an official copy here.


   port 0
   tls-port 6379
   
   tls-cert-file /usr/local/etc/redis/tls/redis.crt
   tls-key-file /usr/local/etc/redis/tls/redis.key
   
   tls-ca-cert-file /usr/local/etc/redis/tls/ca.crt
   
   

Along with setting up the Redis Configuration, the locally-generated certificates and key need to be mounted onto the docker-compose image of Redis.


   redis:
     	image: redis:6.2.0
       command: redis-server /redis.conf
       environment:
         REDIS_PASSWORD: 
         REDIS_TLS_ENABLED: "yes"
         REDIS_TLS_CERT_FILE: /usr/local/etc/redis/redis.crt
         REDIS_TLS_KEY_FILE: /usr/local/etc/redis/redis.key
         REDIS_TLS_CA_FILE: /usr/local/etc/redis/ca.crt
       volumes:
         - ./redis.conf:/usr/local/etc/redis/redis.conf
         - ./tls/redis.crt:/usr/local/etc/redis/tls/redis.crt
         - ./tls/redis.key:/usr/local/etc/redis/tls/redis.key
         - ./tls/ca.crt:/usr/local/etc/redis/tls/ca.crt
       ports:
         - "6379:6379"
   

3. Connecting to the Client

Similar to configuring the client for production only, we pass on the URL itself, but now we pass on all the self-generated certificates and key.


   const REDIS_URL: string = config.get("redis.tlsUrl");
   const redis_uri = new URL(REDIS_URL);
   const redisOptions: any = REDIS_URL.includes("rediss://")
     ? {
       port: Number(redis_uri.port),
       host: redis_uri.hostname,
       password: redis_uri.password,
       db: 0,
       tls: {
         rejectUnauthorized: false,
         cert: fs.readFileSync("tls/redis.crt"),
         key: fs.readFileSync("tls/redis.key"),
         ca: fs.readFileSync("tls/ca.crt"),
       },
     }
     : REDIS_URL;
   _redis = new Redis(redisOptions);
   

That’s it! After this second set of three steps, we can secure our data transportation from the frontend to the database.