GitLabのバックアップ
LAN内で利用しているGitLabサーバを自動バックアップしたい。
0. 要件整理
(1) バックアップ方法
gitlab 12.2以降はgitlab-rake
ではなく、gitlab-backup
コマンドを利用する。
出力されたバックアップデータを同じLAN内のSynology NASに転送して保管することにする。
(2) 頻度・タイミング
個人利用なので、1週間に1度フルバックアップを取ることにする。cronによるgitlab-backup
コマンドを実行する。
タイミングは月曜早朝(AM4時)とする。
(3) バックアップ先容量
10GB程度を確保する。仮に1回のバックアップで1GB利用するとしても2ヶ月は保管できることになる。
(4) 転送方法
一般的なファイル転送方法としては以下が挙げられる。
方法 | NFS | SMB | rsync |
---|---|---|---|
速度 | 速い | 中程度 | 高速(差分同期) |
用途 | ファイル共有 | 異OS間のファイル共有 | バックアップや同期 |
設定の簡単さ | 普通 | 簡単(GUIあり) | 簡単(CLIのみ) |
セキュリティ | 弱め(要設定) | 強力(ユーザ認証) | 強力(SSH利用) |
リアルタイム性 | あり | あり | なし |
対応OS | Linux/Unix | Windows/Linux | 全て |
WAN超え | 不安定 | SMB3以上なら可 | SSH経由で安定 |
ファイルロック | 弱い | 強力 | なし |
使い方 | マウント | マウント | CLIでコマンド実行 |
今回は、マウント処理を入れると挙動が複雑になり運用が大変そうなので、マウント処理が不要なrsyncを採用する。
1. NAS側の設定
1-1. [Synology NAS] 共有フォルダの作成
コントロールパネル > 共有フォルダ > 作成 > 共有フォルダの作成
から新規フォルダを作成
特に暗号化は不要
1-2. [Synology NAS] rsyncサービスの有効化
コントロールパネル > ファイルサービス > rsync
からrsyncサービスを有効にする
1-3. [Synology NAS] gitlab_backupユーザの作成
コントロールパネル > ユーザーとグループ > 作成
から新規ユーザを作成する。
共有フォルダは「gitlab_backup」のみアクセス権限を付与する。
各設定項目は以下のように、基本デフォルトで、アプリケーション権限の割り当てにおいてrsysnc
のみ許可する。
1-4. [Synology NAS] SSH接続の有効化
rsyncは独自のネットワーク転送用プロトコルを持っているが、セキュリティと利便性の観点から、SSHを使って転送することとする。(SSHキー使えばGitLabサーバからパスワードなしで自動接続が可能)
そのため、SSH接続を受け付けるNAS側でもSSHを有効化しておく必要がある。
1-5. [Synology NAS] SSH関連フォルダパーミッション設定
SSHに関連したフォルダは厳格なパーミッション設定が求められる。具体的には、
- 「/home/(ユーザー名)/」のフォルダのパーミッションが「755」より厳しいこと
- 「/home/(ユーザー名)/.ssh」のフォルダのパーミッションが「700」であること
- 「/home/(ユーザー名)/.ssh/authorized_keys」のファイルのパーミッションが「600」であること
Synology NASはデフォルトでこのような権限にはなっていないので、変更してあげる必要がある。
なお、上記のルールはsshd
のソースコードレベルで実装されているので、SSH設定ファイル(/etc/ssh/sshd_config
)には直接「ディレクトリやファイルの権限」を指定する項目はないので、ハマりやすい。
設定方法としては、Synology NASの管理者権限を持つユーザでSSH接続して設定する。
# GitLabサーバ等 -> NAS へSSH
ssh <NAS管理者権限ユーザ>@<NASのIPアドレス>
# rootユーザへ昇格
sudo su -
# 作業ディレクトリ移動
cd /var/services/homes
# 作業前権限確認
ll | grep gitlab_backup
# -> drwx--x--x+ 2 gitlab_backup users 4096 Dec 30 17:57 gitlab_backup
# NAS上のユーザホームディレクトリの権限を700へ
chmod 700 /var/services/homes/gitlab_backup/
# 作業後権限確認
ll | grep gitlab_backup
# -> drwx------ 2 gitlab_backup users 4096 Dec 30 17:57 gitlab_backup
次に、.ssh
ディレクトリの作成を行う
# 作業ディレクトリ移動
cd /var/services/homes/gitlab_backup/
# .sshディレクトリ作成
mkdir -m 700 .ssh
# .ssh所有者変更
chown gitlab_backup:users .ssh
# 作業後確認
ll | grep ssh
# -> drwx------ 2 gitlab_backup users 4096 Dec 31 00:49 .ssh
次に、authorized_keys
ファイルの作成を行う
# 作業ディレクトリ移動
cd /var/services/homes/gitlab_backup/.ssh
# authorized_keys作成
touch authorized_keys
# 権限変更
chmod 600 authorized_keys
# 所有者変更
chown gitlab_backup:users authorized_keys
# 作業後確認
ll
# -> -rw------- 1 gitlab_backup users 0 Dec 31 00:55 authorized_keys
1-6. [Synology NAS] gitlab_backup
ユーザのSSH接続許可設定
NASで/etc/passwd
を確認すると、
# cat /etc/passwd | grep gitlab
gitlab_backup:x:1044:100:gitlabバックアップ用ユーザ:/var/services/homes/gitlab_backup:/sbin/nologin
のように、ユーザログインシェルがnologin
となっており、SSH接続でのユーザログインが拒否されています。なので、gitlab_backup
ユーザのシェルを/bin/sh
に変更してあげます。
# vimで編集
vim /etc/passwd
# (編集前)
# gitlab_backup:x:1044:100:gitlabバックアップ用ユーザ:/var/services/homes/gitlab_backup:/sbin/nologin
# (編集後)
# gitlab_backup:x:1044:100:gitlabバックアップ用ユーザ:/var/services/homes/gitlab_backup:/bin/sh
1-7. 動作確認
ここまでの設定で、外部からNASへgitlab_backup
ユーザでSSH接続が可能となるはずなので、GitLabサーバ等から接続確認を実施する。
ssh gitlab_backup@<NASのIPアドレス>
2. GitLabサーバのrsync設定
2-1. [GitLab] gitlab_backupユーザの作成
GitLabが動作するLinuxにも、バックアップ用のユーザgitlab_backup
ユーザを作成する。(名前はNASで作成したユーザ名と合わせる必要は無い)
adduser gitlab_backup
passwd gitlab_backup
2-2. [GitLab] SSHキー生成
NASへはSSHキーによるrsync接続を実施するため、作成したgitlab_backup
ユーザでログインしてSSHキーを生成する
su - gitlab_backup
ssh-keygen -t rsa -b 4096 -C "gitlab_backup@synologynas"
2-3. [GitLab] SSH公開鍵を登録
作成したSSH公開鍵を登録する。GitLabサーバから、ssh-copy-id
コマンドで登録を実施する
ssh-copy-id -i ~/.ssh/id_rsa.pub gitlab_backup@<NASのIPアドレス>
- 初回はパスワードを求められるので、nasで作成した
gitlab_backup
ユーザのパスワードを入力 - 成功すると、nasの
gitlab_backup
ユーザのホームディレクトリ配下の.ssh/authorized_keys
に公開鍵が追加される
ここまできたら、GitLabサーバからNASへ、SSHキーによるSSH接続が可能となるので、動作確認する。
ssh -i ~/.ssh/id_rsa gitlab_backup@<NASのIPアドレス>
2-4. [GitLab] rsyncの動作確認
(sshキーを用いた)SSH接続ができるようになると、sshキーを用いたrsyncが利用できるようになるということなので、動作確認を実施する。
rsync -avz --dry-run -e "ssh -i ~/.ssh/id_rsa" <転送元ファイル> gitlab_backup@<NASのIPアドレス>:/volume1/gitlab_backup/
-a
: アーカイブモード(パーミッションやタイムスタンプを保持)-v
: 詳細表示モード-z
: 転送時にデータを圧縮-e
: リモートシェル(SSHなど)を指定--dry-run
: 実際に転送せずシミュレーション
3. GitLabサーバのバックアップ設定
さて、ここまででGitLabサーバ->NASへのrsyncによるファイル転送が可能となったので、ここからはGitLabのバックアップ設定をしていく。
3-1. GitLabバックアップ設定
GitLabの設定ファイル/etc/gitlab/gitlab.rb
を編集し、バックアップ設定を行う。
# バックアップの保存場所
gitlab_rails['backup_path'] = "/var/opt/gitlab/backups"
# バックアップ保持期間(7日間)
gitlab_rails['backup_keep_time'] = 604800 # 7日 = 604800秒
変更を反映する。
gitlab-ctl reconfigure
3-2. crontab編集
crontabを編集
crontab -e
以下を追加
0 12 * * * /opt/gitlab/bin/gitlab-backup create && tar -czf /var/opt/gitlab/backups/gitlab-config-$(date +\%Y\%m\%d).tar.gz /etc/gitlab /etc/ssl /etc/gitlab/trusted-certs && rsync -avz -e "ssh -i /home/gitlab_backup/.ssh/id_rsa" /var/opt/gitlab/backups/ [email protected]:/volume1/gitlab_backup/ && rm -f /var/opt/gitlab/backups/*
記載できたら、内容を確認する。
crontab -l
これで、「毎日PM12時にgitlabのバックアップを取得してNASに転送する」というのが実現された。
4. NASのgitlab_backupディレクトリのバージョン管理
このままだと、永遠にバックアップデータが溜まり続けてしまうので、世代管理を行う。
4-1. [Synology NAS] スクリプト作成
gitlab_backup
ユーザディレクトリにスクリプトを作成する。
# ディレクトリ作成
mkdir /var/services/homes/gitlab_backup/Scripts
# スクリプト作成
touch /var/services/homes/gitlab_backup/Scripts/clean_old_backups.sh
スクリプト内容は
#!/bin/bash
BACKUP_DIR="/volume1/gitlab_backup"
MAX_FILES=7
# バックアップファイルを古い順にリストアップし、指定数以上なら削除
ls -t $BACKUP_DIR | grep 'gitlab_backup' | tail -n +$(($MAX_FILES + 1)) | while read FILE; do
echo "Deleting old backup: $FILE"
rm -f $BACKUP_DIR/$FILE
done
# configバックアップファイルを古い順にリストアップし、指定数以上なら削除
ls -t $BACKUP_DIR | grep 'gitlab-config' | tail -n +$(($MAX_FILES + 1)) | while read FILE; do
echo "Deleting old backup config: $FILE"
rm -f $BACKUP_DIR/$FILE
done
スクリプトの実行権限付与
chmod +x clean_old_backups.sh
4-2. [Synology NAS] タスクスケジューラへ登録
コントロールパネル > タスクスケジューラ > 作成 > 予約タスク > ユーザー指定のスクリプト
から、作成したスクリプトを登録する。
実行ユーザはgitlab_backup
開始時刻はバックアップ開始が12時なので13時とか。
作成したスクリプトを指定する。
終わり
自動でバックアップが取れ始められて嬉しい。NASのIPアドレスが変更されたらGitLabサーバのcron設定変えないといけないのは忘れそう。ホスト名でアクセスできるようにした方がいいんかな?けれど、自宅でDNSサーバ立てるのも運用が面倒だしみんなどうしてるんだろう。