Skip to content

Instantly share code, notes, and snippets.

@tsibley
Created October 20, 2023 22:29
Show Gist options
  • Save tsibley/659465e168b6bdcd981712f008731e60 to your computer and use it in GitHub Desktop.
Save tsibley/659465e168b6bdcd981712f008731e60 to your computer and use it in GitHub Desktop.

none

Production requirements

Requirements and considerations for deploying the nextstrain.org server in production.

Note

In this document, the nextstrain.org server is also referred to as the "Node.js server", "the app", the "app server", or just "the server".

Configuration

The Node.js server must be run with:

NODE_ENV=production

set in the environment to put the server into production mode. The default development mode is not suitable nor secured for production.

Additional configuration is done with environment variables and/or fields in a JSON config file. All configuration variables take their values from the environment. Some also take values from the config file when the variable is missing from the environment.

The default config file in production is env/production/config.json. An alternative path is given by setting:

CONFIG_FILE=<path>

in the environment.

Reverse proxy

Nginx, Apache, or another production-ready web server must sit in front of the Node.js server and reverse proxy to it.

The reverse proxy is responsible for terminating TLS and, if desired, rate-limiting requests.

The reverse proxy must add a few conventional headers to each request which allow the app to know under what client-facing URL it's being accessed (and by which actual client IP):

X-Forwarded-For: <client-addr> X-Forwarded-Host: <host> X-Forwarded-Proto: https

The configuration for adding these headers depends on the fronting web server.

The Node.js server should not be directly accessible on the network. It should only be accessible via the reverse proxy.

S3

Amazon S3 or an alternative S3-compatible object store is required for Nextstrain Groups data storage.

The GROUPS_BUCKET environment variable or config file field may be used to override the default bucket name of nextstrain-groups.

The standard AWS credential sources are used, e.g. environment variables, credential and profile files, instance metadata, etc. Environment variables are the typical choice, including:

AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_REGION

Variable names in italics may not be necessary for all configurations.

If using an alternative S3-compatible object store, point the server at its endpoint with:

AWS_ENDPOINT_URL_S3=https://…

set in the environment.

Redis

Redis 6 is required for session storage and related data. It must be configured with persistence enabled (preferrably both RDB and AOF) and a specific key eviction policy:

maxmemory-policy volatile-ttl

Connection details are provided to the Node.js server by setting:

REDIS_URL=rediss://u:<password>@<host>:<port>

in the environment.

TLS (i.e. the rediss protocol) is required, but certificate host name checking is not enabled so a self-signed certificate may be used. User authentication is recommended but not required.

Session encryption

Session data stored in Redis is encrypted. The encryption key(s) are provided as a URL query string by setting:

SESSION_ENCRYPTION_KEYS=<name>=<value>[&<name>=<value>[…]]

in the environment. The <name> of each key must be unique but is for your identification purposes only. It must be URL-encoded as necessary. The <value> of each key must be 32 bytes (256 bits) securely generated from a random source and then encoded with base64url. For example, such values can be generated using the nextstrain.org codebase like so:

node -e 'import("./src/cryptography.js").then(({randomKey}) => console.log(randomKey()))'

Or via other Unix programs:

openssl rand 32 | base64url | sed -e 's/=*$//'

The encryption keys should be treated as sensitive secrets. Multiple keys may be provided to support key rotation. All keys are used for decryption, but only the first key is used for encryption.

Session ids stored in cookies are secured from tampering via signing. A secret is required for such signing and is provided by setting:

SESSION_SECRET=<value>

in the environment or config file. The <value> should be a long random string and can be generated the same way as encryption keys above.

Multiple signing secrets may be provided to support secret rotation. Use a JSON-encoded array of strings to provide multiple secrets, e.g.:

SESSION_SECRET='["<value1>","<value2>"]'

All secrets are used for signature verification, but only the first secret is used for signing.

Groups data file

The Nextstrain Groups that exist are stored in a JSON data file. The default file in production is env/production/groups.json. An alternative path is given by setting:

GROUPS_DATA_FILE=<path>

in the environment or config file. When set in the config file, relative paths are resolved relative to the directory containing the config file.

Identity provider

An OpenID Connect 1.0 (OIDC) and OAuth 2.0 (OAuth2) identity provider (IdP) is required for user authentication and authorization role groups.

Automatic discovery of OIDC metadata from the IdP is supported, so the most common configuration variables that need setting are:

OIDC_IDP_URL
OAUTH2_CLIENT_ID
OAUTH2_CLIENT_SECRET
OAUTH2_CLI_CLIENT_ID
OIDC_USERNAME_CLAIM
OIDC_GROUPS_CLAIM

Discovered metadata can be overridden piecemeal (by setting, e.g., OAUTH2_LOGOUT_URL to override just that metadata field) or wholesale (by setting OIDC_CONFIGURATION to override the whole metadata JSON document).

See src/config.js for details on these configuration variables and other related variables.

Clients

TKTK app server client

session auth

authorization code flow

refresh must be allowed

preferrably confidential client, but may be public client

https://<host>/logged-in

TKTK cli client

bearer auth

Tokens

TKTK lifetimes

interaction with sessions

Authorization role groups

TKTK

formatting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment