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.