要素採用理由
バックアップ元Hostinger VPSNextcloud / n8n / Postiz / 各 DB が稼働
バックアップツールrestic 0.16.4単一バイナリ、暗号化、対応
保存先 R2egress 無料、$0.015/GB/月、S3 互換
スケジュール 04:00 UTC(13:00 JST)サーバー負荷の低い時間帯
日次 7 + 週次 4 + 月次 6restic forget で自動運用
暗号化restic 標準パスフレーズで全リポジトリ暗号化
項目設定
------
Bucket name<任意>(例: vps-backup
LocationAutomatic(Asia Pacific が自動選択)
Default Storage ClassStandard(restic は週 1 回 check で読みに行くため)
項目設定
------
Token namevps-backup-token
PermissionsObject Read & Write(Admin Read & Write は権限が広すぎるので NG)
Specify bucket(s)作成したバケットのみ
TTLForever
バックアップ「あるはず」じゃ済まない時代、御社の耐久力を診断しませんか?
細マッチョ企業診断 / 3 分 8 問
診断する

Step 2: VPS 側のセットアップ

2.1 restic のインストール

export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq restic
restic version
# → restic 0.16.4 compiled with go1.22.2 on linux/amd64

apt-get の対話プロンプトが表示されると SSH 越しにハングするので、DEBIAN_FRONTEND=noninteractive を必ず設定します。

2.2 認証情報を保存



/root/.config/restic/r2-credentials.env を chmod 600 で作成:

export AWS_ACCESS_KEY_ID="<R2 Access Key ID>"
export AWS_SECRET_ACCESS_KEY="<R2 Secret Access Key>"
export RESTIC_REPOSITORY="s3:https://<account-id>.r2.cloudflarestorage.com/<bucket-name>"
export RESTIC_PASSWORD="<openssl rand -base64 32 で生成した強パスフレーズ>"

RESTIC_PASSWORD3 重保管してください(VPS / 手元 PC / オフライン媒体)。これを失うとバックアップは復元できなくなります

2.3 リポジトリ初期化

. /root/.config/restic/r2-credentials.env
restic init
# → created restic repository <id> at s3:https://...

これで R2 バケット内に restic のリポジトリ構造が作られます。

Step 3: バックアップスクリプト



/usr/local/bin/vps-backup.sh を作成(chmod 700)。流れは「DB ダンプ → restic backup → 保持ポリシー適用 → 軽い整合性チェック」。

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

LOG_FILE="/var/log/vps-backup.log"
DUMP_DIR="/tmp/restic-dumps-$$"
log() { printf '[%s] %s\n' "$(date -u +%FT%TZ)" "$*" | tee -a "$LOG_FILE"; }
trap 'rm -rf "$DUMP_DIR"' EXIT

. /root/.config/restic/r2-credentials.env
. /root/.config/restic/db-credentials.env

mkdir -p "$DUMP_DIR" && chmod 700 "$DUMP_DIR"

log "=== Backup START ==="

# DB ダンプ(並列で MariaDB + Postgres x N)
docker exec -e MYSQL_PWD="$NEXTCLOUD_DB_PASSWORD" nextcloud-db \
    mariadb-dump --single-transaction --quick --skip-lock-tables \
    -uroot nextcloud | gzip > "$DUMP_DIR/nextcloud.sql.gz"

docker exec -e PGPASSWORD="$POSTIZ_DB_PASSWORD" postiz-postgres \
    pg_dumpall -U postiz | gzip > "$DUMP_DIR/postiz.sql.gz"

# restic backup
restic backup \
    --tag scheduled \
    --exclude-caches \
    --exclude '/var/log' --exclude '/tmp' \
    --exclude '/root/.npm' --exclude '/root/.cache' \
    /var/lib/docker/volumes/nextcloud_nc_data \
    /var/lib/docker/volumes/n8n_data \
    /var/lib/docker/volumes/postiz_postiz-uploads \
    /etc /root/.ssh /root/.config \
    "$DUMP_DIR"

# 保持ポリシー(日次 7 + 週次 4 + 月次 6)+ 自動 prune
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

# 軽い整合性チェック(5% サブセット)
restic check --read-data-subset=5%

log "=== Backup END ==="

mariadb-dump--single-transactionロックなしダンプ。本番稼働中の DB に影響しません。

Step 3.1: cron に登録

( crontab -l 2>/dev/null; echo '0 4 * * * /usr/local/bin/vps-backup.sh >> /var/log/vps-backup.log 2>&1' ) | crontab -

毎日 04:00 UTC(13:00 JST)に自動実行。サーバー負荷の低い時間帯です。

Step 3.2: ログローテート設定

cat > /etc/logrotate.d/vps-backup <<EOF
/var/log/vps-backup.log {
    weekly
    rotate 8
    compress
    missingok
    notifempty
    create 600 root root
}
EOF

これでログが肥大化することを防げます。

Step 4: 初回フルバックアップ

nohup /usr/local/bin/vps-backup.sh >> /var/log/vps-backup.log 2>&1 &
tail -f /var/log/vps-backup.log
項目
ファイル数332,446
元サイズ16.730 GiB
R2 上の実サイズ5.048 GiB(圧縮率 2.56x、60.93% 削減)
所要時間2 分 59 秒
アップロード速度約 95 MB/s
. /root/.config/restic/r2-credentials.env

# 任意のファイルを R2 から取り出す
restic restore latest \
    --target /tmp/restore-test \
    --include /etc/hostname

# オリジナルと比較
diff /etc/hostname /tmp/restore-test/etc/hostname && echo "✅ 一致"

# 後片付け
rm -rf /tmp/restore-test

当方の実測:単一ファイル復元は1 秒以内、フル復元は 5〜15 分。

💡 KEY TAKEAWAYS
復元テストをしていないバックアップは、バックアップではありません。月 1 回必ず実行する習慣をつけてください。

ハマりポイント 3 つ



restic + R2 構築で踏んだ 3 つの罠
restic + R2 構築で踏んだ 3 つの罠


落とし穴 1: SSH 鍵パスのタイプミス



~/.ssh/_ed25519~/.ssh/_ed25739 と打ち間違えて、SSH コマンドが「Permission denied (publickey)」で延々と弾かれました。Tab 補完を使わずに手打ちで ed25519 を入れる場合、数字部分は要注意です。

突破: SSH 鍵パスはエイリアスを ~/.ssh/config に登録して、ssh で接続するスタイルが安全です。

落とし穴 2: apt-get install がプロンプトでハング



apt-get install restic が SSH 越しに実行中、Configuration file modified の対話プロンプトが出てハングしました。SSH は「待機中」と見えるだけで、何も進みません。

突破: export DEBIAN_FRONTEND=noninteractiveスクリプト先頭で必ず宣言。これだけで対話プロンプトを全て自動回答に切り替えられます。

落とし穴 3: restic の保持ポリシー試算ミス



「日次 7 + 週次 4 + 月次 6 = 17 世代分の容量が必要」と思いがちですが、restic は重複排除しているため、実容量は初回 + 変更分のみ。当方の場合 16.7GB の元データに対し、7 世代維持しても R2 上は 7〜10GB 程度で済みます。

突破: 試算は「初回 × 1.5」程度を上限の目安に。月額計算は実測でみて初月で確定させます。

次のアクション



「バックアップは大事」と頭で分かっていても、実際に組まないと災害復旧はできません。本記事の構成は VPS 1 台あたり月 22 円から始められ、構築 30〜60 分で運用に乗ります。

本シリーズ第 1 回「Nextcloud のロック詰まりは Redis 化で解決する」、第 3 回「Dropbox 代替を自社で組む判断軸」と合わせて読むと、自社のクラウドストレージを / サブスクリプションから卒業する全体像が掴めます。

「自社で組むのは技術的に厳しい」「組んだが運用が続かない」という方は、まず 細マッチョ企業診断 で耐久力(事業継続性)の現在地を把握ください。EXBANK ではバックアップ構築 + 6 ヶ月伴走運用パッケージも提供しています。