feat(server): support IPv6 Redis instances

This enables automatic family affinity by using `0`, which overwrites
ioredis' default set to `4`. With this change, Immich will be able to
connect to Redis exposed only via IPv6.

Users will still be able to overwrite the default with `REDIS_IP_FAMILY`
or by adding `?family=4` to `REDIS_URL`.
This commit is contained in:
Szymon Łągiewka 2025-10-11 20:17:38 +02:00
parent 8fe54a4de1
commit 718878cad0
No known key found for this signature in database
4 changed files with 20 additions and 11 deletions

View file

@ -101,15 +101,16 @@ When `DB_URL` is defined, the `DB_HOSTNAME`, `DB_PORT`, `DB_USERNAME`, `DB_PASSW
## Redis ## Redis
| Variable | Description | Default | Containers | | Variable | Description | Default | Containers |
| :--------------- | :------------- | :-----: | :--------- | | :---------------- | :-------------- | :-----: | :--------- |
| `REDIS_URL` | Redis URL | | server | | `REDIS_URL` | Redis URL | | server |
| `REDIS_SOCKET` | Redis socket | | server | | `REDIS_SOCKET` | Redis socket | | server |
| `REDIS_HOSTNAME` | Redis host | `redis` | server | | `REDIS_HOSTNAME` | Redis host | `redis` | server |
| `REDIS_PORT` | Redis port | `6379` | server | | `REDIS_PORT` | Redis port | `6379` | server |
| `REDIS_USERNAME` | Redis username | | server | | `REDIS_USERNAME` | Redis username | | server |
| `REDIS_PASSWORD` | Redis password | | server | | `REDIS_PASSWORD` | Redis password | | server |
| `REDIS_DBINDEX` | Redis DB index | `0` | server | | `REDIS_DBINDEX` | Redis DB index | `0` | server |
| `REDIS_IP_FAMILY` | Redis IP family | `0` | server |
:::info :::info
All `REDIS_` variables must be provided to all Immich workers, including `api` and `microservices`. All `REDIS_` variables must be provided to all Immich workers, including `api` and `microservices`.
@ -117,7 +118,7 @@ All `REDIS_` variables must be provided to all Immich workers, including `api` a
`REDIS_URL` must start with `ioredis://` and then include a `base64` encoded JSON string for the configuration. `REDIS_URL` must start with `ioredis://` and then include a `base64` encoded JSON string for the configuration.
More information can be found in the upstream [ioredis] documentation. More information can be found in the upstream [ioredis] documentation.
When `REDIS_URL` or `REDIS_SOCKET` are defined, the `REDIS_HOSTNAME`, `REDIS_PORT`, `REDIS_USERNAME`, `REDIS_PASSWORD`, and `REDIS_DBINDEX` variables are ignored. When `REDIS_URL` or `REDIS_SOCKET` are defined, the `REDIS_HOSTNAME`, `REDIS_PORT`, `REDIS_USERNAME`, `REDIS_PASSWORD`, `REDIS_IP_FAMILY`, and `REDIS_DBINDEX` variables are ignored.
::: :::
Redis (Sentinel) URL example JSON before encoding: Redis (Sentinel) URL example JSON before encoding:

View file

@ -1,5 +1,5 @@
import { Transform, Type } from 'class-transformer'; import { Transform, Type } from 'class-transformer';
import { IsEnum, IsInt, IsString, Matches } from 'class-validator'; import { IsEnum, IsIn, IsInt, IsString, Matches } from 'class-validator';
import { DatabaseSslMode, ImmichEnvironment, LogLevel } from 'src/enum'; import { DatabaseSslMode, ImmichEnvironment, LogLevel } from 'src/enum';
import { IsIPRange, Optional, ValidateBoolean } from 'src/validation'; import { IsIPRange, Optional, ValidateBoolean } from 'src/validation';
@ -195,4 +195,9 @@ export class EnvDto {
@IsString() @IsString()
@Optional() @Optional()
REDIS_URL?: string; REDIS_URL?: string;
@IsIn([0, 4, 6])
@Optional()
@Type(() => Number)
REDIS_IP_FAMILY?: 0 | 4 | 6;
} }

View file

@ -35,6 +35,7 @@ const resetEnv = () => {
'REDIS_PASSWORD', 'REDIS_PASSWORD',
'REDIS_SOCKET', 'REDIS_SOCKET',
'REDIS_URL', 'REDIS_URL',
'REDIS_IP_FAMILY',
'NO_COLOR', 'NO_COLOR',
]) { ]) {
@ -138,6 +139,7 @@ describe('getEnv', () => {
username: undefined, username: undefined,
password: undefined, password: undefined,
path: undefined, path: undefined,
family: 0,
}); });
}); });

View file

@ -163,6 +163,7 @@ const getEnv = (): EnvData => {
username: dto.REDIS_USERNAME || undefined, username: dto.REDIS_USERNAME || undefined,
password: dto.REDIS_PASSWORD || undefined, password: dto.REDIS_PASSWORD || undefined,
path: dto.REDIS_SOCKET || undefined, path: dto.REDIS_SOCKET || undefined,
family: dto.REDIS_IP_FAMILY || 0,
}; };
const redisUrl = dto.REDIS_URL; const redisUrl = dto.REDIS_URL;