NPV-AM

← Все руководства

SOPS + age: шифрование секретов

25 июля 2026 · 12 мин чтения · Продвинутый

SOPS (Secrets OPerationS) от Mozilla — инструмент для шифрования секретов в YAML, JSON и ENV файлах. В паре с age (современной заменой GPG) он обеспечивает простое и безопасное хранение секретов в репозитории.

Шаг 1: Установка age и SOPS

# age (Linux)
wget https://github.com/FiloSottile/age/releases/download/v1.1.1/age-v1.1.1-linux-amd64.tar.gz
tar xzf age-v1.1.1-linux-amd64.tar.gz
sudo cp age/age age/age-keygen /usr/local/bin/

# SOPS (Linux)
wget https://github.com/getsops/sops/releases/download/v3.9.2/sops-v3.9.2.linux.amd64
chmod +x sops-v3.9.2.linux.amd64
sudo mv sops-v3.9.2.linux.amd64 /usr/local/bin/sops

# Проверка
age --version
sops --version

Шаг 2: Генерация ключей age

Создайте ключевую пару для каждого участника и CI/CD:

# Ключ для разработчика
age-keygen -o ~/.config/sops/age/keys.txt
# Вывод:
# Public key: age1abc123...dev_key

# Ключ для CI/CD (GitLab/GitHub Actions)
age-keygen -o ci-keys.txt
# Вывод:
# Public key: age1xyz789...ci_key

# Ключ для продакшн-сервера
age-keygen -o prod-keys.txt
# Вывод:
# Public key: age1def456...prod_key

Сохраните приватные ключи в安全ном месте (password manager, vault). Публичные ключи можно хранить в репозитории.

Шаг 3: Конфигурация .sops.yaml

Создайте файл в корне репозитория:

# .sops.yaml
creation_rules:
  # Файлы для dev-окружения
  - path_regex: secrets/dev\.ya?ml$
    key_groups:
      - age:
          - age1abc123...dev_key
          - age1xyz789...ci_key

  # Файлы для staging
  - path_regex: secrets/staging\.ya?ml$
    key_groups:
      - age:
          - age1abc123...dev_key
          - age1xyz789...ci_key
          - age1def456...prod_key

  # Файлы для prod
  - path_regex: secrets/prod\.ya?ml$
    key_groups:
      - age:
          - age1xyz789...ci_key
          - age1def456...prod_key

Шаг 4: Шифрование файлов

Создайте файл с секретами:

# secrets/dev.yml
database:
  host: db.internal.dev
  port: 5432
  user: app_dev
  password: dev_password_123
  name: myapp_dev

redis:
  host: redis.internal.dev
  port: 6379

api_key: sk-dev-abc123def456

Зашифруйте:

sops --encrypt --in-place secrets/dev.yml

# Или создайте зашифрованный файл из открытого
sops --encrypt secrets/dev.yml > secrets/dev.enc.yml

Результат — файл, где значения зашифрованы, а ключи и структура YAML остались открытыми:

database:
    host: db.internal.dev
    port: 5432
    user: app_dev
    password: ENC[AES256_GCM,data:xxxxxx...]
    name: myapp_dev
sops:
    age:
        - recipient: age1abc123...dev_key
          enc: |
            -----BEGIN AGE ENCRYPTED FILE-----
            ...
            -----END AGE ENCRYPTED FILE-----
    lastmodified: "2026-07-25T10:00:00Z"
    version: 3.9.2

Шаг 5: Расшифровка

# Расшифровка в stdout
sops --decrypt secrets/dev.yml

# Расшифровка и редактирование
sops secrets/dev.yml

# Расшифровка отдельного значения
sops --decrypt --extract '["database"]["password"]' secrets/dev.yml

# Конвертация в .env формат
sops --decrypt --output-type dotenv secrets/dev.env > .env

Шаг 6: Использование в Docker Compose

# docker-compose.yml
services:
  app:
    image: myapp:latest
    env_file:
      - .env
    environment:
      - DB_HOST=${DB_HOST}
      - DB_PASSWORD=${DB_PASSWORD}
# Скрипт запуска
#!/bin/bash
set -euo pipefail

sops --decrypt secrets/prod.env > .env
docker compose up -d
rm -f .env

Шаг 7: Ansible lookup plugin

Для использования SOPS-секретов в Ansible:

# ansible.cfg
[defaults]
lookup_plugins = lookup_plugins
# roles/app/templates/env.j2
DATABASE_URL=postgresql://{{ sops.secrets.database.user }}:{{ sops.secrets.database.password }}@{{ sops.secrets.database.host }}:{{ sops.secrets.database.port }}/{{ sops.secrets.database.name }}
API_KEY={{ sops.secrets.api_key }}
REDIS_URL=redis://{{ sops.secrets.redis.host }}:{{ sops.secrets.redis.port }}
# playbooks/deploy.yml
- name: Deploy application
  hosts: app_servers
  vars:
    sops_secrets: "{{ lookup('community.sops.sops', 'secrets/prod.yml') | from_yaml }}"
  tasks:
    - name: Deploy env file
      template:
        src: env.j2
        dest: /opt/app/.env
        owner: app
        group: app
        mode: '0600'

Шаг 8: CI/CD интеграция

В GitLab CI добавьте приватный ключ CI-Runner:

# GitLab CI
deploy:
  stage: deploy
  before_script:
    - mkdir -p ~/.config/sops/age
    - echo "$SOPS_AGE_KEY" > ~/.config/sops/age/keys.txt
  script:
    - sops --decrypt secrets/prod.yml > secrets.yml
    - ansible-playbook deploy.yml -e @secrets.yml
    - rm -f secrets.yml
  after_script:
    - rm -f ~/.config/sops/age/keys.txt

Переменную SOPS_AGE_KEY сохраните в GitLab CI/CD Variables (Masked + Protected).

Всегда добавляйте *.enc.yml или зашифрованные файлы в git. Храните приватные ключи только в vault/password manager. Никогда не коммитьте приватные ключи.

Шаг 9: Ротация ключей

# Обновление ключей в .sops.yaml
# Добавьте новый ключ и удалите старый

# Перешифрование всех файлов
find secrets/ -name '*.yml' -exec sops --encrypt --in-place {} \;

# Или через Makefile
encrypt-all:
	sops --encrypt --in-place secrets/dev.yml
	sops --encrypt --in-place secrets/staging.yml
	sops --encrypt --in-place secrets/prod.yml