age: проста сучасна утиліта для шифрування файлів і секретів
Короткий висновок
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-darwinsecrets;home-managersecrets;.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-keygenkey; - для 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 стане сміттям.
Нормальні варіанти:
- 1Password secure note / file attachment — практично найзручніше для personal use.
- Encrypted USB drive — добрий offline backup.
- Paper backup для emergency key — можна надрукувати private key або QR, але це треба фізично захищати.
- Separate emergency age key — шифрувати важливі backup-и на daily key + offline emergency key.
- 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 скомпрометований, треба:
- Створити новий key:
age-keygen -o ~/.config/sops/age/keys-new.txt
age-keygen -y ~/.config/sops/age/keys-new.txt
- Оновити recipients у
.sops.yaml/recipients.txt. - Re-encrypt SOPS files:
sops updatekeys secrets/secrets.yaml
- Re-encrypt backup archives, якщо вони мають залишатись recoverable новим key.
- Видалити старий recipient з майбутніх encryption flows.
- Зафіксувати 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.