2017.11.9 Update:
GitLab 10.1 + Mattermost 4.2 でうまく動かない部分があったため手順を見直しました。本文およびスクリーンショットは GitLab 9.0 + Mattermost 3.7 のもので現行とは少し異なる場合があります。
はじめに
会社の担当内ツールサーバーに GitLab および Mattermost を導入した際の備忘録です。
むかし Redmine のセットアップに挫折し、すっかり Rails (Ruby) 恐怖症になり、ファイルを置くだけで動くPHPの偉大さに毎日手を合わて拝む日々でしたが、最近はパッケージが整備され手軽に導入できるようになりつつあるようです。
GitLab も例に漏れずオムニバス版とよばれるオールインワンパッケージが提供されるようになったため、今回勇気を出してインストールを試みました。
同パッケージは、Nginx、PostgreSQL、Redis が自動でインストール&セットアップされますが、サーバーにはすでにApacheが動いているので、バンドルの Nginx は使用せず、既存の Apache をリバースプロキシにして使います。
目的・目標
- 最新の GitLab のインストール手順を確認したい(ググると旧バージョン向けの古い情報が混ざっていて戸惑ったので整理したい)
- Proxy環境下でも正常にインストール・運用できるか検証したい
- すでに Apache が動いているサーバーにリバプロを導入して複数のWebアプリを共存させたい
- ドメインネームを使って
http://10.0.0.1:8000/
みたいなIPアドレス+ポート番号のカッコ悪いURLをやめたい - いろいろと便利になるし、アドレスバーがグリーンになって気持ちよいので常時SSLにしたい
条件
- OS: CentOS 7.3
- HTTPサーバ: Apache 2.4.20
- サーバーは社内の閉域網に接続されておりインターネットへの接続は不可。インストール時など、どうしても必要な場合は一時的にプロキシサーバー経由でゴニョゴニョする
また今回の説明で用いるドメインネーム(架空)は次の通り。
- インストール先サーバーのFQDN:
centos.ipnoc.net
- GitLab の公開URL:
https://gitlab.ipnoc.net/
- Mattermost の公開URL:
https://mattermost.ipnoc.net/
- インターネット接続用Proxy:
http://proxy.ipnoc.net:3128/
IUSリポジトリ インストール
CentOS 標準のリポジトリでは、なにかと古いバージョンが入ってしまうため、IUS: Inline with Upstream Stable というサードパーティーのリポジトリをインストールし使います。
yum install -y https://centos7.iuscommunity.org/ius-release.rpm
古いのが嫌なら Fedora か Ubuntu の最新版使えよ、というツッコミはその通りだと思います。
Git クライアントインストール
標準リポジトリでは Git 1.8 という遙か古のバージョンが入ってしまうので、さっそく IUS を利用します。標準のものと衝突しないように "git" ではなく "git2u" という名前で登録されていますので、yum install -y git2u
でインストールします。
# 2017.3時点
$ git --version
git version 2.12.0
オレオレ証明書発行
前段階として HTTPS のための証明書を準備します。ナウなヤングにとって SSL と言えば Let's Encrypt ですが、閉鎖網だとインターネットへリーチャビリティーも無ければグローバルアドレスもありません。そこでみんな大好きオレオレ証明書を使います。
上記エントリを参考にオレオレ認証局(CA) および、オレオレ証明書を作ります。
- オレオレCA証明書(cacert.pem)をクライアント端末に「信頼するルート証明機関」の証明書としてインポート
- オレオレCA証明書(cacert.pem)を
/usr/share/pki/ca-trust-source/anchors/
へコピーし、update-ca-trust
コマンドを実行 - 各秘密鍵ファイル(*.key) は
chmod 600 *.key
で root 以外で開けないようにしておく
Apache セットアップ
Apache インストール
標準だと Apache 2.4.6 という微妙に古いものが入ってしまうので、IUS を使って最新版をインストールします。
-
yum install -y httpd24u httpd24u-mod_ssl httpd24u-mod_proxy_html
でインストール -
systemctl enable httpd
で自動起動設定 -
systemctl start httpd
で起動 -
firewall-cmd --permanent --add-service=http --add-service=https
でファイアウォール設定 -
systemctl reload firewalld
ファイアウォール設定有効化 - 外からWebブラウザで本ホストにアクセスし、"It Works!" が表示されることを確認
SSLセットアップ
/etc/http/conf.d/ssl.conf
を編集します
Listen 443 https
<VirtualHost _default_:443>
ServerName centos.ipnoc.net:443 #サーバーのFQDNを設定
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 #古いプロトコルはしまっちゃおうね〜
SSLCipherSuite HIGH:!ADH:!SSLv2:!MD5:!3DES:!DSS:!PSK #古いプロトコルはしまっちゃおうね〜
SSLCertificateFile /etc/pki/tls/certs/centos.ipnoc.net.crt #サーバー証明書
SSLCertificateKeyFile /etc/pki/tls/private/centos.ipnoc.net.key #サーバー秘密鍵
SSLCACertificateFile /etc/pki/tls/certs/IPNOC-CA.crt #CA証明書
</VirtualHost>
終わったら、systemctl restart httpd
でサーバーを再起動し、Webブラウザでアクセスしてください。
なお Safari, Firefox ではOKだったのですが、Chrome では NET::ERR_CERT_COMMON_NAME_INVALID というエラーが出てしまいました。いや、FQDNあってるじゃん・・・。謎です。 ← SubjectAltName(SAN) の設定が漏れていたためでした。CommonName(CN) だけじゃダメゼッタイ。
設定ファイル置き場作成
既存の設定ファイルに継ぎ足していくと、設定が散らばり、どこに書いたかわからなくなったり、読み込まれる順番によって意図しない誤動作を起こす場合があります。(特に VirtualHost は最初に読まれる設定がデフォルト設定になるためトラブルになりやすい)
うちでは独立したディレクトリを作り、そこにツールごとに設定ファイルを作って httpd.conf で読み込むようにしています。
mkdir /etc/httpd/conf.user.d
- /etc/httpd/conf/httpd.conf の末端に
IncludeOptional conf.user.d/*.conf
を追加
GitLab CE Omnibus セットアップ
GitLab Omnibus インストール
公式ドキュメントを参考にします。
-
yum install -y curl policycoreutils openssh-server openssh-clients
で依存パッケージをインストール(すでに入ってると思いますが) -
curl -x proxy.ipnoc.net:3128 -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | bash
でGitLab公式リポジトリをインストール -
EXTERNAL_URL="https://gitlab.ipnoc.net" yum install -y gitlab-ce
で GitLab CE Omnibus をインストール
オレオレCA証明書インストール
さきほど作成したオレオレ認証局の証明書を /etc/gitlab/trusted-certs/
へコピー
設定ファイル編集
/etc/gitlab/gitlab.rb
を編集
external_url 'https://gitlab.ipnoc.net' #外から見たGitLabのURL
gitlab_rails['time_zone'] = 'Asia/Tokyo' #JSTにする
gitlab_workhorse['listen_network'] = "tcp" #デフォルトはSocket接続だがリバプロできないのでTCPに変更
gitlab_workhorse['listen_umask'] = 000
gitlab_workhorse['listen_addr'] = "127.0.0.1:8181"
gitlab_workhorse['auth_backend'] = "http://127.0.0.1:8080"
nginx['enable'] = false #Apacheを使うので Nginx はOFF
編集が終わったら gitlab-ctl reconfigure
&& gitlab-ctl restart
で設定を反映。
また、gitlab-rake gitlab:check
を実行し怒られないかチェック。
Apache リバースプロキシ設定
/etc/httpd/conf.d/gitlab.conf
を編集
GitLab recipesの gitlab-omnibus-ssl-apache24.conf をコピペ。
-
YOUR_SERVER_FQDN
をよしなに書き換え -
SSLCertificateFile
にサーバーの公開鍵ファイルを指定 -
SSLCertificateKeyFile
にサーバーの秘密鍵ファイルを指定 -
SSLCACertificateFile
にオレオレCAの公開鍵ファイルを指定 -
/var/log/httpd/logs/
というパスは存在しないので、該当のディレクトリを作成するか、設定を/var/log/httpd/
に修正
編集が終わったら systemctl restart httpd
で設定を反映
動作確認(Web)
OKですね。
動作確認(Git)
適当にグループ・プロジェクトを作って、まずはHTTPS経由でアクセスします。
$ git clone https://gitlab.ipnoc.net/ipnoc/test-project.git
Cloning into 'test-project'...
Username for 'https://gitlab.ipnoc.net': miyahan
Password for 'https://miyahan@gitlab.ipnoc.net':
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
つぎに SSH 経由のアクセスを試します。
-
ssh-keygen -t rsa -C <メールアドレス>
で鍵生成 (毎回入力するのが面倒なので passphrase は空にすることをおすすめ) -
~/.ssh/config
を下記内容で作成しつつ、パーミッションを 600 に変更 - GitLab > User Settings > SSH Keys で公開鍵(id_rsa.pub)の中身を貼り付けて登録
- リモートリポジトリへアクセス:
git clone git@gitlab.ipnoc.net:ipnoc/test-project.git
```~/.ssh/config`
Host gitlab.ipnoc.net
User git
Port 22
HostName gitlab.ipnoc.net
TCPKeepAlive yes
identitiesonly yes
identityFile ~/.ssh/id_rsa
$ git clone git@gitlab.ipnoc.net:ipnoc/test-project.git
Cloning into 'test-project'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
$ echo "Hello World!" > README.md
$ git add README.md
$ git commit -m "first commit"
[master f85316b] first commit
1 file changed, 1 insertion(+), 4 deletions(-)
$ git push -u origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 276 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To gitlab.ipnoc.net:ipnoc/test-project.git
ed9904d..f85316b master -> master
Branch master set up to track remote branch master from origin.
SSH/公開鍵認証方式でもアクセスできましたね。ちなみにWebブラウザで GitLab のWebページは開けるのに、git コマンドでのリポジトリへのアクセスができない場合は、Gitlab Workhorse が正しく動作していない可能性があります。
## Mattermost セットアップ
GitLab には Slack ライクなチャットソフトウェア: Mattermost が同梱されています。Slackクローンとして大変出来が良く、GitLab との相性も抜群とくれば使わない手はないでしょう。
### 本体インストール
GitLab CE Omnibus に同梱されているので追加の作業は要りません。
### GitLab APIキー払い出し
今回 Mattermost は自身でのユーザー登録・認証はさせず、GitLab OAuth のみを許可します。GitLab に管理者アカウントでログインし、Admin Area(右上のスパナアイコン) > Applications で New Application を追加してください。

Redirect URL には次の2つを登録します
* <Mattermost 公開URL>/login/gitlab/complete
* <Mattermost 公開URL>/signup/gitlab/complete

ID と Secret Key が生成されるのでメモしておきます。
### コンフィグファイル編集
また `/etc/gitlab/gitlab.rb` を編集します。
```/etc/gitlab/gitlab.rb
gitlab_rails['mattermost_host'] = "https://mattermost.ipnoc.net"
mattermost_external_url 'https://mattermost.ipnoc.net'
mattermost['service_use_ssl'] = false
mattermost['service_site_url'] = 'https://mattermost.ipnoc.net'
mattermost['gitlab_enable'] = true
mattermost['gitlab_id'] = "c79de97835280339d3202cb7f46042d7405ca94826ec5496542e40bdf26ef65d"
mattermost['gitlab_secret'] = "9b9b87e3db550361df18f56de1f0934e9564fc97b7b736bdec0292b831b406e3"
mattermost['gitlab_scope'] = ""
mattermost['gitlab_auth_endpoint'] = "https://gitlab.ipnoc.net/oauth/authorize"
mattermost['gitlab_token_endpoint'] = "https://gitlab.ipnoc.net/oauth/token"
mattermost['gitlab_user_api_endpoint'] = "https://gitlab.ipnoc.net/api/v3/user"
mattermost['email_enable_sign_up_with_email'] = false #GitLab の OAuth のみにする
mattermost['email_enable_sign_in_with_email'] = false
mattermost['email_enable_sign_in_with_username'] = false
mattermost['email_send_email_notifications'] = true #設定しないとうるさいのでON
mattermost['email_require_email_verification'] = false
mattermost['email_send_push_notifications'] = false
mattermost['email_enable_batching'] = false
mattermost['localization_server_locale'] = "ja"
mattermost['localization_client_locale'] = "ja"
mattermost['localization_available_locales'] = "ja,en,es,fr,pt-BR"
mattermost_nginx['enable'] = false #Apacheを使うので Nginx はOFF
で、さきほどと同じく gitlab-ctl reconfigure
&& gitlab-ctl restart
します。
Apache 設定
VirtualHost および Reverse Proxy を設定します。VirtualHost は最初に読まれた設定がデフォルトになる仕様のため、いまから作る設定ファイルは、基本設定ファイル(/etc/httpd/conf.d/ssl.conf
) より後にインクルードされるようにしてください。
<VirtualHost *:80>
ServerName mattermost.ipnoc.net
ServerAdmin admin@ipnoc.net
ServerSignature Off
RewriteEngine on
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [NE,R,L]
</VirtualHost>
<VirtualHost _default_:443>
ServerName mattermost.ipnoc.net:443
ServerAdmin admin@ipnoc.net
ServerSignature Off
SSLEngine On
SSLProtocol all -SSLv2 -SSLv3 -TLSv1
SSLHonorCipherOrder on
SSLCipherSuite HIGH:!ADH:!SSLv2:!MD5:!3DES:!DSS:!PSK
Header add Strict-Transport-Security: "max-age=15768000;includeSubdomains"
SSLCompression Off
SSLCertificateFile /etc/pki/tls/certs/mattermost.ipnoc.net.crt
SSLCertificateKeyFile /etc/pki/tls/private/mattermost.ipnoc.net.key
SSLCACertificateFile /etc/pki/tls/certs/IPNOC-CA.crt
# This setting is required to forwarding Websocket
ProxyPreserveHost On
# The following two lines fix the problem that page is reloaded multiple times whenever switching the channel
RequestHeader unset If-Modified-Since
RequestHeader unset If-None-Match
RequestHeader set X-Forwarded-Proto 'https'
RequestHeader set X-Forwarded-Ssl 'on'
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/api/v3/users/websocket [NC,OR]
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
RewriteRule .* ws://127.0.0.1:8065%{REQUEST_URI} [P,QSA,L]
<Location />
Require all granted
ProxyPass http://127.0.0.1:8065/
ProxyPassReverse http://127.0.0.1:8065/
ProxyPassReverseCookieDomain 127.0.0.1 mattermost.ipnoc.net
</Location>
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common_forwarded
ErrorLog /var/log/httpd/mattermost.ipnoc.net_error.log
CustomLog /var/log/httpd/mattermost.ipnoc.net_forwarded.log common_forwarded
CustomLog /var/log/httpd/mattermost.ipnoc.net_access.log combined env=!dontlog
CustomLog /var/log/httpd/mattermost.ipnoc.net.log combined
</VirtualHost>
動作確認
"GitLab でログインする" というボタンが表示され、かつメールアドレスでのサインインフォームが表示されなければ成功です。
さらに GitLab で認証を承認し、Mattermost にリダイレクトして戻ってくるかどうか確認してください。
ようこそ!あとは Hubot を住まわせるなり、GitLab で Webhook を設定するなりしてイケてるチャットライフをお楽しみください。
トラブルシュート
Mattermost がサブディレクトリで運用できない
実は当初、https://centos.ipnoc.net/gitlab/ および https://centos.ipnoc.net/mattermost/ といったようにサブディレクトリにデプロイしようとしていました。
GitLab は設定できたものの、Mattermost は gitlab_rails['mattermost_host'] = "https://miyadev.ipnoc.net/mattermost" としたところ reconfigure がエラーで止まってしまいました。どうやら Mattermost は(まだ?)サブディレクトリに対応していないようです。結局、VirtualHost を使ったサブドメインに作戦変更しました。まあ後述の通り GitLab もトラブル続きでとても使えたものじゃなかったのでちょうどよかったのですが・・・。
gitlab-ctl reconfigure 時にDBロック解放待ちが発生し続けてしまう
gitlab-ctl reconfigure した際に下記のようなDBロックエラーが出てしまうことがありました。
[execute] createdb: database creation failed: ERROR: source database "template1" is being accessed by other users
DETAIL: There is 1 other session using the database.
このときは、何回か gitlab-ctl restart
してから再度実行したところ直りました。なにかのセッションが持ちきっていたんですかね?
Error compling CSS asset エラーが出て何もできなくなる
当初GitLabをサブディレクトリ(https://centos.ipnoc.net/gitlab/)で運用しようと設定していたところ、どこにアクセスしても "Error compiling CSS assert" というエラー画面がでて何も動かなくなってしまいました。
$ gitlab-rake assets:precompile --trace
** Invoke assets:precompile (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
** Invoke environment (first_time)
** Execute environment
** Execute assets:precompile
I, [2017-03-24T01:09:32.947634 #13329] INFO -- : Writing /opt/gitlab/embedded/service/gitlab-rails/public/assets/katex-0f6b15d9e75a27a42599be41c6dd27deae957093901bb29c0254f5ce67dffb6b.css
I, [2017-03-24T01:09:32.948279 #13329] INFO -- : Writing /opt/gitlab/embedded/service/gitlab-rails/public/assets/katex-0f6b15d9e75a27a42599be41c6dd27deae957093901bb29c0254f5ce67dffb6b.css.gz
rake aborted!
ExecJS::Error: ExecJS disabled
/opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/execjs-2.6.0/lib/execjs/disabled_runtime.rb:18:in `compile'
/opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/execjs-2.6.0/lib/execjs/module.rb:27:in `compile'
/opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/uglifier-2.7.2/lib/uglifier.rb:171:in `initialize'
トレースを見てみると "ExecJS::Error: ExecJS disabled" なるエラーが。ググってみると似たような issue: Frontend broken after update to 8.17 in Scientific Linux 7.3 があり、そこに書かれているワークアラウンドを実行したところ、エラーがでなくなりました。
rm /opt/gitlab/etc/gitlab-rails/env/EXECJS_RUNTIME
chown -R git:git /opt/gitlab/embedded/service
gitlab-rake gitlab:assets:compile
chown -R git:git /opt/gitlab/embedded/service
gitlab-rake webpack:compile
chown -R git:git /opt/gitlab/embedded/service
gitlab-ctl reconfigure
gitlab-ctl restart
ただそれでもサイドメニューが開かない(必要なJSが生成されない)などフロントエンド周りに不具合が残っていてお手上げでした。。。どうやらサブディレクトリでの運用がトリガーになっているらしく、ルートディレクトリに変更して再セットアップしたところ不具合は治まりました。
さいごに
いろいろとつまずき、完全に動くまでに2日かかってしまいましたが、総括すると「足を踏み外さなければ何も起きない。しかし・・・」という感触です。これはバージョンアップとか辛そう・・・。
まあともかく GitLab は立ったので、これからちゃんとソース・issue管理してツールつくるぞー!!