さくらのVPSにGitLabを構築する - その2

# 概要

社内向けにさくらのVPS上での、下記構成のリポジトリサーバ構築メモ  
[前回](https://qiita.com/rot-z/items/763c87ca0f6ef0dc22ea)の続き  

作成したスクリプトは[GitHub](https://github.com/rot-z/GitLabBackupScripts)からどうぞ  

- さくらのVPS使用(RAM 2GB, HDD 200GB)
- CentOS 6.9 (Final)
- GitLab CE Omnibus ver.10.5.2
- 通知用メールはGMailを使用
- リポジトリおよびデータのバックアップはGoogle Driveを使用
- SSLに対応するため、Let's Encryptのサーバ証明書を使用**（WIP）**

# GitLabバックアップ設定

GitLab用に作成したアカウントのGoogle Driveにそのままバックアップすることにする

## gdriveのダウンロード

[gdrive](https://github.com/prasmussen/gdrive)を導入する  
ここでは、/usr/local/bin/gdriveに配置  
wget対象のURLはちょいちょい変わるので、開発者のprasmussenさんのリポジトリで確認すること  

```bash
sudo wget -O gdrive https://docs.google.com/uc?id=0B3X9GlR6EmbnQ0FtZmJJUXEyRTA&export=download
sudo mv gdrive /usr/local/bin/
sudo chmod +x /usr/local/bin
```

## Google Driveでの認証

```bash
sudo /usr/local/bin/gdrive list
```

コマンドをたたくとブラウザでURLにアクセスして認証キーを入れろ、と言われるので、その通りにする  

## バックアップ用スクリプトを作成

gdriveコマンドの使用方法自体は、[aviscaeruleaさん](https://qiita.com/aviscaerulea)が[解説している](https://qiita.com/aviscaerulea/items/53123ce5b79c80e31a71)が、gdriveがちょっと古いせいか、いくつかコマンドラインオプションが古くなっていた  

参照URLにあったスクリプトではうまく動作しなかったので、実験しながら似たようなスクリプトを作成  
（bashのスクリプトを初めて書いたのでコマンドフルパスで埋まってたりするけど、ご愛敬。）  

```bash:bkup_gdrive.sh
#!/bin/bash -eu

readonly TARGET=$1
readonly TARGET_FILENAME=$(basename $TARGET)
readonly TARGET_BASENAME="${TARGET_FILENAME%.*}"
readonly TARGET_BASEEXT="${TARGET_FILENAME##*.}"
readonly GDRIVE_DIR=$2
readonly KEEP_DAYS=10

if [ ! -e $TARGET ]
then
    echo "File not found: $TARGET" >&2
    exit 1
fi

renice -n 10 -p $$ > /dev/null

### Find/Create Backup folder
GDRIVE_DIR_ID=$(/usr/local/bin/gdrive list --no-header --query "trashed=false and mimeType='application/vnd.google-apps.folder' and name='$GDRIVE_DIR'" | awk '{print $1}')
echo "$GDRIVE_DIR -> $GDRIVE_DIR_ID"

if [ -z "$GDRIVE_DIR_ID" ]
then
    echo "Try to create folder: $GDRIVE_DIR"
    GDRIVE_DIR_ID=$(/usr/local/bin/gdrive mkdir "$GDRIVE_DIR" | awk '{print $2}')
    echo "$GDRIVE_DIR -> $GDRIVE_DIR_ID"
    if [ -z "$GDRIVE_DIR_ID" ]
    then
        echo "Folder not created: $GDRIVE_DIR" >&2
    fi
fi

### Upload Encrypted file
/usr/local/bin/gdrive upload --parent $GDRIVE_DIR_ID --name ${TARGET_BASENAME}_`date +%Y%m%d-%H%M%S`.${TARGET_BASEEXT} $TARGET

### House Keeping
LIMIT_TIMESTAMP=$(date -d "$KEEP_DAYS days ago" +%Y-%m-%dT%H:%M:%S)

/usr/local/bin/gdrive list --no-header --query "'$GDRIVE_DIR_ID' in parents and modifiedTime < '$LIMIT_TIMESTAMP'" | while read ln
do
    ITR_ID=$(echo $ln | awk '{print $1}')
    ITR_DATE=$(echo $ln | awk '{print $(NF-1),$NF}')

    echo "ID: $ITR_ID, DATE: $ITR_DATE"
    /usr/local/bin/gdrive delete $ITR_ID
done
```
使用法は下記  

```bash
bkup_gdrive.sh <バックアップするファイルパス> <Googleドライブ上のフォルダ名>
```
<DL>
<DT>バックアップするファイルパス</DT>
<DD>Googleドライブにアップロードするファイルのパス</DD>
<DT>Googleドライブ上のフォルダ名</DT>
<DD>アップロード先のGoogleドライブのフォルダ名。<br />ルート直下の1階層のみサポート</DD>
</DL>

下記制限がある  
- 引数は省略できない
- Google Driveのルート直下のフォルダにしか保存できない

## GitLabのバックアップ設定

GitLabでバックアップが必要なのは、設定とデータ部分  
作成したスクリプトを使用して、両方をGoogle Driveにバックアップする  

### GitLabの設定のバックアップ

面倒なので、/etc/gitlab配下をzip圧縮  
本当は暗号化とかした方がいいのかもだけど、ここではひとまずおいておく  
先ほど作成したbkup_gdrive.shを使用して、Google Driveにアップロードするスクリプトを作成  

```bash:bkup_gitlab_config.sh
#!/bin/bash -eu
echo "$(date "+%Y-%m-%d %H:%M:%S") ---------- START backup gitlab config ----------"

readonly TARGET_FILENAME=$(date "+etc-gitlab-%s.tgz")

# Backup GitLab config folder
tar czf $TARGET_FILENAME -C / etc/gitlab

# Upload Backup file to Google drive
/usr/local/bin/bkup_gdrive.sh $TARGET_FILENAME bk_gitlab_config

# Delete Backup file
rm $TARGET_FILENAME

echo "$(date "+%Y-%m-%d %H:%M:%S") ---------- END backup gitlab config ----------"
```
crontabを使用して、毎日午前2時に上記スクリプトを実行するように設定  
標準出力は動作ログとして、/var/log/backups/bkup_gitlab_config.logに出力する。

```bash
sudo crontab -e -u root
```
```crontab
0 2 * * * /usr/local/bin/bkup_gitlab_config.sh >> /var/log/backups/bkup_gitlab_config.log
```

### GitLabのデータのバックアップ

設定と同様、GitLabのデータをバックアップするスクリプトを作成  

```bash:bkup_gitlab_data.sh
#!/bin/bash -eu
echo "$(date "+%Y-%m-%d %H:%M:%S") ---------- START backup gitlab data ----------"

# Create GitLab Backup file
gitlab-rake gitlab:backup:create

# Get target file name
readonly TARGET_FILENAME=`ls -lt /backups/gitlab/app/* | head -n 1 | awk '{print $NF}'`

# Upload Backup file to Google drive
/usr/local/bin/bkup_gdrive.sh $TARGET_FILENAME bk_gitlab_data

echo "$(date "+%Y-%m-%d %H:%M:%S") ---------- END backup gitlab data ----------"
```
crontabを使用して、毎日午前2時10分に上記スクリプトを実行するように設定。  
標準出力は動作ログとして、/var/log/backups/bkup_gitlab_data.logに出力する。

```bash
sudo crontab -e -u root
```
```crontab
10 2 * * * /usr/local/bin/bkup_gitlab_data.sh >> /var/log/backups/bkup_gitlab_data.log
```

# SSL対応

## Let's Encryptの証明書取得用のコマンドを導入  

さくらインターネットのナレッジに[解説](https://knowledge.sakura.ad.jp/5573/)があったので、参考にしてコマンドを導入する  

```bash
sudo curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
sudo chmod 700 /usr/bin/certbot-auto
```

## webrootで証明書を取得するための準備

GitLabの設定ファイルを編集し、nginxの特殊設定を埋め込む  

```ruby:/etc/gitlab/gitlab.rb
nginx['custom_gitlab_server_config'] = "include /etc/letsencrypt/nginx.conf;"
```

埋め込んだnginx用の特殊設定ファイルを作成  

```bash
sudo mkdir /etc/letsencrypt
sudo vim /etc/letsencrypt/nginx.conf
```

```bash:/etc/letsencrypt/nginx.conf
location ^~ /.well-known {
    alias /var/letsencrypt/.well-known;
}
```

Let's Ecryptのwebroot認証に必要なフォルダの作成  

```bash
sudo mkdir /var/letsencrypt
```

GitLabを再起動

```bash
sudo gitlab-ctl reconfigure
```

## 証明書の取得

certbot-autoを使用して証明書を取得

```bash
sudo certbot-auto certonly --webroot -w /var/letsencrypt -d gitlab.example.com
```

**gitlab.example.com**の部分を自身のドメイン名に変更するのを忘れずに  

## GitLabに証明書を設定

GitLabの設定ファイルを修正  
3箇所ある、**gitlab.example.com**の部分を自分のドメインに変更するのを忘れないように注意！  

```ruby:/etc/gitlab/gitlab.rb
external_url 'https://gitlab.example.com'
nginx['redirect_http_to_https'] = true
nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.example.com/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.example.com/privkey.pem"
```

httpsを通すように設定  

```bash
sudo lokkit -s https
```

GitLabを再起動

```bash
sudo gitlab-ctl reconfigure
```

ブラウザで下記の確認を行う

1. httpsでアクセス可能なこと
2. httpでアクセスするとhttpsにリダイレクトされること

## 証明書の自動更新を設定

crontabにて定期的に証明書を更新するように設定する

```bash
sudo crontab -e -u root
```

```crontab
0 3 1 * * /usr/bin/certbot-auto renew --force-renew && gitlab-ctl restart
```
この設定だと、毎月１日の午前３時０分に証明書を更新する 
適宜変更   

# 参考URL

- [README.md - gdrive](https://github.com/prasmussen/gdrive/blob/master/README.md)
- [遠隔地バックアップ（gdrive）](https://centossrv.com/gdrive.shtml)
- [GitLabの定期バックアップ設定](http://inaba.hatenablog.com/entry/2016/12/24/051330)
- [サーバのバックアップファイルを Google ドライブに退避させる](https://qiita.com/aviscaerulea/items/53123ce5b79c80e31a71)
- [GitLab Omnibus package の SSL 証明書を Let's Encrypt で取得する](https://qiita.com/yuuAn/items/09a434d3f6cffa31101e)
- [Let’s EncryptのSSL証明書で、安全なウェブサイトを公開](https://knowledge.sakura.ad.jp/5573/)