こうした不安を感じながら、バックアップファイルを平文のまま保管しているケースは少なくありません。
バックアップの目的はデータを守ることですが、保管場所のセキュリティが不十分だと、バックアップファイル自体が漏洩経路になります。gpgで暗号化しておけば、万が一ファイルが流出しても鍵なしでは内容を読めません。
この記事では、gpgとシェルスクリプトを組み合わせて暗号化バックアップをcronで無人自動実行する設計を解説します。trapによるエラー処理と後始末、復号テストによる整合性検証まで、本番環境で使える実装パターンを紹介します。
この記事のポイント
・gpg --symmetric でパスフレーズを使った対称暗号化バックアップを無人実行できる
・--passphrase-file でパスフレーズをファイルから安全に渡し、cron環境でも動作する
・trap cleanup EXIT で一時ファイルを確実に後始末するcleanup設計が必須
・暗号化後に gpg --decrypt | tar tz で整合性を検証し、破損を即座に検知する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
バックアップを暗号化しないとどんなリスクがあるのか
バックアップの保管先として、外部ストレージ(NAS、外付けHDD)やクラウドストレージ(S3、Backblaze B2など)を使うことが増えました。こうした場所に平文のままファイルを置くと、次のようなリスクが残ります。・クラウドの不正アクセス:アクセスキーの漏洩やバケットポリシーの設定ミスで、バックアップファイルが公開状態になる事故は実際に起きています。
・転送経路の問題:SFTP・rsync over SSHを使っていれば転送は暗号化されますが、宛先サーバーに保存された時点で平文に戻ります。
・物理メディアの紛失:外付けHDDを持ち出す場面では、紛失・盗難時に内容がそのまま読まれます。
gpgで暗号化すれば、鍵(またはパスフレーズ)を持っていない第三者はファイルの内容を読めません。保管場所のセキュリティとは独立した防衛層を一枚加えられます。
gpgの2つの暗号化方式と自動化での選択
gpgには大きく2つの暗号化方式があります。・対称暗号化(--symmetric):パスフレーズだけで暗号化・復号する。gpg鍵ペアが不要で仕組みが単純。cronなど無人実行と相性がよく、シェルスクリプトから扱いやすい。
・公開鍵暗号化(--encrypt --recipient):受信者の公開鍵で暗号化し、秘密鍵でのみ復号できる。バックアップの暗号化は公開鍵で行い、復号は別の安全なPCでのみできる設計が可能。
cronからの無人バックアップには、設定が少なく管理しやすい対称暗号化を推奨します。パスフレーズはファイルから渡す方法(後述)で安全に管理できます。
tarとgpgを組み合わせた暗号化バックアップの基本パターン
1. ディレクトリをtar圧縮してgpgで対称暗号化する
# tarでgzip圧縮して一時ファイルに保存 tar czf /tmp/backup_www.tar.gz -C /var www # gpgで対称暗号化(対話でパスフレーズを入力する場合) gpg --symmetric --cipher-algo AES256 \ --output /backup/backup_www.tar.gz.gpg \ /tmp/backup_www.tar.gz # 暗号化後に元の一時ファイルを削除 rm -f /tmp/backup_www.tar.gz
パイプで繋げてワンライナーにすることもできます。
# tarの出力を直接gpgに渡す(一時ファイル不要) tar czf - /var/www | gpg --symmetric --cipher-algo AES256 \ --batch --passphrase-file /root/.backup-passphrase \ --output /backup/backup_www.tar.gz.gpg
2. 暗号化ファイルを復号して元に戻す
# 復号して指定ディレクトリに展開 gpg --batch --passphrase-file /root/.backup-passphrase \ --pinentry-mode loopback \ --decrypt /backup/backup_www.tar.gz.gpg \ | tar xzf - -C /restore/
# gpg --version gpg (GnuPG) 2.4.4 libgcrypt 1.10.3 Copyright (C) 2024 g10 Code GmbH ...
シェルスクリプトへの組み込みとエラー処理設計
1. trapでcleanupを確実にする
暗号化処理の途中でエラーや強制終了が起きると、一時ファイルが残ります。`trap ... EXIT` で終了時に必ずcleanupが走る設計にします。#!/bin/bash set -euo pipefail readonly BACKUP_SRC="/var/www/html" readonly BACKUP_DEST="/backup/encrypted" readonly PASSPHRASE_FILE="/root/.backup-passphrase" readonly LOG_FILE="/var/log/backup-gpg.log" # 一時ファイルのパスを変数として保持(cleanup関数で参照する) TMPFILE="" cleanup() { if [[ -n "$TMPFILE" && -f "$TMPFILE" ]]; then rm -f "$TMPFILE" fi } trap cleanup EXIT log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" | tee -a "$LOG_FILE" }
2. 暗号化処理の本体とエラー検知
# 事前確認 [[ -f "$PASSPHRASE_FILE" ]] || { log "ERROR: パスフレーズファイルが存在しない: $PASSPHRASE_FILE"; exit 1; } [[ -d "$BACKUP_SRC" ]] || { log "ERROR: バックアップ元が存在しない: $BACKUP_SRC"; exit 1; } [[ -d "$BACKUP_DEST" ]] || mkdir -p "$BACKUP_DEST" # パスフレーズファイルのパーミッション確認(600または400 のみ許可) PERM=$(stat -c%a "$PASSPHRASE_FILE") if [[ "$PERM" != "600" && "$PERM" != "400" ]]; then log "ERROR: パスフレーズファイルのパーミッションが不正: $PERM(600 が必要)" exit 1 fi TMPFILE=$(mktemp /tmp/gpg_backup_XXXXXX.tar.gz) DEST_FILE="${BACKUP_DEST}/backup_$(date '+%Y%m%d_%H%M%S').tar.gz.gpg" log "INFO: バックアップ開始: $BACKUP_SRC" # tar圧縮 if ! tar czf "$TMPFILE" -C "$(dirname "$BACKUP_SRC")" "$(basename "$BACKUP_SRC")"; then log "ERROR: tar圧縮失敗" exit 1 fi log "INFO: tar圧縮完了 ($(stat -c%s "$TMPFILE") bytes)" # gpg暗号化 if ! gpg --batch \ --passphrase-file "$PASSPHRASE_FILE" \ --pinentry-mode loopback \ --symmetric --cipher-algo AES256 \ --output "$DEST_FILE" "$TMPFILE"; then log "ERROR: gpg暗号化失敗" exit 1 fi log "INFO: 暗号化完了: $DEST_FILE ($(stat -c%s "$DEST_FILE") bytes)"
if ! コマンド の形式は `set -e` の対象外なので、明示的に `exit 1` を書いています。cronからの無人実行:パスフレーズをどう渡すか
cronは対話ターミナルを持たないため、gpgにパスフレーズを対話入力できません。`--passphrase-file` を使い、パスフレーズをファイルから渡します。1. パスフレーズファイルの準備と権限設定
# パスフレーズを書いたファイルを作成 echo "your-strong-passphrase" > /root/.backup-passphrase # root のみ読み取り可能にする chmod 600 /root/.backup-passphrase # 確認 ls -la /root/.backup-passphrase # -rw------- 1 root root 24 Sep 1 10:00 /root/.backup-passphrase
2. GNUPGHOME環境変数でgpg設定を分離する
cronから呼ぶ場合、`$HOME/.gnupg` が参照できなかったり、gpg-agentの扱いが端末実行と異なったりすることがあります。専用の `GNUPGHOME` ディレクトリを用意すると、環境依存の問題を防げます。# スクリプト冒頭(ログ変数定義の前あたり)に追加 export GNUPGHOME="/root/.gnupg-backup" if [[ ! -d "$GNUPGHOME" ]]; then mkdir -p "$GNUPGHOME" chmod 700 "$GNUPGHOME" # pinentry-mode loopback をデフォルト設定として書き込む echo "pinentry-mode loopback" > "${GNUPGHOME}/gpg.conf" fi
crontabへの登録例:
# /etc/cron.d/backup-encrypted # 毎日午前2時に実行 0 2 * * * root /usr/local/bin/backup-encrypted.sh >> /var/log/backup-gpg.log 2>&1
復号テストでバックアップの整合性を自動検証する
暗号化が成功しても、途中でファイルが壊れていたり暗号化が不完全だったりすると復号できません。バックアップ完了後に復号テストを自動実行して、正常に復元できるファイルかどうかを確認します。# バックアップスクリプトの末尾に追加する整合性検証関数 verify_backup() { local encrypted_file="$1" log "INFO: 整合性検証開始: $encrypted_file" # 復号してtarのファイル一覧のみ確認(展開は行わない) if gpg --batch \ --passphrase-file "$PASSPHRASE_FILE" \ --pinentry-mode loopback \ --decrypt "$encrypted_file" \ | tar tzf - > /dev/null; then log "INFO: 整合性検証 OK" return 0 else log "ERROR: 整合性検証失敗 — 復号またはtar読み取りに失敗" return 1 fi } # 暗号化後に呼び出す verify_backup "$DEST_FILE"
実際に動作した際のログ出力の例:
2026-09-01 02:00:03 INFO: バックアップ開始: /var/www/html 2026-09-01 02:00:15 INFO: tar圧縮完了 (148729344 bytes) 2026-09-01 02:00:22 INFO: 暗号化完了: /backup/encrypted/backup_20260901_020003.tar.gz.gpg (74402816 bytes) 2026-09-01 02:00:28 INFO: 整合性検証 OK
トラブルシュート:よくあるエラーと対処
「gpg: no valid OpenPGP data found」または「gpg: decryption failed: Bad session key」暗号化と復号でパスフレーズが一致していない場合に起こります。パスフレーズファイルに余分な改行や空白が含まれていないか
cat -A /root/.backup-passphrase で確認し、末尾に `$` 以外の文字があれば修正します。「gpg: public key decryption failed: No secret key」
対称暗号化(--symmetric)ではなく誤って公開鍵暗号化(--encrypt)で暗号化した場合に起こります。どちらの方式で作成したファイルかを `file コマンド` で確認し、暗号化手順を見直してください。
cronから実行すると動かない(端末から手動実行すると動く)
最も多い原因は次の3つです。
・`GNUPGHOME` が設定されておらず、root の `.gnupg` が参照できていない
・`pinentry-mode loopback` が設定されておらず、pinentryを呼ぼうとして失敗している
・cronの `PATH` に `/usr/bin` が含まれず、gpgやtarのフルパスが必要
crontabの先頭に `PATH=/usr/bin:/usr/local/bin:/bin` を追記するか、スクリプト内で絶対パス (`/usr/bin/gpg`) を使う方法で解消できます。
暗号化後のファイルサイズが元より大きい
gpgの暗号化ヘッダやメタデータの分、数百バイト程度の増加は正常です。gzip圧縮済みの `.tar.gz` を暗号化した場合、圧縮と暗号化でサイズがほぼ変わらないのが正常な動作です。
本記事のまとめ
gpgを使った暗号化バックアップをシェルスクリプトで自動化するポイントをまとめます。| 設計ポイント | 実装のコツ |
|---|---|
| 暗号化方式の選択 | gpg --symmetric --cipher-algo AES256(無人実行向け) |
| パスフレーズの受け渡し | gpg --passphrase-file /root/.backup-passphrase(権限 600 必須) |
| cron環境での設定 | GNUPGHOME固定+--pinentry-mode loopback |
| 一時ファイルの後始末 | trap cleanup EXITで確実に削除 |
| エラー検知の設計 | set -euo pipefail+各コマンドの終了コード確認 |
| 整合性の検証 | 暗号化後にgpg --decrypt | tar tzでテスト |
バックアップは「作るだけ」では不十分です。暗号化して安全に保管し、復元できることを確認するまでが一連の設計です。深夜に無人で動き、万が一の際に確実に復元できるスクリプトを一度組んでおくと、その後の運用の安心感が大きく変わります。
シェルスクリプト講座を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 次のページへ:シェルスクリプトのshoptコマンドでbash動作を設計する方法|globstar・nullglob・nocasematchの実践活用
- 前のページへ:シェルスクリプトでメンテナンスウィンドウを実装する設計|時刻・曜日チェックで作業時間外の実行を制御する方法
- この記事の属するカテゴリ:シェルスクリプトへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます