diff --git a/apps/server/src/app.module.ts b/apps/server/src/app.module.ts index 4f5411eca..2de94a662 100644 --- a/apps/server/src/app.module.ts +++ b/apps/server/src/app.module.ts @@ -22,7 +22,8 @@ import { TelemetryModule } from './integrations/telemetry/telemetry.module'; import { RedisModule } from '@nestjs-labs/nestjs-ioredis'; import { RedisConfigService } from './integrations/redis/redis-config.service'; import { CacheModule } from '@nestjs/cache-manager'; -import KeyvRedis from '@keyv/redis'; +import KeyvRedis, { defaultReconnectStrategy } from '@keyv/redis'; +import { parseRedisUrl } from './common/helpers'; import { LoggerModule } from './common/logger/logger.module'; import { ClsModule } from 'nestjs-cls'; import { NoopAuditModule } from './integrations/audit/audit.module'; @@ -62,10 +63,20 @@ try { isGlobal: true, useFactory: async (environmentService: EnvironmentService) => { const redisUrl = environmentService.getRedisUrl(); + const { family, tls } = parseRedisUrl(redisUrl); return { ttl: 5 * 1000, - stores: [new KeyvRedis(redisUrl)], + stores: [ + new KeyvRedis({ + url: redisUrl, + socket: { + family, + reconnectStrategy: defaultReconnectStrategy, + ...tls, + }, + }), + ], }; }, inject: [EnvironmentService], diff --git a/apps/server/src/collaboration/collaboration.gateway.ts b/apps/server/src/collaboration/collaboration.gateway.ts index b799ce366..05536664e 100644 --- a/apps/server/src/collaboration/collaboration.gateway.ts +++ b/apps/server/src/collaboration/collaboration.gateway.ts @@ -66,6 +66,7 @@ export class CollaborationGateway { password: this.redisConfig.password, db: this.redisConfig.db, family: this.redisConfig.family, + tls: this.redisConfig.tls, retryStrategy: createRetryStrategy(), }), serverId: `collab-${os?.hostname()}-${nanoid(10)}`, diff --git a/apps/server/src/common/helpers/utils.ts b/apps/server/src/common/helpers/utils.ts index 21475c143..100d55d92 100644 --- a/apps/server/src/common/helpers/utils.ts +++ b/apps/server/src/common/helpers/utils.ts @@ -30,13 +30,14 @@ export type RedisConfig = { db: number; password?: string; family?: number; + tls?: { rejectUnauthorized?: boolean }; }; export function parseRedisUrl(redisUrl: string): RedisConfig { - // format - redis[s]://[[username][:password]@][host][:port][/db-number][?family=4|6] + // format - redis[s]://[[username][:password]@][host][:port][/db-number][?family=4|6][&rejectUnauthorized=false] const url = new URL(redisUrl); - const { hostname, port, password, pathname, searchParams } = url; - const portInt = parseInt(port, 10); + const { hostname, port, password, pathname, protocol, searchParams } = url; + const portInt = port ? parseInt(port, 10) : 6379; let db: number = 0; // extract db value if present @@ -54,7 +55,14 @@ export function parseRedisUrl(redisUrl: string): RedisConfig { family = parseInt(familyParam, 10); } - return { host: hostname, port: portInt, password, db, family }; + const tls = + protocol === 'rediss:' + ? searchParams.get('rejectUnauthorized') === 'false' + ? { rejectUnauthorized: false } + : {} + : undefined; + + return { host: hostname, port: portInt, password: password || undefined, db, family, tls }; } export function createRetryStrategy() { diff --git a/apps/server/src/integrations/health/redis.health.ts b/apps/server/src/integrations/health/redis.health.ts index 96ed53b6b..1c9f43611 100644 --- a/apps/server/src/integrations/health/redis.health.ts +++ b/apps/server/src/integrations/health/redis.health.ts @@ -5,6 +5,7 @@ import { import { Injectable, Logger } from '@nestjs/common'; import { EnvironmentService } from '../environment/environment.service'; import { Redis } from 'ioredis'; +import { parseRedisUrl } from '../../common/helpers'; @Injectable() export class RedisHealthIndicator { @@ -19,8 +20,10 @@ export class RedisHealthIndicator { const indicator = this.healthIndicatorService.check(key); try { - const redis = new Redis(this.environmentService.getRedisUrl(), { + const redisUrl = this.environmentService.getRedisUrl(); + const redis = new Redis(redisUrl, { maxRetriesPerRequest: 15, + tls: parseRedisUrl(redisUrl).tls, }); await redis.ping(); diff --git a/apps/server/src/integrations/queue/queue.module.ts b/apps/server/src/integrations/queue/queue.module.ts index eeb74cbb3..fcb317dbf 100644 --- a/apps/server/src/integrations/queue/queue.module.ts +++ b/apps/server/src/integrations/queue/queue.module.ts @@ -18,6 +18,7 @@ import { GeneralQueueProcessor } from './processors/general-queue.processor'; password: redisConfig.password, db: redisConfig.db, family: redisConfig.family, + tls: redisConfig.tls, retryStrategy: createRetryStrategy(), }, defaultJobOptions: { diff --git a/apps/server/src/integrations/redis/redis-config.service.ts b/apps/server/src/integrations/redis/redis-config.service.ts index 719f89f12..7f3e90174 100644 --- a/apps/server/src/integrations/redis/redis-config.service.ts +++ b/apps/server/src/integrations/redis/redis-config.service.ts @@ -19,6 +19,7 @@ export class RedisConfigService implements RedisOptionsFactory { password: redisConfig.password, db: redisConfig.db, family: redisConfig.family, + tls: redisConfig.tls, retryStrategy: createRetryStrategy(), }, }; diff --git a/apps/server/src/ws/adapter/ws-redis.adapter.ts b/apps/server/src/ws/adapter/ws-redis.adapter.ts index a221c84a3..ee1be320c 100644 --- a/apps/server/src/ws/adapter/ws-redis.adapter.ts +++ b/apps/server/src/ws/adapter/ws-redis.adapter.ts @@ -17,6 +17,7 @@ export class WsRedisIoAdapter extends IoAdapter { const options: RedisOptions = { family: this.redisConfig.family, + tls: this.redisConfig.tls, retryStrategy: createRetryStrategy(), };