内藤 裕二/ 2018年 10月 5日/ 技術

はじめに

本記事は、Qiita上で2018/3/14に初公開した記事を転記したものです。

概要

社内向けにさくらのVPS上での、下記構成のリポジトリサーバ構築メモ
前回の続き

作成したスクリプトはGitHubからどうぞ

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

GitLabバックアップ設定

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

gdriveのダウンロード

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

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での認証

sudo /usr/local/bin/gdrive list

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

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

gdriveコマンドの使用方法自体は、aviscaeruleaさん解説しているが、gdriveがちょっと古いせいか、いくつかコマンドラインオプションが古くなっていた

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

#!/bin/bash -eu

readonly TARGET=$1
readonly TARGET_FILENAME=$(basename $TARGET)
readonly TARGET_BASENAME="${TARGET_FILENAME%.<em>}"
readonly TARGET_BASEEXT="${TARGET_FILENAME##</em>.}"
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

使用法は下記

bkup_gdrive.sh <バックアップするファイルパス> <Googleドライブ上のフォルダ名>


バックアップするファイルパス

Googleドライブにアップロードするファイルのパス

Googleドライブ上のフォルダ名

アップロード先のGoogleドライブのフォルダ名。
ルート直下の1階層のみサポート

下記制限がある

  • 引数は省略できない
  • Google Driveのルート直下のフォルダにしか保存できない

GitLabのバックアップ設定

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

GitLabの設定のバックアップ

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

#!/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に出力する。

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

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

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

#!/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に出力する。

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

SSL対応

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

さくらインターネットのナレッジに解説があったので、参考にしてコマンドを導入する

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

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

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

nginx['custom_gitlab_server_config'] = "include /etc/letsencrypt/nginx.conf;"

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

sudo mkdir /etc/letsencrypt
sudo vim /etc/letsencrypt/nginx.conf
location ^~ /.well-known {
    alias /var/letsencrypt/.well-known;
}

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

sudo mkdir /var/letsencrypt

GitLabを再起動

sudo gitlab-ctl reconfigure

証明書の取得

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

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

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

GitLabに証明書を設定

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

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を通すように設定

sudo lokkit -s https

GitLabを再起動

sudo gitlab-ctl reconfigure

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

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

証明書の自動更新を設定

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

sudo crontab -e -u root
0 3 1 * * /usr/bin/certbot-auto renew --force-renew && gitlab-ctl restart

この設定だと、毎月1日の午前3時0分に証明書を更新する
適宜変更

参考URL