skip to Main Content

I’m deploying a flask app on Heroku using a Redis premium plan. I get the following error: ‘SSL Certification Verify Failed’. Attempted fixes:

  • Downgrading to Redis 5
  • Passing ssl_cert_reqs=None to the Redis constructor in redis-py

A solution to this problem could be:

  1. Explain how to disable TLS certification on heroku redis premium plans
  2. Explain how to make TLS certification work on heroku redis premium plans

From Heroku’s docs, this may be a hint: ‘you must enable TLS in your Redis client’s configuration in order to connect to a Redis 6 database’. I don’t understand what this means.

8

Answers


  1. Chosen as BEST ANSWER

    You can disable TLS certification on Heroku by downgrading to Redis 5 and passing ssl_cert_reqs=None to the Redis constructor.

    $ heroku addons:create heroku-redis:premium-0 --version 5
    
    from redis import ConnectionPool, Redis
    import os
    connection_pool = ConnectionPool.from_url(os.environ.get('REDIS_URL'))
    app.redis = Redis(connection_pool=connection_pool, ssl_cert_reqs=None)
    

    My mistake was not doing both at the same time.

    An ideal solution would explain how to configure TLS certification for Redis 6.


  2. The docs are actually incorrect, you have to set SSL to verify_none because TLS happens automatically.

    From Heroku support:

    "Our data infrastructure uses self-signed certificates so certificates
    can be cycled regularly… you need to set the verify_mode
    configuration variable to OpenSSL::SSL::VERIFY_NONE"

    I solved this by setting the ssl_params to verify_none:

    ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }
    

    For me it was where I config redis (in a sidekiq initializer):

    # config/initializers/sidekiq.rb
    Sidekiq.configure_client do |config|
      config.redis = { url: ENV['REDIS_URL'], size: 1, network_timeout: 5, 
        ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }
    end
    
    Sidekiq.configure_server do |config|
      config.redis = { url: ENV['REDIS_URL'], size: 7, network_timeout: 5, 
        ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }
    end
    
    Login or Signup to reply.
  3. This solution works with redis 6 and python on Heroku

    import os, redis
    
    redis_url = os.getenv('REDIS_URL')
    redis_store = redis.from_url(redis_url, ssl_cert_reqs=None)
    

    In my local development environment I do not use redis with the rediss scheme, so I use a function like this to allow work in both cases:

    def get_redis_store():
        '''
        Get a connection pool to redis based on the url configured
        on env variable REDIS_URL
    
        Returns
        -------
        redis.ConnectionPool
        '''
        redis_url = os.getenv('REDIS_URL')
        if redis_url.startswith('rediss://'):
            redis_store = redis.from_url(
                redis_url, ssl_cert_reqs=None)
        else:
            redis_store = redis.from_url(redis_url)
        return redis_store
    
    Login or Signup to reply.
  4. If using the django-rq wrapper and trying to deal with this, be sure to not use the URL parameter with SSL_CERTS_REQS. There is an outstanding issue that describes this all, but basically you need to specify each connection param instead of using the URL.

    Login or Signup to reply.
  5. I solved my problem by adding ?ssl_cert_reqs=CERT_NONE to the end of REDIS_URL in my Heroku config.

    Login or Signup to reply.
  6. On Heroku (assuming Heroku Redis addon), the redis TLS route already has the ssl_cert_reqs param sorted out. A common oversight that can cause errors in cases like this on heroku is: using REDIS_URL over REDIS_TLS_URL.

    Solution:

    redis_url = os.environ.get('REDIS_TLS_URL')

    Login or Signup to reply.
  7. Solution works for nodejs16 and redis client 4.6.x

    redisClient = redis.createClient({
                url: process.env.REDIS_URL,
                socket: {
                    tls: true,
                    rejectUnauthorized: false
                })
    
    Login or Signup to reply.
  8. I ran into difficulty on this but finally got it resolved…

    A lot of documentation and posts on this topic are unclear. I’ve requested Heroku update their documentation on https://devcenter.heroku.com/articles/connecting-heroku-redis#connecting-in-python to include a specific change to the Procfile.

    It’s sort of mentioned above but refers to "Heroku config" instead of the Procfile specifically.

    In your Procfile add ?ssl_cert_reqs=none to $REDIS_URL.

    e.g.:

    web: gunicorn webapp:app
    worker: rq worker -u $REDIS_URL?ssl_cert_reqs=none queue
    

    Don’t update REDIS_URL directly as Heroku cycle this from time to time.

    I also updated the Redis setup as per the original documentation:

    url = urlparse(os.environ.get("REDIS_URL"))
    r = redis.Redis(host=url.hostname, port=url.port, password=url.password, ssl=True, ssl_cert_reqs=None)
    

    But it was the change to the Procfile that finally got Redis v6.2.11 with TLS working correctly for me.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search