deploy: require redis auth (--requirepass) across all consumers

Redis without a password was the root cause of the security incident
(cron miner via unauthenticated replication RCE, see
.forcc/deploy/SESSION2-FINDINGS.md). Loopback binding alone doesn't
protect against a compromised container inside the same compose
network, so wire REDIS_PASSWORD as a required secret everywhere redis
is used: backend/worker/worker-transcriber(-gpu), redis-exporter,
livekit and egress (via rendered templates). docker compose now
refuses to start without it instead of silently running unauthenticated.
This commit is contained in:
2026-07-25 22:59:34 +03:00
parent d593add0f3
commit 5e42f6d11b
9 changed files with 77 additions and 15 deletions

View File

@@ -32,6 +32,13 @@ services:
redis:
image: redis:7
restart: unless-stopped
# requirepass обязателен: сам по себе loopback-биндинг порта (ниже) не
# защищает от взлома через скомпрометированный/зловредный контейнер в
# той же compose-сети — только внешнюю экспозицию. Инцидент безопасности
# (см. .forcc/deploy/SESSION2-FINDINGS.md) начался именно с redis без
# пароля. `${REDIS_PASSWORD:?...}` — без секрета в .env контейнер не
# стартует, а не тихо поднимается без аутентификации.
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD:?REDIS_PASSWORD не задан в .env}"]
# Публикуем ТОЛЬКО на loopback: redis используется исключительно внутри
# compose-сети (backend/worker/livekit/egress по имени `redis:6379`).
# Публикация на 0.0.0.0 без пароля = открытый redis в интернет — вектор
@@ -41,7 +48,7 @@ services:
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:?REDIS_PASSWORD не задан в .env}", "--no-auth-warning", "ping"]
interval: 5s
timeout: 5s
retries: 10
@@ -56,7 +63,7 @@ services:
- ../.env
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://vidconf:vidconf@postgres:5432/vidconf}
REDIS_URL: ${REDIS_URL:-redis://redis:6379/0}
REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD не задан в .env}@redis:6379/0
PLUGINS_CONFIG_PATH: ${PLUGINS_CONFIG_PATH:-config/plugins.yaml}
LIVEKIT_API_KEY: ${LIVEKIT_API_KEY:?LIVEKIT_API_KEY не задан в .env}
LIVEKIT_API_SECRET: ${LIVEKIT_API_SECRET:?LIVEKIT_API_SECRET не задан в .env}
@@ -119,7 +126,7 @@ services:
- ../.env
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://vidconf:vidconf@postgres:5432/vidconf}
REDIS_URL: ${REDIS_URL:-redis://redis:6379/0}
REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD не задан в .env}@redis:6379/0
PLUGINS_CONFIG_PATH: ${PLUGINS_CONFIG_PATH:-config/plugins.yaml}
PYTHONPATH: /app
volumes:
@@ -216,7 +223,7 @@ services:
- ../.env
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://vidconf:vidconf@postgres:5432/vidconf}
REDIS_URL: ${REDIS_URL:-redis://redis:6379/0}
REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD не задан в .env}@redis:6379/0
PLUGINS_CONFIG_PATH: ${PLUGINS_CONFIG_PATH:-config/plugins.yaml}
RECORDINGS_DIR: ${RECORDINGS_DIR:-/recordings}
PYTHONPATH: /app
@@ -272,7 +279,7 @@ services:
- ../.env
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://vidconf:vidconf@postgres:5432/vidconf}
REDIS_URL: ${REDIS_URL:-redis://redis:6379/0}
REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD не задан в .env}@redis:6379/0
PLUGINS_CONFIG_PATH: ${PLUGINS_CONFIG_PATH:-config/plugins.yaml}
RECORDINGS_DIR: ${RECORDINGS_DIR:-/recordings}
PYTHONPATH: /app
@@ -684,6 +691,7 @@ services:
restart: unless-stopped
environment:
REDIS_ADDR: "redis://redis:6379"
REDIS_PASSWORD: ${REDIS_PASSWORD:?REDIS_PASSWORD не задан в .env}
depends_on:
redis:
condition: service_healthy