Skip to content

feat(security): доступ к Docker через docker-socket-proxy - #59

Merged
friench merged 1 commit into
mainfrom
feat/docker-socket-proxy
Jul 6, 2026
Merged

feat(security): доступ к Docker через docker-socket-proxy#59
friench merged 1 commit into
mainfrom
feat/docker-socket-proxy

Conversation

@friench

@friench friench commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Что это

mail-api больше не монтирует сырой, root-эквивалентный /var/run/docker.sock (закрывает #19). Вместо этого дефолтный compose поднимает least-privilege tecnativa/docker-socket-proxy, а mail-api ходит в Docker API по TCP (DOCKER_HOST=tcp://docker-socket-proxy:2375).

Прокси разрешает только то, что реально нужно mail-api — CONTAINERS, EXEC, POST, ALLOW_RESTARTS; сырой сокет примонтирован read-only в прокси на internal-сети. Компрометация mail-api больше не даёт управлять произвольными контейнерами/образами/томами хоста.

Изменения

  • lib/docker: resolveDockerOptions(env)DOCKER_HOST (tcp-URL) → host/port/protocol, иначе DOCKER_SOCKET_PATH (+ unit-тест).
  • Все пять dockerode-клиентов (dms, engine, ops, migrator, nginx-reloader) переведены на общий dockerOptions; index.ts резолвит соединение один раз.
  • env: DOCKER_HOST (опционально).
  • compose: сервис docker-socket-proxy + internal-сеть docker_proxy; mail-api больше не монтирует сокет, depends_on прокси.
  • Docs: _docs/deployment.md + CLAUDE.md (таблица конфига).

Обратная совместимость

Убрать DOCKER_HOST → падение обратно на прямой сокет (тогда mail-api снова нужен docker-group group_add). Флаг-контролируемо, дефолт SQLite... то есть дефолт compose — через прокси.

Проверки

typecheck · lint · format:check · vitest (528 ✓). Compose провалидирован YAML-парсером (сервисы/сети/переменные на месте, сокет у mail-api убран).

Заметка

Точный набор флагов прокси и TCP-подключение проверяются на живом стеке (docker CLI в CI-песочнице недоступен). /version (согласование API dockerode) в tecnativa-прокси разрешён по умолчанию; если понадобится — добавить INFO=1/VERSION=1. restart требует ALLOW_RESTARTS=1 (включён).

Closes #19

🤖 Generated with Claude Code

mail-api no longer mounts the raw, root-equivalent /var/run/docker.sock.
Instead the default compose runs a least-privilege
tecnativa/docker-socket-proxy and mail-api reaches the Docker API over TCP
(DOCKER_HOST=tcp://docker-socket-proxy:2375). The proxy enables only what
mail-api needs — CONTAINERS, EXEC, POST, ALLOW_RESTARTS — with the raw
socket mounted read-only on an internal network. A mail-api compromise can
no longer drive arbitrary host containers/images/volumes.

- lib/docker: resolveDockerOptions(env) — DOCKER_HOST (tcp URL) → host/port,
  else DOCKER_SOCKET_PATH (+ unit test)
- refactor all five dockerode clients (dms, engine, ops, migrator, nginx
  reloader) to take a `dockerOptions` connection; index.ts resolves it once
- env: DOCKER_HOST (optional); compose: docker-socket-proxy service +
  internal docker_proxy network, mail-api no longer mounts the socket
- docs: deployment.md + CLAUDE.md

Backward compatible: unset DOCKER_HOST to fall back to the mounted socket.

Closes #19

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@friench
friench merged commit 9b250b8 into main Jul 6, 2026
1 check passed
@friench
friench deleted the feat/docker-socket-proxy branch July 6, 2026 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docker-socket-proxy in front of the Docker socket

1 participant