SynologyサーバーのGlacier Deep Archiveバックアップ設定

バックアップ対象
/var/services/homes
/var/services/music

$ aws configure sso --use-device-code

$ /bin/sudo /usr/local/bin/docker run --rm -it -v ~/.aws:/root/.aws amazon/aws-c
li --version
$ which curl
/bin/curl
$ which bash
/bin/bash

Container Managerでamazon/aws-cliをダウンロード
docker run --rm -it amazon/aws-cli --version
# cron向けなら
/usr/local/bin/docker run --rm -it amazon/aws-cli --version
--rm
:コマンド実行後、コンテナを自動削除してくれる
-it
:対話的なシェルを立ち上げてくれる的な?

管理者権限が必要なコマンドは、rootユーザーのcronとして登録する
(ベストプラクティスかはわからない)

cronスクリプトの改善
$ /usr/local/bin/docker run --rm -it amazon/aws-cli --version
the input device is not a TTY
-it
オプションを削除すればよいらしい
↓
やった!
$ /usr/local/bin/docker run --rm -it amazon/aws-cli --version
aws-cli/2.25.6 Python/3.12.9 Linux/5.10.55+ docker/aarch64.amzn.2

Container Manager のコンテナ dazzling_euler が予期せず停止しました。[コンテナ] ページで [dazzling_euler] を選択し、[詳細] ボタンをクリックし、[ログ] タブで詳細を確認してください。
という通知が毎回来る。

コントロールパネルから力技で止めることもできそう

丁寧にやるなら、この辺りを読み解く必要があるか。
一旦、そのままで様子見とする

AWS CLIの初期設定に移る

推奨されている、「IAM アイデンティティセンターのワークフォースユーザーの短期認証情報」にチャレンジする。
……と考えたが、このサイトを参考にアクセスキー・ベースの認証にする

コンソール
→ Identity and Access Management (IAM)
→ アクセス管理>ユーザー
→ ユーザーの作成
→ S3FullAccessを付与(グループを作成するなり、ポリシーを直接アタッチするなり)
作成したユーザーを選択
→ セキュリティ認証情報
→ アクセスキーを作成
→ アクセスキー、シークレットアクセスキーを大切な場所に保管しておく

とてもうまくいきそうだが、コンテナ作成時のボリューム選択画面で homes
ディレクトリが表示されない。

ここで示されている回避策は次の通り:
-
/var/sercives/homes
をボリュームとしてマウントできるよう、コマンドで起動する - シンボリックリンクは有効とも無効とも
- Portainerを使用してボリュームをマップする

docker start
時にマウントするのがよさそうかなぁ
沼らないように、きちんと勉強してやってみよう

Claude Codeに
Synology Glacier Deep Archiveバックアップ実装
1. 事前準備
1.1 S3バケットの作成
# バケット作成(リージョンは適宜変更)
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-e AWS_PROFILE=default \
amazon/aws-cli s3 mb s3://your-backup-bucket-name --region ap-northeast-1
1.2 AWS認証情報の設定
# ~/.aws/credentials に設定
[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY
region = ap-northeast-1
2. バックアップスクリプトの作成
2.1 メインバックアップスクリプト
/volume1/scripts/backup_to_glacier.sh
を作成:
#!/bin/bash
# 設定
BACKUP_BUCKET="your-backup-bucket-name"
LOG_FILE="/volume1/logs/glacier_backup.log"
TEMP_DIR="/tmp/backup_$(date +%Y%m%d_%H%M%S)"
DATE_STAMP=$(date +%Y%m%d_%H%M%S)
# ログ関数
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}
# エラーハンドリング
error_exit() {
log "ERROR: $1"
cleanup
exit 1
}
# クリーンアップ
cleanup() {
log "クリーンアップ開始"
rm -rf "$TEMP_DIR"
log "クリーンアップ完了"
}
# バックアップ対象ディレクトリ
BACKUP_TARGETS=(
"/var/services/homes"
"/var/services/music"
)
# メイン処理開始
log "=== Glacier Deep Archive バックアップ開始 ==="
# 一時ディレクトリ作成
mkdir -p "$TEMP_DIR" || error_exit "一時ディレクトリの作成に失敗"
mkdir -p "$(dirname "$LOG_FILE")" || error_exit "ログディレクトリの作成に失敗"
for target in "${BACKUP_TARGETS[@]}"; do
if [ ! -d "$target" ]; then
log "WARNING: $target が存在しません。スキップします。"
continue
fi
# ディレクトリ名取得(パスから最後の部分)
dir_name=$(basename "$target")
archive_name="${dir_name}_${DATE_STAMP}.tar.gz"
archive_path="$TEMP_DIR/$archive_name"
log "$target のアーカイブ作成開始: $archive_name"
# tar.gz作成(進捗表示付き)
tar -czf "$archive_path" -C "$(dirname "$target")" "$dir_name" 2>&1 | \
while read line; do
log "TAR: $line"
done
if [ ${PIPESTATUS[0]} -ne 0 ]; then
error_exit "$target のアーカイブ作成に失敗"
fi
# ファイルサイズ確認
file_size=$(stat -c%s "$archive_path")
file_size_mb=$((file_size / 1024 / 1024))
log "アーカイブサイズ: ${file_size_mb}MB"
# S3にアップロード(Glacier Deep Archiveストレージクラス指定)
log "S3へのアップロード開始: s3://$BACKUP_BUCKET/backups/$archive_name"
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-v "$TEMP_DIR:/backup" \
-e AWS_PROFILE=default \
amazon/aws-cli s3 cp "/backup/$archive_name" \
"s3://$BACKUP_BUCKET/backups/$archive_name" \
--storage-class DEEP_ARCHIVE \
--progress 2>&1 | while read line; do
log "S3: $line"
done
if [ ${PIPESTATUS[0]} -ne 0 ]; then
error_exit "S3へのアップロードに失敗: $archive_name"
fi
log "$archive_name のアップロード完了"
# 一時ファイル削除
rm -f "$archive_path"
log "$archive_name のローカルファイル削除完了"
done
cleanup
log "=== すべてのバックアップが正常に完了しました ==="
2.2 スクリプトに実行権限を付与
chmod +x /volume1/scripts/backup_to_glacier.sh
3. 動作検証
3.1 テスト用の小さなディレクトリでテスト
# テスト用ディレクトリ作成
mkdir -p /volume1/test_backup
echo "テストファイル $(date)" > /volume1/test_backup/test.txt
# テスト用スクリプトの実行(BACKUP_TARGETSを変更して)
/volume1/scripts/backup_to_glacier.sh
3.2 バックアップ確認
# S3内のファイル一覧確認
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-e AWS_PROFILE=default \
amazon/aws-cli s3 ls s3://your-backup-bucket-name/backups/ --recursive
# 特定ファイルの詳細情報確認
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-e AWS_PROFILE=default \
amazon/aws-cli s3api head-object \
--bucket your-backup-bucket-name \
--key backups/homes_20250702_120000.tar.gz
3.3 復元テスト(注意:Deep Archiveは復元に12時間かかります)
# 復元リクエスト(Expedited, Standard, Bulk から選択)
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-e AWS_PROFILE=default \
amazon/aws-cli s3api restore-object \
--bucket your-backup-bucket-name \
--key backups/test_backup_20250702_120000.tar.gz \
--restore-request Days=1,GlacierJobParameters='{Tier=Standard}'
# 復元状況確認
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-e AWS_PROFILE=default \
amazon/aws-cli s3api head-object \
--bucket your-backup-bucket-name \
--key backups/test_backup_20250702_120000.tar.gz
4. Cron設定
4.1 ボリュームマウント問題の解決
Container Managerでhomesディレクトリが表示されない問題の解決策:
# コマンドライン版(推奨)
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-v /var/services/homes:/mnt/homes:ro \
-v /var/services/music:/mnt/music:ro \
-v /volume1/scripts:/scripts \
-v /volume1/logs:/logs \
-e AWS_PROFILE=default \
amazon/aws-cli --version
4.2 最終バックアップスクリプト(マウント対応版)
/volume1/scripts/backup_to_glacier_container.sh
:
#!/bin/bash
BACKUP_BUCKET="your-backup-bucket-name"
DATE_STAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/volume1/logs/glacier_backup.log"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}
mkdir -p "$(dirname "$LOG_FILE")"
log "=== Glacier Deep Archive バックアップ開始 ==="
# Dockerコンテナ内でバックアップ実行
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-v /var/services/homes:/mnt/homes:ro \
-v /var/services/music:/mnt/music:ro \
-v /volume1/scripts:/scripts \
-v /volume1/logs:/logs \
-e AWS_PROFILE=default \
-e BACKUP_BUCKET="$BACKUP_BUCKET" \
-e DATE_STAMP="$DATE_STAMP" \
--entrypoint /bin/bash \
amazon/aws-cli /scripts/backup_inside_container.sh
log "=== バックアップ処理完了 ==="
4.3 コンテナ内実行スクリプト
/volume1/scripts/backup_inside_container.sh
:
#!/bin/bash
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "/logs/glacier_backup.log"
}
# バックアップ対象
TARGETS=(
"homes:/mnt/homes"
"music:/mnt/music"
)
TEMP_DIR="/tmp/backup_${DATE_STAMP}"
mkdir -p "$TEMP_DIR"
for target_info in "${TARGETS[@]}"; do
target_name=$(echo "$target_info" | cut -d: -f1)
target_path=$(echo "$target_info" | cut -d: -f2)
if [ ! -d "$target_path" ]; then
log "WARNING: $target_path が存在しません"
continue
fi
archive_name="${target_name}_${DATE_STAMP}.tar.gz"
archive_path="$TEMP_DIR/$archive_name"
log "$target_path のアーカイブ作成開始"
tar -czf "$archive_path" -C "$target_path" . || {
log "ERROR: アーカイブ作成失敗 - $target_path"
continue
}
file_size=$(stat -c%s "$archive_path")
file_size_mb=$((file_size / 1024 / 1024))
log "アーカイブサイズ: ${file_size_mb}MB"
log "S3アップロード開始: $archive_name"
aws s3 cp "$archive_path" \
"s3://$BACKUP_BUCKET/backups/$archive_name" \
--storage-class DEEP_ARCHIVE \
--progress || {
log "ERROR: S3アップロード失敗 - $archive_name"
continue
}
log "$archive_name アップロード完了"
rm -f "$archive_path"
done
rm -rf "$TEMP_DIR"
log "クリーンアップ完了"
4.4 実行権限付与
chmod +x /volume1/scripts/backup_to_glacier_container.sh
chmod +x /volume1/scripts/backup_inside_container.sh
4.5 Cron設定
# rootのcrontabを編集
sudo crontab -e
# 毎週日曜日の午前2時に実行
0 2 * * 0 /volume1/scripts/backup_to_glacier_container.sh >> /volume1/logs/cron_backup.log 2>&1
# 毎月1日の午前3時に実行(月次バックアップ)
0 3 1 * * /volume1/scripts/backup_to_glacier_container.sh >> /volume1/logs/cron_backup.log 2>&1
5. 監視・メンテナンス
5.1 バックアップ履歴確認
# 最近のバックアップ一覧
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-e AWS_PROFILE=default \
amazon/aws-cli s3 ls s3://your-backup-bucket-name/backups/ \
--human-readable --summarize
# ログ確認
tail -f /volume1/logs/glacier_backup.log
5.2 古いバックアップの削除(ライフサイクル設定)
# ライフサイクル設定JSONファイル作成
cat > /volume1/scripts/lifecycle.json << 'EOF'
{
"Rules": [
{
"ID": "DeleteOldBackups",
"Status": "Enabled",
"Filter": {
"Prefix": "backups/"
},
"Expiration": {
"Days": 2555
}
}
]
}
EOF
# ライフサイクル設定適用(7年後に削除)
/usr/local/bin/docker run --rm \
-v ~/.aws:/root/.aws \
-v /volume1/scripts:/scripts \
-e AWS_PROFILE=default \
amazon/aws-cli s3api put-bucket-lifecycle-configuration \
--bucket your-backup-bucket-name \
--lifecycle-configuration file:///scripts/lifecycle.json
5.3 通知設定(オプション)
失敗時にメール通知する場合は、Synologyの通知機能を活用:
# バックアップスクリプトに追加
send_notification() {
local message="$1"
local subject="Glacier Backup Notification"
# Synology通知機能を使用
/usr/syno/bin/synonet --wake lan1 &
echo "$message" | mail -s "$subject" admin@yourdomain.com
}
# エラー時に通知
error_exit() {
log "ERROR: $1"
send_notification "バックアップエラー: $1"
cleanup
exit 1
}
6. コスト最適化のTips
-
圧縮率の向上:
tar -czf
の代わりにtar -cJf
(xz圧縮)を使用 - 重複排除: rsyncでの差分バックアップと組み合わせ
- バックアップ頻度の調整: 重要度に応じて日次/週次/月次を使い分け
-
マルチパートアップロード: 大きなファイルの場合は
aws s3 cp
が自動で実施
7. トラブルシューティング
よくある問題と解決策
- 権限エラー: Dockerコンテナ内でのファイルアクセス権限
- 容量不足: 一時ディレクトリの容量確認
- ネットワークエラー: アップロード中断時の再開
- 認証エラー: AWS認証情報の確認
詳細な問題解決は実際の症状に応じて対応します。

動作検証
# 最小限の検証
/usr/local/bin/docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli sts get-caller-identity && echo "✅ AWS認証OK" || echo "❌ AWS認証NG"
# バケットアクセス + アップロード権限確認
/usr/local/bin/docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli bash -c 'aws s3 ls s3://your-bucket/ && echo "test" | aws s3 cp - s3://your-bucket/test.txt && aws s3 rm s3://your-bucket/test.txt && echo "✅ S3操作OK"' || echo "❌ S3操作NG"
# パイプアップロード確認
/usr/local/bin/docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli bash -c 'echo "test" | tar -czf - -T - | aws s3 cp - s3://your-bucket/pipe-test.tar.gz --storage-class DEEP_ARCHIVE && aws s3 rm s3://your-bucket/pipe-test.tar.gz && echo "✅ パイプアップロードOK"' || echo "❌ パイプアップロードNG"

ターミナルでの検証
****@****: ~$ sudo -i
Password:
root@****: ~# /usr/local/bin/docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli --version
aws-cli/2.27.47 Python/3.13.4 Linux/5.10.55+ docker/aarch64.amzn.2
root@****:~# /usr/local/bin/docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli sts get-caller-identity
Unable to locate credentials. You can configure credentials by running "aws configure".
root@8888:~# /usr/local/bin/docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli configure

まずは認証情報を手動設定
****@****:~# cat > ~/.aws/credentials << 'EOF'
> [default]
> aws_access_key_id = xxxxxxxxx
> aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxx
> EOF
****@****:~# /usr/local/bin/docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli sts get-caller-identity
{
"UserId": "xxxxxxxxxxxxxxxxxx",
"Account": "xxxxxxxxx",
"Arn": "arn:aws:iam::xxxxxxxxx:user/xxxxxxxxx"
}

次に設定を手動設定
まずはレイテンシを犠牲にしても、安価なリージョンを選択
****@****:~# cat > ~/.aws/config << 'EOF'
> [default]
> region = us-east-1
> output = json
> EOF
****@****:~# /usr/local/bin/docker run --rm -v ~/.aws:/root/.aws amazon/aws-cli configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************QQ7E shared-credentials-file
secret_key ****************hRNE shared-credentials-file
region us-east-1 config-file ~/.aws/config