age: проста сучасна утиліта для шифрування файлів і секретів

notes · 2026-05-27

Короткий висновок

age — це сучасна утиліта для шифрування файлів, яку зручно використовувати там, де GPG занадто важкий, а повноцінний secret manager на кшталт Vault або 1Password CLI — надмірний.

Найсильніші сторони age:

  • маленькі зрозумілі ключі;
  • простий CLI без десятків режимів;
  • добре працює в shell pipelines;
  • легко шифрувати для кількох отримувачів;
  • підтримує SSH public keys;
  • добре інтегрується з sops, nix-darwin, home-manager, backups і GitOps;
  • менше operational complexity, ніж у GPG.

Правильна роль age в моєму сетапі:

  • шифрувати backup-и OpenClaw state;
  • шифрувати локальні secrets для Nix/SOPS;
  • безпечніше переносити файли між Macʼами;
  • давати простий recovery path для нового компʼютера;
  • не заміняти password manager для людських паролів і не заміняти Vault/KMS для production secrets.

age — це не “один інструмент для всіх секретів”. Це дуже хороший building block для file encryption.


Що таке age

age — це simple, modern and secure file encryption tool. Його автори навмисно зробили маленький набір функцій: шифрування файлів для recipient keys, дешифрування identity key, passphrase mode, recipients file, UNIX-style stdin/stdout.

Офіційна ідея дуже практична: замість складної PGP-моделі з keyrings, trust levels, subkeys і довгими командами — дати маленькі explicit keys і зрозумілий формат.

Типовий flow:

age-keygen -o key.txt
age -r age1... secret.txt > secret.txt.age
age -d -i key.txt secret.txt.age > secret.txt

Публічний ключ виглядає так:

age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p

Приватний ключ виглядає так:

AGE-SECRET-KEY-1...

Public recipient можна безпечно зберігати в Git. Private identity — ні.


Коли age зручний

1. Encrypted backup перед міграцією Mac

Наприклад, backup OpenClaw:

cd ~
tar --exclude='.openclaw/cache' \
    --exclude='.openclaw/logs' \
    --exclude='.openclaw/tmp' \
    -czf openclaw-state.tar.gz \
    .openclaw

age -r age1yourpublicrecipient... \
  -o openclaw-state.tar.gz.age \
  openclaw-state.tar.gz

Дешифрування на новому Mac:

age -d -i ~/.config/sops/age/keys.txt \
  -o openclaw-state.tar.gz \
  openclaw-state.tar.gz.age

Це дуже сильний сценарій: backup можна покласти на зовнішній диск, NAS, cloud drive або тимчасово в Git LFS/artifact storage, не боячись plaintext exposure.

2. SOPS secrets для Nix

У macOS/Nix підході age часто використовується не напряму, а через sops:

sops secrets/secrets.yaml

Під капотом sops може шифрувати values через age recipients. Це зручно для:

  • nix-darwin secrets;
  • home-manager secrets;
  • .env шаблонів;
  • токенів CLI tooling;
  • credentials, які треба version-control-ити encrypted.

У repo можна комітити encrypted secrets.yaml, але не можна комітити age private key.

3. File transfer між машинами

Якщо треба передати sensitive файл на інший Mac:

age -r age1recipientofnewmac... -o file.txt.age file.txt
scp file.txt.age newmac:~/Downloads/

На новому Mac:

age -d -i ~/.config/sops/age/keys.txt file.txt.age > file.txt

Це краще, ніж пересилати plaintext через месенджери або cloud sync.

4. Team/shared recipients

Можна шифрувати один файл для кількох людей або пристроїв:

age \
  -r age1alice... \
  -r age1bob... \
  -r age1newmac... \
  -o backup.tar.gz.age \
  backup.tar.gz

Кожен recipient зможе розшифрувати файл своїм приватним ключем.

Для постійних наборів краще зробити recipients file:

# recipients.txt
# Aleksandr main Mac
age1...

# OpenClaw Mac
age1...

# Emergency offline key
age1...

Шифрування:

age -R recipients.txt -o backup.tar.gz.age backup.tar.gz

Як встановити age на macOS

Через Nix

У Nix-first підході краще додати age в mac-config, щоб він був частиною system baseline.

Тимчасово:

nix shell nixpkgs#age

Або permanent через environment.systemPackages / home-manager packages.

Через Homebrew

brew install age

Для мого сетапу краще: Nix для reproducibility, Homebrew як fallback.

Перевірка:

age --version
age-keygen --version

Генерація ключа

Простий age key

mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt
chmod 600 ~/.config/sops/age/keys.txt

Показати public recipient:

age-keygen -y ~/.config/sops/age/keys.txt

Private file:

~/.config/sops/age/keys.txt

Public recipient можна додати в:

  • .sops.yaml;
  • recipients.txt;
  • README для команди;
  • Nix repo;
  • backup scripts.

Private identity тримати тільки локально або в secure backup.

Генерація age key з SSH key

Іноді зручно отримати age identity з SSH ключа через ssh-to-age:

ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt
chmod 600 ~/.config/sops/age/keys.txt

Public recipient:

ssh-to-age < ~/.ssh/id_ed25519.pub

Плюс: менше ключів для керування.

Мінус: SSH key і encryption identity стають повʼязаними. Якщо SSH key треба rotate-ити через GitHub compromise або зміну машини, це зачепить і encryption story.

Моя рекомендація:

  • для personal migration backup можна мати окремий age-keygen key;
  • для SOPS/Nix — окремий age key у ~/.config/sops/age/keys.txt;
  • SSH-derived age key використовувати тільки якщо явно хочеш спростити key management.

Post-quantum keys

Новіші версії age підтримують hybrid post-quantum keys:

age-keygen -pq -o pq-key.txt
age-keygen -y pq-key.txt > pq-recipient.txt

Це цікаво для long-term archives, але recipient дуже довгий. Для щоденного operational use звичайні age keys поки простіші.

Практична позиція: для backup-ів, які мають жити багато років і містять sensitive дані, можна завести окремий PQ recipient. Для поточних Nix/SOPS secrets — не ускладнювати без потреби.


Де зберігати ключі

Public recipient

Public recipient — не секрет.

Його можна зберігати в Git:

.sops.yaml
recipients.txt
docs/security/age-recipients.md

Приклад .sops.yaml:

creation_rules:
  - path_regex: secrets/.*\.ya?ml$
    age: age1examplepublicrecipient...

Private identity

Private key — секрет.

Рекомендоване місце на macOS:

~/.config/sops/age/keys.txt

Permissions:

chmod 700 ~/.config/sops
chmod 700 ~/.config/sops/age
chmod 600 ~/.config/sops/age/keys.txt

Не класти private key у:

  • Git repo;
  • Obsidian plaintext note;
  • Hugo content;
  • Telegram/Slack;
  • Desktop/Downloads без encryption;
  • shared iCloud folder без додаткового шифрування;
  • backup archive без encryption.

Secure backup private key

Private key треба мати в recovery. Інакше encrypted backup стане сміттям.

Нормальні варіанти:

  1. 1Password secure note / file attachment — практично найзручніше для personal use.
  2. Encrypted USB drive — добрий offline backup.
  3. Paper backup для emergency key — можна надрукувати private key або QR, але це треба фізично захищати.
  4. Separate emergency age key — шифрувати важливі backup-и на daily key + offline emergency key.
  5. YubiKey через age-plugin-yubikey — сильніше, але складніше operationally.

Моя practical recommendation:

  • primary age identity: ~/.config/sops/age/keys.txt;
  • backup copy: 1Password attachment;
  • emergency recipient: окремий offline key на encrypted USB або папері;
  • recipients file шифрує важливі backup-и на primary + emergency.

Базові команди

Encrypt file

age -r age1recipient... -o secret.txt.age secret.txt

Decrypt file

age -d -i ~/.config/sops/age/keys.txt -o secret.txt secret.txt.age

Encrypt directory через tar

age шифрує файл/stream, не директорію напряму. Для директорій:

tar -czf - ~/Documents/private-folder \
  | age -r age1recipient... \
  > private-folder.tar.gz.age

Restore:

age -d -i ~/.config/sops/age/keys.txt private-folder.tar.gz.age \
  | tar -xzf - -C ~/Restore

Encrypt для кількох recipients

age -r age1mac... -r age1emergency... -o backup.age backup.tar.gz

Recipients file

age -R recipients.txt -o backup.age backup.tar.gz

Passphrase mode

age -p -o secret.txt.age secret.txt

Це зручно для разового файлу, але гірше для automation. Для backups/Nix/SOPS краще key-based encryption.


Good patterns

Pattern 1: backup OpenClaw state

#!/usr/bin/env bash
set -euo pipefail

stamp=$(date +%Y%m%d-%H%M%S)
out="$HOME/Backups/openclaw-state-$stamp.tar.gz.age"
recipient_file="$HOME/.config/age/recipients-openclaw.txt"

tar \
  --exclude='.openclaw/cache' \
  --exclude='.openclaw/logs' \
  --exclude='.openclaw/tmp' \
  -czf - \
  -C "$HOME" .openclaw \
  | age -R "$recipient_file" -o "$out"

echo "Encrypted backup: $out"

Important: перевіряти restore, не тільки creation.

age -d -i ~/.config/sops/age/keys.txt "$out" | tar -tzf - | head

Pattern 2: encrypted migration bundle

mkdir -p ~/migration-bundle
cp ~/.openclaw/openclaw.json ~/migration-bundle/
cp ~/.openclaw/cron/jobs.json ~/migration-bundle/openclaw-cron-jobs.json
cp ~/.openclaw/workspace/USER.md ~/migration-bundle/
cp ~/.openclaw/workspace/MEMORY.md ~/migration-bundle/

tar -czf - ~/migration-bundle \
  | age -R ~/.config/age/recipients-migration.txt \
  > migration-bundle.tar.gz.age

Pattern 3: SOPS + age для Nix secrets

.sops.yaml:

keys:
  - &openclaw age1example...

creation_rules:
  - path_regex: secrets/.*\.yaml$
    key_groups:
      - age:
          - *openclaw

Create/edit:

sops secrets/secrets.yaml

Decrypt only for local debug:

sops -d secrets/secrets.yaml

Не робити sops -d > secrets.plain.yaml без дуже чіткої потреби.


Bad patterns

Bad: private key у Git

git add ~/.config/sops/age/keys.txt

Ні. Це повний компроміс усіх файлів, зашифрованих на цей key.

Bad: один backup key без recovery

Якщо є тільки один private key на одному Mac, а Mac помер — backup не існує.

Мінімум: backup private key у 1Password або encrypted offline storage.

Bad: plaintext temp files

age -d secret.age > secret.txt
# потім забути secret.txt в Downloads

Краще працювати через pipe, або видаляти recoverably/securely згідно з threat model.

Bad: passphrase mode для automation

Passphrase mode ок для людини. Але для cron/Nix/CI він породжує проблеми:

  • де зберігати passphrase;
  • як вводити без interaction;
  • як rotate-ити;
  • як audit-ити access.

Для automation — key recipients або KMS/Vault.

Bad: шифрувати все одним ключем назавжди

Краще мати різні recipients для різних trust zones:

  • personal backup;
  • OpenClaw migration;
  • Nix/SOPS secrets;
  • team/project secrets;
  • emergency recovery.

Як age вписується в OpenClaw/macOS/Nix підхід

Для OpenClaw host на macOS з Nix я б тримав таку структуру:

~/.config/sops/age/keys.txt          # private identity, 600
~/.config/age/recipients-openclaw.txt # public recipients for backups
~/Projects/mac-config/.sops.yaml      # public recipients only
~/Projects/mac-config/secrets/*.yaml  # encrypted SOPS files
~/Projects/knowledge-base             # git-crypt encrypted vault
~/.openclaw/.env                      # local plaintext runtime secrets, chmod 600

Ролі:

  • age — encrypt/decrypt files and backup archives.
  • sops — structured secrets in Git, encrypted with age.
  • git-crypt — repository-level encryption for knowledge-base.
  • 1Password — human password manager and recovery storage.
  • Vault/KMS — production/cloud secret management.

Це clean separation. Не треба змушувати один інструмент робити все.


Аналоги і порівняння

Інструмент Найкраще для Плюси Мінуси Коли обрати
age File encryption, backups, simple recipient-based encryption Простий CLI, маленькі ключі, легко автоматизувати, підтримує SSH keys, добре з UNIX pipes Не password manager, не secret store, немає policy/audit/rotation workflow з коробки Personal backups, migration bundles, SOPS backend
GPG / PGP Email/file encryption, legacy ecosystems, signing Дуже поширений, підтримує signing, smartcards, web-of-trust Складний UX, keyring complexity, багато footguns Якщо потрібна сумісність з PGP або signing workflow
SOPS Encrypted YAML/JSON/ENV secrets у Git Шифрує окремі values, Git-friendly diffs, підтримує age/KMS/PGP Це не standalone crypto primitive; потрібен backend key/KMS Nix secrets, Kubernetes secrets manifests, config repos
git-crypt Прозоре шифрування файлів у Git repo Зручно для vault/repo, файли автоматично decrypt після unlock Менш granular, складніше audit, залежить від repo workflow Knowledge-base або repo з encrypted files
1Password Людські паролі, API keys, recovery material Сильний UX, device sync, sharing, recovery, browser/app integration Не зручно для GitOps/pipelines як primary encryption Зберігати private age key backup, tokens, human secrets
HashiCorp Vault Dynamic secrets, production secret management Policy, audit, leases, rotation, integrations Operational overhead, потребує server/control plane Production infra, AWS/database dynamic credentials
Cloud KMS Envelope encryption, cloud-native key management IAM, audit, centralized control, no local private key Cloud lock-in, online dependency, складніше для offline migration Production/cloud secrets, CI/CD encryption
OpenSSL CLI Ad-hoc crypto operations Всюди доступний, дуже flexible Забагато небезпечних опцій, поганий UX для secrets workflows Низькорівневі задачі, сумісність, не daily secret management
VeraCrypt / encrypted disk image Encrypted volumes Добре для bulk local storage Не Git-friendly, не зручно для automation Зовнішній диск, offline archive, великий локальний vault
macOS FileVault Full-disk encryption Захищає Mac at rest, transparent Не захищає файл після копіювання з диску Має бути увімкнено завжди, але це не заміна age

age vs GPG

Якщо коротко: age краще для modern operational file encryption; GPG краще для legacy compatibility і signing.

GPG сильний, але UX складний:

  • keyrings;
  • trust database;
  • subkeys;
  • agents;
  • recipient discovery;
  • багато форматів і режимів.

age навпаки:

  • public recipient прямо в команді;
  • private identity прямо у файлі;
  • мінімум options;
  • простіше пояснити і відновити через рік.

Для OpenClaw backup/migration я б не використовував GPG як default. age простіший і менш крихкий.

age vs SOPS

Це не конкуренти.

age — encryption tool/format.

sops — secret file editor/manager, який може використовувати age як backend.

Для одного backup archive:

age -r age1... backup.tar.gz > backup.tar.gz.age

Для structured secrets у Git:

sops secrets.yaml

Правильна пара: SOPS + age.

age vs git-crypt

git-crypt зручний, коли весь repo або частина repo має encrypted files, які прозоро відкриваються після git-crypt unlock.

age краще, коли треба зашифрувати конкретний файл/архів незалежно від Git repo.

Для ~/Projects/knowledge-base логічний git-crypt, бо це vault repo.

Для ~/.openclaw backup логічний age, бо це archive/migration artifact.

age vs 1Password

1Password краще для людського UX:

  • passwords;
  • API keys;
  • secure notes;
  • device sync;
  • emergency access.

age краще для CLI automation:

  • encrypt archive;
  • decrypt in shell;
  • pipe tar output;
  • use with SOPS.

Практично: private age key backup можна зберігати в 1Password, але не треба намагатись замінити age 1Password CLI для backup archives.

age vs Vault/KMS

Vault/KMS потрібні, коли є production requirements:

  • audit logs;
  • IAM policies;
  • dynamic secrets;
  • leases;
  • key rotation;
  • centralized access control.

age краще для local/offline/simple workflows.

Якщо секрет потрібен production service — думати про Vault/KMS.

Якщо треба зашифрувати backup перед переносом на новий Mac — age.


Ротація ключів

age не має magical automatic re-encryption. Якщо private key скомпрометований, треба:

  1. Створити новий key:
age-keygen -o ~/.config/sops/age/keys-new.txt
age-keygen -y ~/.config/sops/age/keys-new.txt
  1. Оновити recipients у .sops.yaml / recipients.txt.
  2. Re-encrypt SOPS files:
sops updatekeys secrets/secrets.yaml
  1. Re-encrypt backup archives, якщо вони мають залишатись recoverable новим key.
  2. Видалити старий recipient з майбутніх encryption flows.
  3. Зафіксувати rotation у knowledge-base, але без private material.

Important: старі encrypted files, які вже були доступні compromised key, не стають “безпечними” від того, що ти створив новий key. Їх треба re-encrypt і вважати старі copies exposed, якщо attacker мав доступ.


Практична policy для мого сетапу

Для OpenClaw migration backups

  • Шифрувати через age.
  • Recipients: current OpenClaw Mac + emergency offline key.
  • Backup private identity зберігати в 1Password/encrypted offline media.
  • Не класти plaintext .tar.gz у cloud sync.
  • Перевіряти decrypt після створення backup.

Для Nix/mac-config secrets

  • Використовувати sops + age.
  • Public recipients у .sops.yaml можна комітити.
  • Private key тільки локально + secure backup.
  • Не зберігати .env напряму в Git.

Для knowledge-base

  • Поточний pattern: git-crypt.
  • age можна використовувати для snapshot backup або migration bundle.
  • Не дублювати private keys у notes.

Для cloud/production

  • Не використовувати age як єдиний production secret manager.
  • Для AWS/GCP/Azure — KMS/Vault/Secrets Manager залежно від use case.
  • age може бути тільки bootstrap/recovery layer.

Мінімальний cheat sheet

Generate key:

age-keygen -o ~/.config/sops/age/keys.txt
chmod 600 ~/.config/sops/age/keys.txt

Show public recipient:

age-keygen -y ~/.config/sops/age/keys.txt

Encrypt file:

age -r age1... -o file.age file

Decrypt file:

age -d -i ~/.config/sops/age/keys.txt -o file file.age

Encrypt directory:

tar -czf - ./folder | age -r age1... > folder.tar.gz.age

Decrypt directory:

age -d -i ~/.config/sops/age/keys.txt folder.tar.gz.age | tar -xzf -

Encrypt to multiple recipients:

age -R recipients.txt -o backup.age backup.tar.gz

SOPS edit:

sops secrets/secrets.yaml

Verify encrypted backup is readable:

age -d -i ~/.config/sops/age/keys.txt backup.tar.gz.age | tar -tzf - | head

Final recommendation

Для персонального DevSecOps/OpenClaw середовища age варто мати як стандартний інструмент. Він простий, переносимий і достатньо сильний для більшості local/offline encryption задач.

Моя рекомендована модель:

  • age — encrypted backups і migration bundles;
  • sops + age — secrets у Nix/mac-config;
  • git-crypt — encrypted knowledge-base repo;
  • 1Password — recovery material і людські secrets;
  • Vault/KMS — production secrets.

Це дає хороший баланс: мінімум складності локально, нормальна відтворюваність через Nix, безпечна міграція OpenClaw, і немає ілюзії, що один CLI вирішує весь secret-management lifecycle.