Навіщо шифрувати файли та резервні копії на сервері за допомогою GPG?
Шифрування файлів і резервних копій захищає дані, якщо носій або канал передачі скомпрометовано: викрадено диск VDS, скопійовано архів бекапу зі стороннього S3-сховища, перехоплено трафік під час вивантаження на віддалений сервер. GPG (GnuPG, реалізація OpenPGP) шифрує файли без сервера ключів і бази даних — достатньо бінарника gpg і файлу-ключа. На VDS/VPS і виділених серверах ZevsHost.net у Німеччині, США та Франції шифрування бекапів через GPG обов'язкове завжди, коли архів покидає сервер: іде на зовнішній S3, на FTP резервного хостингу або в інший дата-центр.
GPG підтримує два режими: симетричне шифрування одним паролем (gpg -c) для разового захисту файлу та асиметричне шифрування парою ключів — публічним і приватним — для автоматичних бекапів без участі людини. Розберемо обидві схеми нижче.
Як швидко зашифрувати файл симетрично: gpg -c і passphrase?
Симетричне шифрування підходить для разового завдання: передати один архів колезі, надіслати конфіг із секретами, зашифрувати знімок бази перед копіюванням на флешку.
gpg -c --cipher-algo AES256 backup.sql
# запитає passphrase двічі, створить backup.sql.gpg
gpg -o backup.sql -d backup.sql.gpg
# запитає passphrase для розшифрування
Прапорець --cipher-algo AES256 фіксує алгоритм явно: без нього старі версії GPG обирають CAST5, а він слабший за AES256. Пароль тут вводиться інтерактивно, тому для cron-скрипта потрібен файл із паролем і правами 600, інакше його зможе прочитати будь-який локальний користувач — детальніше про права читайте у статті про налаштування прав доступу Linux.
Як згенерувати пару ключів GPG і зашифрувати бекап асиметрично?
Асиметрична схема потрібна для автоматичних бекапів: скрипт шифрує архів публічним ключем, а розшифрувати його може лише той, у кого є приватний ключ і пароль до нього. Приватний ключ на продакшн-сервері зберігати не обов'язково — достатньо публічного.
gpg --full-generate-key
# обрати RSA and RSA, розмір ключа 4096
gpg --list-keys
gpg --export -a "backup@zevshost-client.example" > pubkey.asc
gpg --import pubkey.asc
Ключова пара за замовчуванням зберігається в ~/.gnupg (для root — у /root/.gnupg). Шифрування бекапу під ключ отримувача:
gpg --encrypt --recipient "backup@zevshost-client.example" backup.tar.gz
# створить backup.tar.gz.gpg
gpg --output backup.tar.gz -d backup.tar.gz.gpg
Приватний ключ — єдиний спосіб повернути дані, тому його потрібно винести за межі сервера: на офлайн-носій або в захищене сховище секретів, як описано у статті про зберігання секретів у Vault. Якщо приватний ключ втрачено або забуто пароль до нього — розшифрувати архіви фізично неможливо, служби відновлення в GPG немає.
Як автоматизувати GPG у cron без введення пароля вручну?
Cron-скрипт бекапу не може чекати на інтерактивне введення пароля, тому є робочі варіанти автоматизації. Для симетричного шифрування — файл із паролем і прапорці --batch:
umask 077
echo 'мій-довгий-пароль' > /root/.backup_pass
chmod 600 /root/.backup_pass
gpg --batch --yes --passphrase-file /root/.backup_pass -c --cipher-algo AES256 -o backup.tar.gz.gpg backup.tar.gz
Для асиметричного шифрування пароль не потрібен у момент архівації: шифрування публічним ключем відбувається без passphrase, а gpg-agent потрібен лише для операцій із приватним ключем (розшифрування, підпис).
| Спосіб | Де зберігається секрет | Підходить для cron | Ризик при компрометації сервера |
|---|---|---|---|
| gpg -c інтерактивно | вводиться вручну | ні | низький |
| --passphrase-file (600) | файл на диску | так | середній |
| gpg-agent + кеш | пам'ять агента | так, із застереженнями | середній |
| шифрування публічним ключем | приватний ключ не на сервері | так | низький |
Приклад рядка в crontab -e для root:
0 3 * * * tar czf - /var/www | gpg --encrypt --recipient "backup@zevshost-client.example" -o /backups/site-$(date +\%F).tar.gz.gpg && find /backups -name '*.gpg' -mtime +14 -delete
Як перевірити цілісність бекапу: підпис і verify?
Шифрування саме собою не гарантує, що файл не підмінили чи не пошкодили під час передачі на S3. Для цього GPG вміє підписувати файли окремо від шифрування:
gpg --detach-sign --armor backup.tar.gz.gpg
# створить backup.tar.gz.gpg.asc — файл підпису
gpg --verify backup.tar.gz.gpg.asc backup.tar.gz.gpg
# gpg: Good signature from "..." — файл цілий
# gpg: BAD signature — файл змінено або пошкоджено
У скрипті автоматичної перевірки зручно поєднувати шифрування та підпис однією командою --encrypt --sign, а перевірку виносити окремим кроком перед вивантаженням на S3. У разі відповіді BAD signature вивантаження варто зупиняти й надсилати сповіщення, а не перезаписувати старий бекап битим архівом. Загальний підхід до захисту сервера, на якому працює такий скрипт, — у статті про хардненінг SSH.
Чек-лист: типові помилки під час роботи з GPG на сервері
- Втрата приватного ключа без резервної копії — розшифрувати старі бекапи стане неможливим назавжди.
- Файл із паролем для --passphrase-file лежить із правами 644 замість 600 і читається будь-яким користувачем сервера.
- Шифрування без --cipher-algo AES256 на старих збірках GPG — використовується слабший алгоритм за замовчуванням.
- Приватний ключ зберігається на тому самому сервері, що шифрує бекапи, — під час зламу сервера втрачається весь захист.
- Немає окремої перевірки gpg --verify після вивантаження на S3 — пошкоджений архів виявляється лише під час відновлення.
Для порівняння: шифрування файлової системи через LUKS захищає весь диск, але не захищає окремий файл під час вивантаження назовні — про цей варіант читайте у статті про LUKS-шифрування диска. GPG і LUKS закривають різні сценарії й зазвичай використовуються разом: LUKS — для диска сервера повністю, GPG — для файлів і бекапів, що покидають сервер.