Go インストールから go get まで

とある OSS のツールが便利だと聞き、試しに使ってみようと思ったところ Go のパッケージ管理コマンドでインストールができるという情報が記載されていました。
今まで Go には触れたことがなかったので、Go 環境のセットアップから Hello world、パッケージインストールまでを一通りやってみます。

検証環境

インストール

ダウンロードと展開

Go 公式の Downloads から Linux 用の URL を取得します。

バイナリをダウンロードして /usr/localgo ディレクトリを展開します。

$ curl -O https://dl.google.com/go/go1.11.linux-amd64.tar.gz
$ sudo tar -xzf go1.11.linux-amd64.tar.gz -C /usr/local

PATH 設定

ユーザの .bash_profile 末尾に環境変数を追加します。
なお、新しく追加する GOPATH は Go のワーキングディレクトリとなります。

export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin

追加した環境変数を読み込み、go コマンドを実行してパスが通っていることを確認します。

$ source ~/.bash_profile
$ go version
go version go1.11 linux/amd64

Hello world

以下の内容で hello.go を作成します。
また、Go の規約ではインデントはハードタブ (\t) を使用することになっています。

package main

import "fmt"

func main() {
    fmt.Printf("hello, world\n")
}

ソフトタブ (\s) でコーディングしてしまっても、フォーマット用コマンドで自動整形してくれます。

$ go fmt hello.go

go runソースコードを実行します。

$ go run hello.go
hello, world

パッケージインストール

ghkw インストール

今回は ghkw (GitHub KeyWord) という GitHub 上のソースコードに出現する単語数を調べてくれるツールを使用してみます。

$ go get -u github.com/kyoshidajp/ghkw

インストールに成功すると、GOPATH のワーキングディレクトリに srcbin が作成され、以下のようにファイルが配置されます。

$ ls go/src/github.com/kyoshidajp/ghkw/
Changes  cli_test.go  Gopkg.toml  main.go   README.md
cli.go   Gopkg.lock   LICENSE     Makefile  search_term.go

$ ls go/bin/
ghkw

ghkw 実行

bin 配下のバイナリが実行ファイルとなっているので、適当に引数を与えて実行します。
通知関連の機能を実装しているときに命名に迷った notify と notification を引数に与えて検索を行ってみます。

$ ./go/bin/ghkw notify notification
| RANK |   KEYWORD    |    TOTAL    |
|------|--------------|-------------|
|    1 | notify       | 143,190,506 |
|    2 | notification |  90,243,988 |

件数が多い順に結果が表示されました。
使い所にもよりますが、命名に迷ったときなどに参考になるかもしれません。

こういったパッケージの利用も容易にできるということが分かったので、今後は積極的に Go 製のツールも使っていきたいと思います。

参考サイト

Yum でインストールした Tomcat をバイナリでインストールし直す

以前構築した GitBucket の Tomcat ですが、構築後のバージョンアップをしばらく怠っていました。
脆弱性もいくつか修正されているため、今回は最新版へのバージョンアップを行ってみます。

また、簡単という理由で構築時に yum でインストールをしていましたが、yumリポジトリには脆弱性対応済みの最新版がありません。
なので、一旦 yum パッケージのアンインストールを行った後、公式サイトの tar.gz を展開して再インストールを行っていきます。

検証環境

事前準備とアンインストール

可能ならば仮想マシンのスナップショットを作成しておきます。

tomcat サービスを停止させ、自動起動を無効化させます。

# systemctl stop tomcat
# systemctl disable tomcat

アプリケーションの退避

この環境では Tomcat ディレクトリ配下に Git リポジトリと GitBucket のアプリケーションが配置されているため、適当なディレクトリを作成して退避させておきます。
今回は /tmp/tomcat_update というディレクトリを作成して退避させます。

# mkdir /tmp/tomcat_update && cd $_
# mv /usr/share/tomcat/.gitbucket/ ./
# mv /usr/share/tomcat/webapps/gitbucket.war ./
# ls -a /tmp/tomcat_update/
.  ..  .gitbucket  gitbucket.war

server.xmlweb.xml などの設定ファイルも消してしまうため、設定値に変更がある場合は設定ファイルも控えておきましょう。

アンインストール

退避が完了したら yum でインストールした旧バージョンの tomcat をアンインストールしていきます。
アンインストール対象のパッケージを洗い出し、全て削除します。

# yum list installed | grep tomcat
Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
tomcat.noarch                      7.0.76-2.el7                   @base
tomcat-el-2.2-api.noarch           7.0.76-2.el7                   @base
tomcat-jsp-2.2-api.noarch          7.0.76-2.el7                   @base
tomcat-lib.noarch                  7.0.76-2.el7                   @base
tomcat-servlet-3.0-api.noarch      7.0.76-2.el7                   @base

# yum remove tomcat tomcat-el-2.2-api tomcat-jsp-2.2-api tomcat-lib tomcat-servlet-3.0-api

Tomcat 用のディレクトリも削除します。

# rm -rf /usr/share/tomcat

新バージョンのインストール

以前 yum でインストールしたときにユーザが作られていますが、新規インストールの場合には新しくユーザを追加します。

# useradd -s /sbin/nologin tomcat

ダウンロードと展開

先ほど作成した作業用ディレクトリでバイナリのダウンロードと展開を行い、tomcat ディレクトリに移動させます。
Apache Tomcat 7 Software Downloads から tomcat をダウンロードします。

# cd /tmp/tomcat_update
# curl -O http://ftp.riken.jp/net/apache/tomcat/tomcat-7/v7.0.90/bin/apache-tomcat-7.0.90.tar.gz
# tar -xzvf ./apache-tomcat-7.0.90.tar.gz
# mv /tmp/tomcat_update/apache-tomcat-7.0.90 /usr/share/tomcat
# chown -R tomcat:tomcat /usr/share/tomcat

バージョン確認のスクリプトを実行すると、7.0.90 であることを確認できます。

# /usr/share/tomcat/bin/version.sh
Using CATALINA_BASE:   /usr/share/tomcat
Using CATALINA_HOME:   /usr/share/tomcat
Using CATALINA_TMPDIR: /usr/share/tomcat/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /usr/share/tomcat/bin/bootstrap.jar:/usr/share/tomcat/bin/tomcat-juli.jar
Server version: Apache Tomcat/7.0.90
Server built:   Jul 2 2018 17:05:37 UTC
Server number:  7.0.90.0
OS Name:        Linux
OS Version:     3.10.0-514.el7.x86_64
Architecture:   amd64
JVM Version:    1.8.0_151-b12
JVM Vendor:     Oracle Corporation

Tomcat サービス化

startup.sh でも開始できますが、systemctl コマンドでサービスの起動・停止を操作したいので systemd ユニットファイルを作成します。

# cat <<EOS  >/usr/lib/systemd/system/tomcat.service
[Unit]
Description=Apache Tomcat 7
After=network.target

[Service]
User=tomcat
Group=tomcat
Type=oneshot
ExecStart=/usr/share/tomcat/bin/startup.sh
ExecStop=/usr/share/tomcat/bin/shutdown.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOS

systemctl コマンドで tomcat サービスのステータスが確認できるようになっています。

# systemctl daemon-reload
# systemctl status tomcat

リポジトリとアプリケーションの復旧

退避しておいたリポジトリとアプリケーションを tomcat ディレクトリに戻します。

# mv /tmp/tomcat_update/.gitbucket /usr/share/tomcat/
# mv /tmp/tomcat_update/gitbucket.war /usr/share/tomcat/webapps/

アプリケーション開始

停止させていた GitBucket アプリケーションと Web サーバを起動します。

# systemctl start tomcat
# systemctl enable tomcat

アプリケーション (GitBucket) にアクセスし、リポジトリに対する操作などが問題なく行えることが確認できたら完了です。

参考サイト

社内の Subversion を Git に移行した話

検証時の手順やメモばかりを記事にしていましたが、たまには仕事の話を日記的に書いてみます。

上司から「部署の Subversion を Git に移行したいんだけど、できそう?」という話を持ちかけられて、勢いで「やってみます!」と答えてから一ヶ月ほど一人で移管プロジェクトを回していました。
若手の安い単価とはいえ一人月も好きに使って良いと言われたので、それなりに計画を立ててやらねばなりません。色んな案件を転々としてきてまともな業務知識が身に付いていない若造ですが、なんちゃって要件定義から運用計画まで一人でやってみましたので、ここに残しておきます。

やったこと一覧

  • Subversion 調査
  • OSS 調査・選定
  • Git サーバ構築検証
  • データベース構築
  • リポジトリ移行
  • HTTPS 化対応
  • クライアントツール検討
  • 本番環境構築
  • SSL 証明書と正引きレコード追加
  • 自動バックアップの実装
  • メール通知の設定
  • ブランチ運用手法の調査
  • 部内展開・教育
  • 本番稼働に向けて調整

構築については以前の記事で書いていますので、今回の記事では調査・選定や移行部分について触れていきます。

現状のヒアリング・調査など

サーバの運用・管理について

  • どこかの物理ホストの Windows サーバで稼働している
  • プライベートネットワーク内にいるが実体がどこにあるのか不明
  • 誰も管理していないし、管理者が分からない
  • このままではサーバ老朽化に引き摺られてソースコードも全て道連れになる
  • 一応バックアップは取っているがリストア手順が不明

現状の運用に正直がっかりしてしまいましたが、がっかりしていても前に進めないので解決に向けて検討していきます。

Git に対しての要望

  • SVN 上のソースコードをそのまま Git に移行したい
  • できればコミット履歴も引き継ぎたい
  • Pull Request の機能が欲しい
  • あとは Subversion で出来ていたことが大体できれば良い

部署内の調査をしたところ、誰も Git を触ったことがなく「プルリクっていうのが便利らしいね」くらいの認識でした。
特に書き連ねる意味はありませんが、個人的な要望はこのあたりです。

  • 何か OSS 使ってクラウド運用してみたい
  • git-flow のようなブランチ運用がしたい
  • ソースコードを ZIP でダウンロードできると楽
  • 構築面、運用面で簡単かつ慣れている Linux 環境だと助かる

Git 移行可否についての調査

git-svn というコマンドを使えば簡単にできそうなことが分かりました。 (フラグ)

Subversion 調査

開発をするときに Eclipse プラグイン (Subversive) 経由でしか触ったことがなかったため、実際使われているサーバや Subversion 自体についての調査から始めました。
※ 以降、SubversionSVN と記載します。

SVN リポジトリについて

SVNリポジトリは大きく分けて以下の3要素から成ります。

  • trunk/
  • branches/
  • tags/

主に trunk 配下にソースコードが入っていき、branches と tags は補助的に利用するようです。
Git のブランチ・タグとは使い方が異なることと SVN で特に使用していなかったことから、今回は trunk 配下のソースコードを引き出すことのみ考えていきます。

社内で運用中の SVN について

現状使用している SVN リポジトリは trunk ディレクトリ配下に全てのプロジェクトが入っている構成になっていました。
プロジェクトやプロダクトごとにリポジトリを持つのが正しい姿かと思っていましたが、実際のところどのくらいの粒度でリポジトリを作るのが理想なのでしょうか。

/
|-- branches/
|-- tags/
|-- trunk/
    |-- PROJECT_A
    |-- PROJECT_A_20150401
    |-- PROJECT_A_bk
    |-- PROJECT_A_old
    |-- PROJECT_B
    |-- PROJECT_C
    |-- ...

上記のような構成になってしまっていたため、プロジェクトのディレクトリをひとつのリポジトリとして分割してクローンしていく必要があります。
バージョン管理とは一体……と思ってしまう名前のディレクトリもいくつかありましたが、フルバックアップしておきたい気持ちも分からなくもないので触れずに全移行します。

OSS 調査・選定

Git ホスティングのサービスをいくつか調査しました。
箇条書きのメモで見づらくなっていますが、念のため残しておきます。

GitHub と Bitbucket についてはオンプレミス版は有償のため、評価対象外としています。

候補 1. GitLab

  • 実行環境
    • Ruby on Rails
      • ruby, nginx, unicorn, chef, postgresql, redis など必要なものは全て同梱
      • gitlab-ctl start で全部が動く
    • ハード要件
      • CPU は 2 コア以上を推奨
      • メモリは 1GB 必須、4GB 以上を推奨
  • OSS 的な側面
    • オンプレ Git サービスといったら GitLab というくらい情報が多い気がする
    • 開発団体が存在している
    • 月次でバージョンアップされている
  • 導入に際して
    • インストールに30〜40分かかり、スクリプトで何やってるか分からなくて不安
    • 組み込みのモジュールが多すぎて環境を汚しそう
    • 起動しても何故かエラー連発でログインすらできない
    • ハード要件を満たしていても動作が重く操作が満足にできない
    • 技術系ブログを見た感じだと挫折して GitBucket に流れ着いてる人がちらほら

候補 2. GitBucket

  • 実行環境
    • Scala
    • H2 という組み込みデータベースを使用
      • H2 はデータの保全性に問題があり、公式は外部 DB の利用を推奨している
      • MySQLPostgreSQL を公式サポート
      • DB にはアカウントやグループなどの情報を保存
  • OSS 的な側面
    • 日本人が開発しているので公式ブログからの情報が得やすい
    • GitBucket 自体は GitHub で管理されている
    • GitHub から指摘を受けてデザイン変更した過去があり、それ以降 UI が変わった
    • 検索したときに Bitbucket の情報ばかり出てきて困る
  • 導入に際して
    • ダウンロードした war ファイルを配置して Tomcat を動かすだけなので簡単
    • JVMTomcat であれば部内でも慣れている方が多い

結果

GitBucket にしました。
GitLab は Web サーバや DB サーバが全て同梱とのことで、どうやって管理していったら良いのか見当つかず、運用を考えたときに躓いてしまいそうなので避けてしまいました。

また、私の部署は Java の経験者が多く、何かあったときに少しでも理解がある人に任せられる(かも)という保身的な考えからも JVM 環境で実行できる GitBucket が無難かと思い採用に至りました。

リポジトリ移行

先ほど挙げた git-svn を用いて移行します。
基本的には以下のような流れです。

  1. git-svn コマンドで SVN リポジトリを Git リポジトリとしてローカルにクローン
  2. GitBucket 上に空のリポジトリを作成する
  3. 2 で作成した空のリモートリポジトリにローカルリポジトリをプッシュ

たったそれだけかといった感じですがいくつかハマった点もありますので、そちらは後ほど紹介します。

1. SVNリポジトリをクローン

Git Bash を開き、以下のコマンドで SVN からリポジトリをクローンします。

$ git svn clone http://xxx.xxx.xxx.xxx:xxxx/svn/trunk/PROJECT_A

もしくは git svn fetch + git svn rebaseリポジトリをクローンします。

$ mkdir ./PROJECT_A && cd $_
$ git svn init http://xxx.xxx.xxx.xxx:xxxx/svn/trunk/PROJECT_A
$ git svn fetch
$ git svn rebase

git svn clone ではタイムアウトなどが原因で失敗する場合がありますが、git svn fetch ではエラーになっても次のフェッチ時に途中からリビジョンを取得することができます。
また、trunk/ 配下に各プロジェクトが展開されていて不安でしたが、普通に一つのリポジトリとしてクローンしてくることができました。

SVN リポジトリの総コミット数は 10,000 件ほどあり、そのうち 5,000 コミットほどを占めている大きなディレクトリのクローンは 4 時間ほどかかりました。
ネットワーク環境が悪いのかは分かりませんが、終始この調子だったため、全プロジェクトをクローンするだけでほぼ丸一日潰れてしまいました。スクリプトで自動化をしていなければもっと酷いことになっていたと思います。

最新リビジョンのみをクローン (非推奨)

覚え書きとして記載しておきます。
速度は速いですが、HEAD のソースコードのみ取得するため差分の履歴は引き継げません。
過去のコミット履歴が不要であればこちらを使用しても良いかもしれません。

$ git svn clone -r HEAD http://xxx.xxx.xxx.xxx:xxxx/svn/trunk/PROJECT_A

2. Git にリモートリポジトリを作成する

ブラウザから GitBucket アプリケーションにログインし、プロジェクト単位で New Repository をしていきます。
操作については割愛します。

3. Git リモートリポジトリにプッシュする

GitBash に戻り、リモート環境 (GitBucket) の空リポジトリ情報を追加してプッシュします。

$ git remote add origin http://XXX.XXX.XXX.XXX/gitbucket/git/GROUP/PROJECT_A.git
$ git push -u origin --all

移行時にハマったこと

空のディレクトリは保管できない

「Git からクローンしてきたプロジェクトがビルドできない」という報告を受けて気付くことができました。

Git はファイルのバージョンを管理する仕組みであるため、ディレクトリだけ存在していても管理対象として認識することができません。 アプリケーションによっては tmp や cache といったディレクトリを使用している可能性がありますので、0 バイトのダミーファイルを格納するなどして回避する必要があります。
Git の仕様ではありませんが .gitkeep という 0 バイトファイルを作成する慣習があるようですので、それに倣ってディレクトリとファイルを再度コミットしました。

それほど数は多くなかったため、find . -type d -empty でリストアップしたディレクトリに対して touch .gitkeep を連打するスクリプトを書いて解決しました。

日本語表記や半角スペースは使用できない

SVN で日本語やスペースが使われているディレクトリは、git svn clone できても git push ができませんでした。

リポジトリ、ブランチ、グループ、ユーザ などの Git の根本機能に関わる名前は URI にも使用されることがあるため、半角英数を利用するよう周知し、適当にリネームして凌ぎました。
例) Sample Project (テスト用)/Sample_Project_test/

「プロジェクト名に日本語使いたいんだけど」という要望もありましたが、「URI になるのでできません」と具体的に説明したらなんとか理解を得られました。

また、日本語表記で躓いた箇所がもう一点あります。
MySQLmy.cnf に下記を設定しておかないと日本語を POST したときにアプリ側でエラーになるので注意が必要です。早い段階で気づいていなかったら後で悲惨なことになっていました。

[mysqld]
character-set-server = utf8

この設定をしたことで、ファイル名やコミットメッセージ、レビューコメントなど無事に日本語で書けることが確認できました。

バイナリファイルの差分管理は得意ではない

移行後、バイナリファイルをコミットしていた方がいたので気づけました。

Git はプログラムのソースコードなどのテキストファイルのバージョン管理を目的としており、動画ファイルや OS イメージなどのバイナリファイルの管理は得意としていません。
リポジトリに格納することは仕組み上可能ですが、バイナリファイルでは差分を計測することができず、必要以上にサイズが膨れ上がってしまい、ディスクを圧迫することに繋がってしまいます。
アプリケーションで利用する静的ファイルなどに用途を限定し、テキストファイル以外の設計書などはなるべくファイルサーバへ保管するよう周知し、なんとか和解しました。

また、試しに CentOS のイメージファイルをプッシュをしてみたところ、プッシュはできてもクローンはできず、処理できないゴミが増えてしまっただけでした。

別の移行対象リポジトリが存在していた

移行が終わったと安心していた段階で隣の課の先輩から「○○のソースは無いんだ?」と聞かれ、もう一つ別の SVN リポジトリの存在を知りました。
これは Git どうこうではなく完全に私の調整不足が原因ですが、SVN 歴の長い先輩や上司にきちんと聞いて移行範囲を明確にするべきでした。

振り返り

一人だけのプロジェクトでしたが KPT っぽく振り返ってみます。

良かったこと

  • SVN, Git についての理解を深めることができた
  • 割り込みのタスクがほとんど無く、のびのびと調査や検証ができてストレスが無かった
  • ワイルドカード証明書の仕組みを覚えた
  • 社内 DNS の登録申請フローを覚えた
  • 未知の技術に対して積極的な人、保守的な人などの特徴が見えた

悪かったこと

  • 誰も Git を触ったことが無かったため自分の進捗の良し悪しを誰も判断できなかった
  • マージ、リベースなどのブランチ運用の学習に時間がかかってしまった
  • 部内教育用のドキュメント作成に半分くらい時間をもっていかれた
  • 導入や教育が一部投げやりで無責任だった
    • 「ドキュメント格納しておいたので見ておいてください」など
  • SVN リポジトリを切り捨てるタイミングが明確に決められなかった
    • 「慣れるまで数ヶ月平行運用していきましょう」が今になってジワジワ効いてきた

気づいたこと、改善していくこと

  • イレギュラーは必ず起きるものと思って早めに行動し、対処できる時間を残しておく
    • ビルドできない件、日本語入力の件、リポジトリが別に存在した件など
  • 業務時間内の勉強だけでは圧倒的に足りないので日常的にアンテナを張っておく
    • 今回は運良く業務時間に勉強できたがそんな恵まれた環境はまず無い
  • 新しい技術の導入に保守的な人に対してのコミュニケーションを上手くやる
    • 疑問や質問については丁寧に正しく答える。即答できなければ曖昧にせず調査する時間をもらう
  • 利用者の習熟度を上げて味方を増やしていく
    • 後輩が Git の操作のことでたくさん質問してきてくれて精神的にすごく助かった
  • ドキュメント作成がスムーズにできるように普段から人に見せられる文体でメモを書き残す
  • 顔を合わせて共有できる時間を取る
    • ドキュメント展開しました、の連絡だけでは誰も興味を持ってくれない

所感

自分の裁量で仕事が出来たのが純粋にとても楽しかったというのと、社内のみんなが知らない分野だから誰からも仕事ぶりを突っ込まれないというハラハラした気持ちが混在した面白いプロジェクトでした。
また、普段エンドのお客さんからサービスの感想など直接いただくことの無い SI 企業の末端 SE なので、誰かに使ってもらって「便利だね」と言って貰えるのは心底嬉しいなと感じました。達人たちの技術ブログの真似をして環境を整備し、出来合いのアプリを動かしただけではありますが、やってよかったと思っています。

「新しい技術に保守的な人」について触れましたが、これは悪い意味で書いたつもりは一切ありません。
システムを長い目で見たときにプロダクトのライフサイクルまで考えなければなりませんし、変更やリプレースは障害を引き起こすポイントでもあるので、慎重に考えるに越したことはないと思っています。
上手にメリットを伝えて上手に不安を取り除く、といったように人をうまくコントロールすることについても考える良い機会になりました。どこまでいっても最後には対人スキルが必要になってくるんだなぁと感じます。

あと、「アプリ書いてるときより黒い画面見てるときの方が生き生きしてるね」と先輩に言われたのが印象的でした。

以上、日記でした。

自己署名証明書の作成と HTTPS 対応

自己署名証明書(オレオレ証明書)を作成して SSL/TLS の暗号化通信を可能にします。

検証環境

  • CentOS 7.3
  • OpenSSL 1.0.1e
  • Nginx 1.12.2

自己署名証明書の作成

※ 今回扱うファイル名が紛らわしいため先に名前を定義します。

  • server.key : 秘密鍵 (CSR 作成, 署名兼用)
  • server.csr : CSR (証明書署名要求)
  • server.crt : 証明書

秘密鍵作成

OpenSSL で鍵長 2048bit の RSA 秘密鍵を作成します。

# openssl genrsa 2048 > ./server.key
Generating RSA private key, 2048 bit long modulus
.......................+++
.........+++
e is 65537 (0x10001)

CSR 作成

作成した秘密鍵を引数に CSR を作成します。
コモンネームや組織名などの入力を求められますが、今回は自己署名証明書のため、入力は全て Enter でデフォルト値を設定してしまいます。

# openssl req -new -key ./server.key > ./server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

証明書作成

CSR に先ほど作成した秘密鍵で署名し、有効期限 10 年間として証明書を作成します。

# openssl x509 -days 3650 -req -signkey ./server.key < ./server.csr > ./server.crt
Signature ok
subject=/C=XX/L=Default City/O=Default Company Ltd
Getting Private key

リダイレクトで出力した server.crt が証明書ファイルとして使用できます。

Nginx の HTTPS アクセス設定

証明書の配置とアクセス権変更

作成した秘密鍵CSR、証明書のうち、秘密鍵と証明書を Nginx で使用します。
nginx ディレクトリ配下に ssl ディレクトリを作成して格納します。

# mkdir /etc/nginx/ssl/
# cp -p ./server.key /etc/nginx/ssl/
# cp -p ./server.crt /etc/nginx/ssl/

秘密鍵と証明書のアクセス権は root の読み取りのみに限定します。

# chmod 400 /etc/nginx/ssl/server.*
# chmod 700 /etc/nginx/ssl/

設定変更

Nginx の設定ファイルを編集します。
設定の要点は以下3つです。

  • ポート 80 (HTTP) へのアクセスに対しては HTTPS にリダイレクトさせる
  • ポート 443 (HTTPS) へのアクセスは SSL 設定を有効にする
  • location 等の設定は全て SSL の server ディレクティブに記述する
# vi /etc/nginx/nginx.conf

    ...省略...

    server {
        listen      80;
        server_name localhost;

        return 301  https://$host$request_uri;
    }

    server {
        listen       443 ssl;
        server_name  localhost;

        ssl                 on;
        ssl_certificate     /etc/nginx/ssl/server.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';

        ...省略...
    }

ssl_protocolsssl_ciphers については Mozilla SSL Configuration Generator で生成される設定を利用するのが一般的なようです。

設定の文法に問題がないことをテストしてリロードします。

# nginx -t /etc/nginx/nginx.conf
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# systemctl reload nginx

ブラウザからアクセスし、HTTPS の通信ができていること、HTTP が HTTPS にリダイレクトされることを確認します。
証明書情報が正しくないためブラウザからエラーが出ますが、エラーの無視や例外追加でページを閲覧することができます。

参考サイト

GitBucket のデータベース変更

前回に引き続き GitBucket の環境改善です。

組み込みの H2 データベースでは具合が悪いとのことが公式で言及されているため、
GitBucket でサポートしている MySQL に変更します。

GitBucketをPostgreSQLやMySQLで動かす - たけぞう瀕死ブログ

GitBucketは標準では内蔵のH2という組み込みデータベースで動作しますが、4.0からはH2の代わりに外部データベースとしてPostgreSQLMySQLを使うことができるようになっています。H2はデータの保全性に問題がありますので業務等の重要な用途にGitBucketを使われるのであればなるべくPostgreSQLもしくはMySQLを利用することが望ましいです(パフォーマンス面でもメリットがあります)。

基本的にはリンク先の通りの内容で問題なく解決できますが、
DB 側の設定をしていなかったので MySQL の導入から進めていきます。


検証環境

MySQL セットアップ

インストール

# yum install https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
# yum --enablerepo=mysql57-community -y install mysql-community-server

サイズが 200 MB ほどあるので、タイムアウトエラーが出る場合は
yumtimeout の設定を適当に追加します。

# vi /etc/yum.conf
timeout=3600

デフォルトでは一部の文字コードが latin1 になってしまうため、データベースやテーブルを作成する前に設定を追記します。

# vi /etc/my.cnf

[mysqld]
character-set-server = utf8

[client]
default-character-set = utf8

[mysql]
default-character-set = utf8

[mysqldump]
default-character-set = utf8

インストールと文字コード設定が完了したら mysqld を起動します。

# systemctl start mysqld
# systemctl enable mysqld

MySQL 設定変更

MySQL の初回起動後は root ユーザのパスワードが仮設定され、
ログに仮パスワードが出力されます。

# cat /var/log/mysqld.log | grep 'temporary password'
2017-10-20T04:25:29.312034Z 1 [Note] A temporary password is generated for root@localhost: Uo7hApMhqg(k

パスワードとして Uo7hApMhqg(k が設定されていることが分かりましたので、
この情報を元に初回ログインと設定変更をします。

また、パスワードポリシーはデフォルトで MEDIUM に設定されていて、
数字, 小文字, 大文字, 記号 の4種がそれぞれ1つずつ含まれている必要があるようです。

MEDIUM policy adds the conditions that passwords must contain at least 1 numeric character, 1 lowercase character, 1 uppercase character, and 1 special (nonalphanumeric) character.

初回設定をしていきます。

# mysql_secure_installation
Enter password for user root: Uo7hApMhqg(k

New password: (root パスワードを入力)
Re-enter new password: (root パスワードを再入力)

Change the password for root ? ((Press y|Y for Yes, any other key for No) : n
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y

mysql コマンドでログインし、プロンプトに変わったらログイン成功です。

# mysql -u root -p
Enter password: (先ほど設定した root パスワード)

mysql>

データベースとユーザの作成

GitBucket 用のデータベースとユーザを作成し、権限を付与して反映させます。
ここではパスワードを P@ssw0rd として作成しているので、適宜変更してください。

> CREATE DATABASE gitbucket;
Query OK, 1 row affected (0.02 sec)

> CREATE USER 'gitbucket'@'localhost' IDENTIFIED BY 'P@ssw0rd';
Query OK, 0 rows affected (0.02 sec)

> GRANT ALL PRIVILEGES ON gitbucket.* TO 'gitbucket'@'localhost';
Query OK, 0 rows affected (0.01 sec)

> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

H2 データベースからデータを抽出

前回の検証時に組み込みの H2 データベース上にユーザを登録してしまったため、
一旦 H2 からデータをエクスポートします。

最初から MySQL で構築を始める場合、この項目は飛ばしてください。

GitBucket からデータをエクスポート

  1. 管理者でログイン
  2. 右上のユーザメニューから 'System administration' を選択
  3. 左メニューの 'Data export / import' を選択
  4. チェックボックス全てにチェックを入れた状態で Export ボタンを選択
  5. gitbucket-export-xxxxxxxx.sql ファイルをダウンロード

上記の手順でデータが出力されます。

サービス停止

GitBucket のアプリケーションを停止します。

# systemctl stop tomcat

データのインポート

先ほどの .sqlMySQL に直接読み込ませます。

# mysql -u gitbucket -p < gitbucket-export-xxxxxxxx.sql
Enter password: P@ssw0rd

データベース接続設定変更

GitBucket のデータベース接続設定ファイルを編集します。

# vi /usr/share/tomcat/.gitbucket/database.conf

db {
  url = "jdbc:mysql://localhost/gitbucket?useUnicode=true&characterEncoding=utf8"
  user = "gitbucket"
  password = "P@ssw0rd"
}

設定が完了したらもう一度 GitBucket を起動します。

# systemctl start tomcat

ユーザやリポジトリの情報が復旧していれば作業完了です。

参考サイト