Skip to content

Commit

Permalink
Allow and document how to run safely in production mode without Redis
Browse files Browse the repository at this point in the history
This is made possible by the previous commit which switched the
non-Redis fallback from an in-memory store to an on-disk SQLite store.

As a nice side-effect, we can now set REDIS_REQUIRED=true in development
mode (i.e. not the default) to more easily test the production mode code
path.

Related-to: <nextstrain/private#94>
  • Loading branch information
tsibley committed Oct 25, 2023
1 parent 0137b2b commit 4ab3cf0
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 19 deletions.
25 changes: 22 additions & 3 deletions docs/production.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ set in the environment.
Redis
=====

Redis 6 is required for session storage and related data. It must be
configured with `TLS support`_, persistence_ enabled (preferrably both RDB and
AOF), and a specific `key eviction policy`_::
Redis 6 is required by default for session storage and related data. It must
be configured with `TLS support`_, persistence_ enabled (preferrably both RDB
and AOF), and a specific `key eviction policy`_::

maxmemory-policy volatile-ttl

Expand All @@ -126,6 +126,25 @@ authentication is recommended but not required.
.. _persistence: https://redis.io/docs/management/persistence/
.. _key eviction policy: https://redis.io/docs/reference/eviction/#eviction-policies

Disabling
---------

Two other requirements must be met to safely disable the requirement for Redis:

1. The app server's filesystem must be persistent and durable (e.g. across
host restarts).

2. Only a single app server instance must be run, *or*, in a load-balancing
configuration of multiple app server instances (e.g. horizontal scaling),
all instances must use a shared filesystem that's consistent and supports
atomic rename-based writes.

If these are met, then the requirement for Redis can be disabled by setting::

REDIS_REQUIRED=false

in the environment or config file.


Session encryption
==================
Expand Down
24 changes: 24 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,30 @@ export const SESSION_SECRET = fromEnvOrConfig("SESSION_SECRET", PRODUCTION ? und
export const SESSION_MAX_AGE = fromEnvOrConfig("SESSION_MAX_AGE", 30 * 24 * 60 * 60); // 30d in seconds


/**
* Flag indicating if Redis (via REDIS_URL) is required.
*
* Defaults to true if {@link PRODUCTION} and not {@link REVIEW_APP}, otherwise
* false.
*
* @type {boolean}
*/
/* XXX TODO: Provision lowest-tier Heroku Redis addon for review apps and
* remove the !REVIEW_APP condition.
*
* Heroku has good support for this, but to enable it I think we need to switch
* how we configure review apps. Currently they're configured via the Heroku
* Dashboard¹. I think we need to switch to the app.json file² instead, as
* described in the review app documentation.³
* -trs, 12 Oct 2023
*
* ¹ <https://dashboard.heroku.com/pipelines/38f67fc7-d93c-40c6-a182-501da2f89d9d/settings>
* ² <https://devcenter.heroku.com/articles/app-json-schema>
* ³ <https://devcenter.heroku.com/articles/github-integration-review-apps>
*/
export const REDIS_REQUIRED = fromEnvOrConfig("REDIS_REQUIRED", PRODUCTION && !REVIEW_APP);


/**
* Path to a JSON file containing Groups data.
*
Expand Down
19 changes: 3 additions & 16 deletions src/redis.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import Redis from 'ioredis';

import { PRODUCTION, REVIEW_APP } from './config.js';
import { REDIS_REQUIRED } from './config.js';
import * as utils from './utils/index.js';


Expand All @@ -33,21 +33,8 @@ const REDIS = process.env.REDIS_URL
? herokuRedisClient(process.env.REDIS_URL)
: null;

/* XXX TODO: Provision lowest-tier Heroku Redis addon for review apps and
* remove the !REVIEW_APP condition.
*
* Heroku has good support for this, but to enable it I think we need to switch
* how we configure review apps. Currently they're configured via the Heroku
* Dashboard¹. I think we need to switch to the app.json file² instead, as
* described in the review app documentation.³
* -trs, 12 Oct 2023
*
* ¹ <https://dashboard.heroku.com/pipelines/38f67fc7-d93c-40c6-a182-501da2f89d9d/settings>
* ² <https://devcenter.heroku.com/articles/app-json-schema>
* ³ <https://devcenter.heroku.com/articles/github-integration-review-apps>
*/
if (PRODUCTION && !REVIEW_APP && !REDIS) {
throw new Error("REDIS_URL required in production mode");
if (!REDIS && REDIS_REQUIRED) {
throw new Error("REDIS_URL required by default in production mode (or by config). If you understand the implications of not using Redis (see the production requirements doc) and want to override this check, set REDIS_REQUIRED=false.");
}

if (REDIS) {
Expand Down

0 comments on commit 4ab3cf0

Please sign in to comment.