Как я полночи занимался сексом, причем пассивным, с HashiCorp Vault, чтобы не хранить пароли в докере как дебил

Или почему "PASSWORD=admin123" в docker-compose.yml — это не best practice (но мы все равно так делаем)

Короче, сидел я как-то, смотрел на свой docker-compose-develop.yml и мозолила мне глаза конструкция такого вида:


configs:
- source: EXTERNAL DOCKER CONFIG
target: /var/www/html/.env


Конфиги докера штука хорошая, спору нет, но для доставки переменных среды подходит со скрипом, ввиду того что изменять конфиг нельзя — только создавать новый. Это как научить собаку команде "сидеть", но каждый раз когда она садится, нужно придумывать новое слово для команды.

Docker Swarm Configs: История одного пиздеца

Вот как выглядит типичный день с Docker Swarm configs:


# Создаем конфиг
echo "DB_PASSWORD=sobaka123" | docker config create my-env-v1 -

# Ой, пароль поменялся
echo "DB_PASSWORD=sobaka456" | docker config create my-env-v2 -

# Теперь танцы с бубном
docker service update \
--config-rm my-env-v1 \
--config-add source=my-env-v2,target=/app/.env \
my-service

# А теперь удаляем старый конфиг
docker config rm my-env-v1
# Error: config is in use by service my-service
# СУКА!


Причем каждый новый конфиг — это новое имя. Через месяц у тебя:
- my-env-v1
- my-env-v2
- my-env-v3-final
- my-env-v3-final-FINAL
- my-env-v3-final-FINAL-блять
- my-env-prod-do-not-delete
- my-env-prod-do-not-delete-2

Собака быстрее выучит квантовую физику, чем ты запомнишь, какой конфиг актуальный.

Enter HashiCorp Vault

Vault — это такой сейф для паролей, только не такой, какой был у твоей бабушки под кроватью. Это сейф, который требует, чтобы ты сначала нашел три ключа, потом станцевал ритуальный танец, и только потом, может быть, даст тебе пароль.

Почему Vault, а не просто .env файл?

- .env файл рано или поздно закоммитит джун (или ты сам в пятницу вечером)
- Docker secrets работают как собака-поводырь для слепого программиста — вроде помогают, но ты все равно в стену въебешься
- Переменные окружения видны через docker inspect любому, у кого есть доступ к докер хосту (а это обычно пол-офиса)
- А Vault — это модно, стильно, молодёжно (и главное — можно на резюме написать)

Как я это поднимал в Swarm (спойлер: хотел повеситься)

Шаг 1: Нужен Consul (потому что одной проблемы мало)


# docker-stack-consul.yml
version: '3.8'
services:
consul:
image: consul:latest
command: agent -server -bootstrap-expect=3 -ui -client=0.0.0.0
environment:
CONSUL_BIND_INTERFACE: eth0
deploy:
replicas: 3
placement:
constraints:
- node.role == manager # Только на менеджерах, как элитная собака
networks:
- vault-net


Да, нужно 3 инстанса. Почему? Потому что "консенсус". Это как спросить трех собак, где закопана кость — две должны согласиться.

Шаг 2: Запускаем Vault в Swarm


# docker-stack-vault.yml
version: '3.8'
services:
vault:
image: vault:latest
environment:
VAULT_ADDR: 'http://0.0.0.0:8200'
VAULT_LOCAL_CONFIG: '{"backend": {"consul": {"address": "consul:8500"}}, "listener": {"tcp": {"address": "0.0.0.0:8200", "tls_disable": 1}}}'
command: server
deploy:
replicas: 1 # Больше — больше гемора с unseal
placement:
constraints:
- node.labels.vault == true # Чтобы знать, где эта собака зарыта
secrets:
- source: vault-unseal-keys
target: /tmp/unseal # Да, я знаю, что это плохо
networks:
- vault-net


Шаг 3: Инициализация (тут начинается треш)
# Деплоим стек
docker stack deploy -c docker-stack-consul.yml consul
docker stack deploy -c docker-stack-vault.yml vault

# Инициализируем (получаем 5 ключей, как Танос камни бесконечности)
docker exec $(docker ps -q -f name=vault) vault operator init

# Unseal Key 1: blablabla...
# Unseal Key 2: blablabla...
# Root Token: s.blablabla...
# ЗАПИШИ ЭТО БЛЯТЬ КУДА-НИБУДЬ!
# Теперь unseal (каждый раз после рестарта)
docker exec $(docker ps -q -f name=vault) vault operator unseal <key1>
docker exec $(docker ps -q -f name=vault) vault operator unseal <key2>
docker exec $(docker ps -q -f name=vault) vault operator unseal <key3>


Это как научить собаку открывать дверь, но только если она знает три разных пароля.

## Интеграция с Docker Swarm сервисами

Вариант "Я оптимист" (Init Container Pattern)

```yaml
version: '3.8'
services:
app:
image: myapp:latest
environment:
VAULT_ADDR: 'http://vault:8200'
VAULT_TOKEN_FILE: /run/secrets/vault-token
secrets:
- vault-token
deploy:
replicas: 3
entrypoint: |
sh -c
# Достаем секреты из Vault как собака тапки
export DB_PASS=$$(vault kv get -field=password secret/myapp/db)
export API_KEY=$$(vault kv get -field=api_key secret/myapp/api)
# Запускаем приложение
exec /app/start.sh

```

### Вариант "Я реалист" (Sidecar Pattern)


version: '3.8'
services:
vault-agent:
image: vault:latest
command: |
sh -c '
cat > /tmp/agent.hcl <<EOF
vault {
address = "http://vault:8200"
}
auto_auth {
method {
type = "token"
config {
token = "$$(cat /run/secrets/vault-token)"
}
}
}
template {
contents = "{{ with secret \"secret/data/myapp/db\" }}DB_PASS={{ .Data.data.password }}{{ end }}"
destination = "/shared/.env"
}
EOF
vault agent -config=/tmp/agent.hcl
'
volumes:
- env-data:/shared
secrets:
- vault-token

app:
image: myapp:latest
volumes:
- env-data:/config
command: |
sh -c '
# Ждем пока Vault Agent принесет палку... то есть секреты
while [ ! -f /config/.env ]; do sleep 1; done
source /config/.env
exec /app/start.sh


## Сравнение с Kubernetes ConfigMaps (для понтов)

В Kubernetes это выглядит примерно так же уебищно:


# ConfigMap (без секретов, потому что не дебилы же)
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_host: "postgres.default.svc"

---
# Secret (base64, лол)
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
data:
password: c29iYWthMTIzCg== # Это "sobaka123" в base64, хакеры в шоке!


Разница в том, что в Kubernetes хотя бы есть встроенный механизм ротации. В Swarm ты будешь создавать my-secret-v947 до конца своих дней.

## CI/CD Pipeline с Vault (GitLab, потому что мазохизм)



deploy_swarm:
stage: deploy
script:
# Логинимся в Vault как хорошая собака
- export VAULT_TOKEN=$(vault write -field=token auth/jwt/login role=gitlab jwt=$CI_JOB_JWT)

# Создаем Docker secret с токеном
- echo $VAULT_TOKEN | docker secret create vault-token-${CI_COMMIT_SHORT_SHA} -

# Обновляем сервис (и молимся)
- |
docker service update \
--secret-rm vault-token-old \
--secret-add source=vault-token-${CI_COMMIT_SHORT_SHA},target=vault-token \
--force \
my-service

# Пытаемся удалить старый secret (спойлер: не получится)
- docker secret rm vault-token-old || true


## Auto-unseal (или как я научился не беспокоиться и полюбил AWS)


# vault-config.hcl
seal "awskms" {
region = "us-east-1"
kms_key_id = "blablabla"
}


Теперь вместо того, чтобы хранить 5 ключей, ты хранишь AWS креды. Прогресс? Ну, типа того. Это как научить собаку приносить тапки, но только если у нее есть ключ от квартиры. Что в итоге?

Плюсы:
- Секреты в безопасности (если Vault не упал)
- Аудит (видно, кто и когда обосрался)
- Ротация паролей (автоматическая головная боль)
- Можешь рассказывать на митапах

Минусы:
- Ещё один сервис, который может упасть
- Unseal после каждого рестарта (как собака, которая забывает команды после сна)
- Docker Swarm configs все равно говно
- Полночи на настройку, и это в лучшем случае

## Мораль
Docker Swarm configs — это как дрессировка кота. Вроде что-то получается, но ты не уверен, что именно.

Vault — это как завести служебную собаку. Да, она охраняет дом, но ты должен её кормить, выгуливать, и помнить команды, иначе она тебя же и покусает.

В итоге я потратил полночи, чтобы настроить систему, которая делает то же самое, что и .env файл, но с аудитом и возможностью сказать на собеседовании: "У нас централизованное управление секретами через HashiCorp Vault с динамической ротацией и интеграцией в CI/CD".

P.S. Если кто знает, как заставить Docker Swarm нормально работать с обновлением конфигов без создания новых версий — скиньте контакт вашего дилера, у него явно хороший стафф.

P.P.S. Собаки все еще умнее большинства DevOps инженеров. Они хотя бы не придумывают себе проблемы.

---

*Автор успешно использует Vault в проде, периодически вспоминает где хранятся unseal ключи, и до сих пор создает docker configs с постфиксом -final-FINAL-2* Телеграм-посты vs Telegraph: Когда размер имеет значение

Или почему я думаю переехать на Telegraph (но боюсь, что никто читать не будет)

Сижу я тут, смотрю на свой пост про Vault — 300 строк циничного текста про то, как я ебался с HashiCorp'ом. И думаю: а кто это вообще дочитает до конца в телеграме?

Проблема формата Telegram

Что имеем:
- Максимум 4096 символов на пост (это примерно 50-60 строк нормального текста)
- Форматирование кода — боль (моноширинный шрифт и всё)
- Картинки только сверху или снизу
- Нет нормальной навигации по тексту
- Скролл на 300 строк в мобилке — это пытка

Как люди читают телеграм:
1. Увидел пост
2. Начал читать
3. "Блять, как много букв"
4. Проскроллил до конца
5. Поставил реакцию 🔥
6. Не прочитал


Telegraph: спасение или хуйня?

Плюсы Telegraph:
- Неограниченный объем (пиши хоть "Войну и мир")
- Нормальное форматирование кода с подсветкой
- Картинки где угодно
- Оглавление и якоря
- Читается как нормальная статья
- Можно вернуться и дочитать

Минусы Telegraph:
- Лишний клик (люди ленивые как собаки)
- Выход из телеграма (потеря контекста)
- Нет реакций под статьей
- Статистика просмотров — хуй пойми как считается
- SEO — ноль (гугл Telegraph не очень любит)

@durov — пишет простыни прямо в телеге (но он Дуров, ему можно)

@vltv — длинные тексты на Telegraph, в телеге превью

Технические каналы — 50/50, зависит от аудитории

Мемные каналы — какой нахуй Telegraph, максимум 3 строки текста

### Мой вывод

Зависит от контента:

Оставляю в телеграме:
- Быстрые решения проблем (< 2000 символов)
- Сниппеты кода с коротким описанием
- Мемы и шутки про собак
- Новости и горячие темы

Выношу в Telegraph:
- Туториалы и гайды (> 3000 символов)
- Подробные разборы технологий
- Посты с множеством примеров кода
- Case studies и post-mortems

### Эксперимент для подписчиков

Давайте проверим:

1. Этот пост ~100 строк размышлений
2. Если дочитали до сюда — поставьте 👍
3. Если хотите Telegraph для длинных постов — 📝
4. Если хотите всё в телеге — 💬
5. Если вам похуй — 🤷‍♂️

### P.S. А может дело не в формате?

Может проблема не в том, где размещать контент, а в том, что:
- Люди разучились читать больше твита
- Внимание — новая валюта
- TikTok приучил к 15-секундному контенту
- Даже собаки концентрируются дольше современных людей

Но это уже тема для отдельного экзистенциального поста.

---

*Автор дочитал до конца свой же пост и охуел от его длины. Ирония? Возможно.*

*P.P.S. Если вы это читаете — вы либо очень терпеливый, либо просто проскроллили вниз. В любом случае — респект.*