GitLab(Omnibus)のバックアップをAWSのS3に行う

Omnibus版のGitLabをVPS上で運用しているけどバックアップ取っていないな…と思い立ったのでAWSのS3にバックアップを取るように設定。
GitLabのマニュアルを見ると作業できるけど、整理も兼ねて。

基本的には、ここ [Upload backups to remote (cloud) storage](http://doc.gitlab.com/omnibus/settings/backups.html#upload-backups-to-remote-cloud-storage) や [Backup restore](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/raketasks/backup_restore.md) に書かれている設定を /etc/gitlab/gitlab.rb に記述して

```sh
# gitlab-ctl reconfigure
```
でGitLabの設定は完了する。

## やること

一通り設定完了になるまでの流れは

1. [AWS] AWSにバックアップデータを保存するS3バケットを作る
1. [AWS] IAMでバックアップ用のS3バケットにアクセスするユーザーを作る
1. [GitLab] /etc/gitlab/gitlab.rb にバックアップの設定を書く
1. [GitLab] バックアップを実行する
1. [GitLab] cronに設定する

こんなところ。

## AWSにバックアップデータを保存するS3バケットを作る

AWSのコンソールからなり、コマンドからなりS3上にバックアップを入れるためのバケットを作ります。
バケット名になんとなく「.」(ドット)を入れてしまうと、

> Uploading backup archive to remote storage host.backet-gitlab ... [fog][WARNING] fog: the specified s3 bucket name(chost.backet-gitlab) contains a '.' so is not accessible over https as a virtual hosted bucket, which will negatively impact performance.  For details see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/BucketRestrictions.html

と警告されます。

ここでは仮に「gitlab-backup」というバケット名にします。
(実際には、世界中で一意になるようにしなきゃいけないけど…)

AWS内のサーバからの場合、そのサーバがあるリージョンにすると転送料を気にしなくても良くなる。
それ以外なら、お好きなリージョンで。

作ったバケットのLifecycleを以下に設定しました。

```
Action on Objects
  Archive to the Glacier Storage Class 1 days after the object's creation date.
  Permanently Delete 91 days after the object's creation date
```

* アップロードから1日後にGlacier
* アップロードから91日後に完全削除

バックアップなので1日前があれば大丈夫と思いつつ、Glacierしてみたかったので(^^;


## IAMでバックアップ用のS3バケットにアクセスするユーザーを作る

[Upload backups to remote (cloud) storage](http://doc.gitlab.com/omnibus/settings/backups.html#upload-backups-to-remote-cloud-storage)

このページに書かれているポリシーを持つユーザーを作ります。

以下の形で作りました。

* User Name: gitlab-backup
* Policy Name: AllowS3-gitlab-backup

まずポリシー。
ポリシーの定義は以下("Resource"に書いているS3のARN以外は、まんまGitLabのページにあるもの)

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1412062044000",
      "Effect": "Allow",
      "Action": [
        "s3:AbortMultipartUpload",
        "s3:GetBucketAcl",
        "s3:GetBucketLocation",
        "s3:GetObject",
        "s3:GetObjectAcl",
        "s3:ListBucketMultipartUploads",
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": [
        "arn:aws:s3:::gitlab-backup/*"
      ]
    },
    {
      "Sid": "Stmt1412062097000",
      "Effect": "Allow",
      "Action": [
        "s3:GetBucketLocation",
        "s3:ListAllMyBuckets"
      ],
      "Resource": [
        "*"
      ]
    },
    {
      "Sid": "Stmt1412062128000",
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::gitlab-backup"
      ]
    }
  ]
}
```

で、次にユーザーを作成。

作成したユーザーに、上で作ったポリシーを割り当てます。

この時に生成された *Access Key ID* と *Secret Access Key* をダウンロードなりコピペなりで確保しておきます。

## /etc/gitlab/gitlab.rb にバックアップの設定を書く

/etc/gitlab/gitlab.rb を編集します。

以下の内容がコメントアウトされた状態にあるので、コメントアウトを解除して設定を記述します。

```rb:gitlab.rb
gitlab_rails['backup_upload_connection'] = {
 'provider' => 'AWS',
 'region' => 'us-west-2', # リージョンを指定
 'aws_access_key_id' => 'AKIxxxxxxxxxx', # IAMでユーザーを作った時のアクセスキーID
 'aws_secret_access_key' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx' # IAMでユーザーを作った時のシークレットアクセスキー
}
gitlab_rails['backup_upload_remote_directory'] = 'gitlab-backup'
```

記述が完了したら

```sh
# gitlab-ctl reconfigure
```

で設定を反映。


## バックアップを実行する

```sh
# gitlab-rake gitlab:backup:create
Dumping database ...
Dumping PostgreSQL database gitlabhq_production ... [DONE]
done
Dumping repositories ...
 * repository ... [DONE]
done
Dumping uploads ...
done
Dumping builds ...
done
Dumping artifacts ...
done
Dumping lfs objects ...
done
Creating backup archive: 1458963192_gitlab_backup.tar ... done
Uploading backup archive to remote storage gitlab-backup ... done
Deleting tmp directories ... done
done
done
done
done
done
done
Deleting old backups ... skipping
```

*Uploading backup archive to remote storage gitlab-backup ... done* があれば、正常にS3に対してアップロードが完了。

S3のコンソールで確認するとファイルが作られている。


## cronに設定する

```crontab:cron
0 6 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create CRON=1
```

CRON=1を設定することによってエラー以外の出力が抑えられるそうです。
GitLabのページではAM4:00に実行するようになってましたが、AM4:00だと他のバッチも動いているのと夜遅くまで作業していると、たまにAM4とかなりそうなので、そんなときに寝てるであろうAM6に設定(^^;

この状態で、明日以降
* S3に上げたバックアップがGlacierになるか？
* AM6:00にバックアップ処理が実行されファイルがS3に上がるか？

を確認して、OKであれば完了です。