CentOS7にGitLab 9をインストールして日本語化

最近CentOS7にGitLabを入れて、日本語化してみました。
最近9が出たようで、あまり参考になるサイトもなく、詰まるポイントもあったため手順を記録します。

結論としては、ポイントは以下の3つでした。
・npm install
・bundle exec rake assets:precompile RAILS_ENV=production
・bundle exec rake webpack:compile RAILS_ENV=production

また今回インストールしたのはGitLab9.0.5になります。

GitLab9のインストール

基本的に公式サイトの手順に従うだけで完了します。

# これによりruby, postgres, nginx全てまとめてインストール、セットアップされる。
$ curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
$ yum install gitlab-ce

       *.                  *.
      ***                 ***
     *****               *****
    .******             *******
    ********            ********
   ,,,,,,,,,***********,,,,,,,,,
  ,,,,,,,,,,,*********,,,,,,,,,,,
  .,,,,,,,,,,,*******,,,,,,,,,,,,
      ,,,,,,,,,*****,,,,,,,,,.
         ,,,,,,,****,,,,,,
            .,,,***,,,,
                ,*,.

...
インストール:
  gitlab-ce.x86_64 0:9.0.5-ce.0.el7

完了しました!

これだけでいいの?  と思いますが、これだけでOKです。
ソースから入れたり、既存のnginxを利用したいなどあると思いますがその場合にはインストール後の設定で対応可能なようです。

GitLab初期設定

私もまだ構築中なので、設定そのものは参考程度に留めていただいた方が良いと思います。

# 手探りで初期設定。mail, https設定など不足。unicorn, redisは正直不明。デフォルトを利用するようにだけしてみたつもり
$ cp /etc/gitlab/gitlab.rb /etc/gitlab/gitlab.rb.org
$ vi /etc/gitlab/gitlab.rb
$ diff /etc/gitlab/gitlab.rb.org /etc/gitlab/gitlab.rb
13c13
< external_url 'http://hogehoge'
---
> external_url 'http://hogehoge.com'
40a41
> gitlab_rails['time_zone'] = 'Asia/Tokyo'
518c519
< # unicorn['worker_timeout'] = 60
---
> unicorn['worker_timeout'] = 60
521c522
< # unicorn['worker_processes'] = 2
---
> unicorn['worker_processes'] = 2
524,529c525,530
< # unicorn['listen'] = '127.0.0.1'
< # unicorn['port'] = 8080
< # unicorn['socket'] = '/var/opt/gitlab/gitlab-rails/sockets/gitlab.socket'
< # unicorn['pidfile'] = '/opt/gitlab/var/unicorn/unicorn.pid'
< # unicorn['tcp_nopush'] = true
< # unicorn['backlog_socket'] = 1024
---
> unicorn['listen'] = '127.0.0.1'
> unicorn['port'] = 8080
> unicorn['socket'] = '/var/opt/gitlab/gitlab-rails/sockets/gitlab.socket'
> unicorn['pidfile'] = '/opt/gitlab/var/unicorn/unicorn.pid'
> unicorn['tcp_nopush'] = true
> unicorn['backlog_socket'] = 1024
578,581c579,582
< # postgresql['enable'] = true
< # postgresql['listen_address'] = nil
< # postgresql['port'] = 5432
< # postgresql['data_dir'] = "/var/opt/gitlab/postgresql/data"
---
> postgresql['enable'] = true
> postgresql['listen_address'] = nil
> postgresql['port'] = 5432
> postgresql['data_dir'] = "/var/opt/gitlab/postgresql/data"
655,656c656,657
< # redis['enable'] = true
< # redis['username'] = "gitlab-redis"
---
> redis['enable'] = true
> redis['username'] = "gitlab-redis"
660,661c661,662
< # redis['uid'] = nil
< # redis['gid'] = nil
---
> redis['uid'] = nil
> redis['gid'] = nil
722c723
< # nginx['enable'] = true
---
> nginx['enable'] = true
752c753
< # nginx['listen_addresses'] = ['*', '[::]']
---
> nginx['listen_addresses'] = ['*', '[::]']


# 設定を有効化
$ gitlab-ctl reconfigure

# 状態の確認
$ gitlab-ctl status
run: gitaly: (pid 12284) 26s; run: log: (pid 11807) 65s
run: gitlab-monitor: (pid 12336) 24s; run: log: (pid 12238) 38s
run: gitlab-workhorse: (pid 12296) 25s; run: log: (pid 11858) 63s
run: logrotate: (pid 12000) 55s; run: log: (pid 11999) 55s
run: nginx: (pid 11958) 57s; run: log: (pid 11957) 57s
run: node-exporter: (pid 12113) 47s; run: log: (pid 12112) 47s
run: postgres-exporter: (pid 12324) 24s; run: log: (pid 12195) 40s
run: postgresql: (pid 11522) 110s; run: log: (pid 11521) 110s
run: prometheus: (pid 12308) 25s; run: log: (pid 12070) 49s
run: redis: (pid 11410) 121s; run: log: (pid 11409) 121s
run: redis-exporter: (pid 12155) 41s; run: log: (pid 12154) 41s
run: sidekiq: (pid 11760) 71s; run: log: (pid 11759) 71s
run: unicorn: (pid 11705) 73s; run: log: (pid 11704) 73s

# ポートの開放。私はhomeで接続元許可とかしてるのでhomeに追加。
# 公開サーバであればzoneはpublicか未指定で。
$ firewall-cmd --add-service=http --zone=home --permanent
success

GitLab日本語化

続いてGitLabの日本語化を行なっていきます。
ここからが問題になる場所で、日本語化途中にある assets:precompile が上手くいかないのです。
GitLab9自体が出たばかりで日本での報告はまだあまり見ませんが、海外ではいろいろとお話がされていました。

また日本語化パッチはまだ9.0.4までしか出ていないため、一部不具合が出るかもしれませんが現状特に問題なく日本語化できているっぽくもあります。

パッチの適用

まずはパッチの適用を行なっていきます。
nodeを7.7.4でインストールしているのは、海外のフォーラムで「私は7.7.4で動いたわ」っていうコメントを見かけたからになります。
おそらく最新で問題ないです。

# パッケージ準備
$ yum remove nodejs
$ yum install gcc-c++ git
$ cd /usr/local/src/
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.26.1/install.sh | bash
$ source ~/.bashrc
$ nvm install v7.7.4

# パッチファイルを取得
$ wget https://raw.githubusercontent.com/ksoichiro/gitlab-i18n-patch/master/patches/v9.0.4/app_ja.patch

# patchコマンドをインストール
$ yum install patch

# 日本語パッチの適用
$ cd /opt/gitlab/embedded/service/gitlab-rails/
$ patch -p1 < /usr/local/src/app_ja.patch

assets:precompile

問題のassetsのprecompileです。
どうやら最新のgitlabだとprecompile前に
「/opt/gitlab/embedded/service/gitlab-rails/」のフォルダでnpm installしないといけないみたいです。
これを行わないとモジュールが不足しているためコンパイルできないという旨のエラーにハマります。

またさらに、ここで正常にコンパイルが成功してもGitLabは500エラーになっていました。
ログを見るとwebpackがどうこう言っていたので、そちらもコンパイルしてあげると、ちゃんと日本語化されて起動できます。

# 再コンパイルのために必要なnode_modulesを取得
# 一部エラーが出るが無視
$ npm install

# 起動済みのため再コンパイル
$ rm -rf public/assets
$ export PATH=/opt/gitlab/embedded/bin:$PATH
$ bundle exec rake assets:precompile RAILS_ENV=production

# precompileのみだと起動後にwebpackが云々でエラーになるのでこちらのコンパイルも行う
$ bundle exec rake webpack:compile RAILS_ENV=production
$ gitlab-ctl reconfigure
$ gitlab-ctl restart

感想

今回は無駄に時間がかかってしまったことと、npm install時のリポジトリがないよ的なエラーは未解決です。
そちらもちょっと試してたのですが、サクッと解決できなかったため一旦置いています。実は問題ないんじゃないの、って思ってますがどうなんでしょうか。

自分が何か入れようとして最新を取得すると、だいたいつい最近メジャーバージョン上がったんだよねってなってて参考サイトがないこととが多々あります。
間が悪いですね。

ボッチ初学者のScalaMatsuri in 2017

ScalaMatsuri2017に参加してきました。
自分はこの手のイベントに参加したことがなくイメージがつかないままに参加したので、来年以降のそういう人の参考になればと思います。

私自身の技術者としての能力が正直今は低いので、発表やアンカンファレンスの内容については特に突っ込んだ内容はありません。
身の丈、ありのままの感想文になります。

最初に書いておきますが「楽しいから初心者でも行ったほうがいいよ」が結論です。

参考情報

ではまず参考として、私の知識やスキル周りを記載します。

プログラム経験: 大学2年からの約2年 + 社会人で突発に少々。
技術範囲(程度は置いといて): フロント, サーバサイド, インフラ。一通り一人でウェブシステム作れます感。
言語: Java, PHP, C#
DB: 普通にsql書いてつかってレベル。RDBXMLをDB代わりに使ったりくらい。
フレームワーク: Struts, Spring(少々), Laravel, .Net MVC
その他: xsltとか。

学生時代は企業で週5、ひたすら開発をしてました。大学は情報系でしたが、行ってませんでした。卒業してません。
社会人になってからは1年目の途中までC#をゴリゴリ書いて、そこからはSIの上流工程やサポートに従事してました。
途中で突発でショート案件を一人で書いたりしましたが、貯蓄で捌いてた感じ。

まともに技術学び直してちゃんとエンジニアしなきゃと思ったのが5年ぶりくらい? の感じです。

学習対象としてScalaを選択した理由は大学3年ごろにScalaの存在を知って憧れていたから。
当時直感で「Scalaはなんか10年後も残ってそうだし微妙にメジャーくらいの位置になってそう」と思ってliftを触って「あっ」ってなって辞めたのですが、Scala自体には消えぬ思いが燻り続けてました。燻製になる前に火を起こした感じ。

ScalaMatsuri 1日目

早速振り返り兼感想文に移ります。

オープニング

ScalaMatsuriにはオープニングがあったのですが、あんまり何も考えずに観に行きたいプログラムの部屋に移動してたので参加できませんでした。

Scala.js 1.0への道

Scala.jsというものの存在はわりと昔から知っていたのですが、それがついに1.0ということで聴きにいきました。
ScalaMatsuriには同時翻訳用のレシーバーがあり、リアルタイムで翻訳者の方が翻訳をしてくれます。

事前に調べて観たところ去年はちょっと不評っぽい意見が散見していたので心配していましたが、全く問題ありませんでした。
普通に話として聞けるレベルで翻訳をしてくれていたので、内容は十分わかりました。

内容自体は「は〜紆余曲折あったんだねぇ」という具合で、いろいろと変更、リファクタの歴史を話してもらったのですが話を聞いた瞬間にそれが何故問題で、それが何故解決されたのか理解できるほど知識も能力も足りずというところです。
あと恥ずかしいレベルでいうと、CommonJSってなんやねん、って思ってました。
ServerJSとかブラウザ以外で使うJsのことらしいですよ。
Wiki

言われれば「あぁあれね」ってわかるのですが、技術とかは置いといたとしても言葉を知らないためにわからないことが結構ありました。

完全に感想ですが、この人がScalaをjsにしようなんてイカれたことを考えて且つ実行してるイカれた人なんだ(褒め言葉)って思いました。

またエコシステムってなんだ? って思いましたし、今も思ってます。

Scala Warrior

Scala.jsの話を聞いたので、Scala.jsを使ったというこちらの話を聞いてみました。
僕はてっきり、脳筋だけどめっちゃ強いScalaエンジニアたちのための〜、みたいな話だと思ってたんですが、Scala Warriorっていうシステムがあったみたいです。

またこのセッションはScala界隈なのかプログラム界隈なのかわかりませんが、有名人なtakezoeさんのセッションでした。
Scalaパズルっていう本の執筆をされていたんですね。勉強会とかいくとちょいちょい耳にする本です。
せっかくだし買うか、って思いました。

こちらは入力されたScalaのコードをサーバへ送って、Scala.jsでコンパイルしてフロントに戻しつつ実行する流れでできているとのこと。
ScalaTags, ScalaCSS, Scala.js-Reactなんていうものもあるらしく、根性と愛があれば全部Scalaで作れちゃいますね!

公演の中でもそのような話はありましたが、残念ながら辛いということです。
そりゃそうですよね。

話の中で、jsonを処理する部分については旨味があったというような話があったのですが、そこは「ほぉ〜」というところですね。
まだ浅いのでわかりませんが、ScalaってJsonのパーサーがいけてるのない印象があるので、そこ切り出してうまいこと使えないもんかな。

あと絶妙な感じの絵が個人的には凄く好き

本当に死ぬブロッキング&コンテキストスイッチング

こちらは現場で起きた障害をベースにしたお話でした。
自分話を聞くときにあまりメモを取らず、その時の雰囲気を覚えておけば後で引っかかるから大丈夫というスタンスで生きているので細かい内容を覚えていません。

playのDB接続で使われるcontextの一つが無限にプールだかコネクション作るよ
for文の中で不適切なコード書くと逐次処理になってその中で上記が呼ばれまくって本当に死ぬよ
playはnon-blockingでスレッド少なくフルで動かす作りだよ
迂闊にblockingするメソッド使うと死ぬよ。メソッド名が日本人にはblockingなメソッドってわかりづらいから気をつけよう

って内容だったはず。

そもそも処理的に微妙とかそういう話は置いておく、ということだったので特に気にはせず。
チームでやってると「微妙だけど、まぁうんいいか」ってしちゃうコードも稀にあるので、そういうときに限って死ぬっていう感じでハマりますよね。

これは内容とかも「そうだね」という感じで、わかりやすいというか、わかる内容でした。

便利tips

よく使うけどよく使う書き方じゃなくて、こっちで書くと早くなるよ、という内容。

このレベルでチューニングが必要なことは稀だと思いますが、知ってるなら遅いより速い方で書けばいいよね、というところで良かったです。
あと初心者でもついていける話でした。
ついていくとか以前の話になるのですが、速くなる理由含めてお話ししてくれているのでパッとわからなかったとしても大丈夫というのも親切でしたね。

ランチ(お昼休憩)

ここまで安定のボッチで、ここからも引き続きボッチなのですがお昼です。
お弁当をもらえるので、それを持って空き部屋で食べました。

このときに大学生時代にお世話になっていた就活イベント運営会社の人を見つけました。
そっくりだけど間違えてたら怖いのでFacebookから連絡とったら、その人でしたね。
ScalaMatsuriのスポンサーとしてその方の現在の勤め先企業が載っていたので、そんなこともあるかもっておもってましたが、あったね。

エンジニア世界って広いけどめっちゃ狭いよなぁと思います。

私は今年から勉強会とかに参加するようにしているのですが、そこで観た人たちも結構お祭りに参加してましたね。
Scalaは採用企業も増えてきてはいますが、やはり母数はまだまだということでしょうねぇ。
あとイベント参加するために家の外に出る系エンジニアの母数がそもそもというのもね。

DMMでAkka

私はAkka触ったことがないのですが、噂のAkkaをDMMでの活用事例などを元に聞けるのかな〜と思い参加。

かなり作りこまれた資料を元に、丁寧にアーキテクチャの説明をしてくれていました。
残念なのは、ここでも同じく「へぇ〜そうなんだぁ、なるほど、すごいな〜」くらいの感想しか抱けない無力さですね。
まずそもそもAkkaわからんし、アクターモデルについても「分散していい感じに各々処理してくれるんだよね」くらいのイメージなので、そもそもこれAkka採用してる旨味どこなん? 状態。

そのようにしている事実だけわかるんですが、それ結局話聞いて唸ってるだけでなんもわかってないよね、って感じ。

このタイミングから「そもそも俺は祭りに参加してるより、家に帰って勉強しなきゃいけないのでは?」と思い始めてます。

おそらくちゃんと内容についていける人にとっては事例としても、システム構成も非常にためになったのではないでしょうか。

Introduction to ScalikeJDBC

これは初心者向けの講座でした。
内容も十分理解できましたが、後半ちょっと走り気味だったかな?

スピーカーの方も、「ぶっちゃけドキュメント読んだらそれで終わりなんですけどね」っておっしゃってましたが、まさに「ぐぐってドキュメント読めばわかるよね」という話。
スピーカーの方が悪いとかいうことは全くなく、そういう対象者のための講座なんですよね。

そう、つまり、今の自分のScala力は技術力とか以前に「知らない」っていう状態。
なんだろうそもそも、話をする土俵に立っていないわけです。
基本構文も含め、みんな使ってるモジュールやフレームワークを触ってないので思考に入ることができずに、ただありのままを受け止める感じ。

そろそろ本格的に帰って勉強しようかな、って気持ちが強くなった頃です。

またこのときに出てきていた、DSLという言葉がわからずにいました。
たぶん今生きてるエンジニアならわからないと死んだ方がいいよってレベルの言葉なんだろうなぁと思いながら聞いてました。

Serverless Architecture

一昔前からちょいちょい聞くサーバレスの話。
サーバレスっていうか、サーバあるじゃん? って今でも思ってますが、そういう意味じゃないんだよねきっと。

という私が聞くわけなので、ちゃんと話を理解することはできませんでした。
ただBlue/Greenデプロイという考えと、その構成は参考になりました。

あとはAWSってほんといろんなサービスあるよなって感想です。
こちらもまだ理解が追いつく内容だったので、楽しく拝聴できました。
今何があったのか言えって言われても、自分じゃ説明できないので理解が腹には落ちてませんけどね。

いつか必要になったときに、プレゼン資料の図と話の全体感だけ思い出して調べながらなんとかできそうであればいいよね、って生き方をそろそろやめた方がいいのかもしれない。

Chatworkプロジェクト

Scalaを触っている日本人ほぼ全員気になってるであろうChatwork社のFalconプロジェクトの歴史です。
こちらは技術的にどうこうというよりは、歴史や流れなど全体のお話だったので純粋に楽しめました。

途中で結構アーキテクチャ変わってるのですが、内部でどのような流れがあり変わっていったのかとかのお話が興味深かった。
PoCをかなりしっかりと行いながら技術選定して再建していったようです。
また技術よりも、チームマネジメントやコミュニケーションデザインが大変だったみたいですね。
人間版MVCじゃないけど、V <--> M <--> C 間の情報伝達や認識共有というかね。そうだよなぁって。

懇親会

全体が終わった後に懇親会がありました。
懇親会は一つのフロアに結構な人が集まっていたので密度半端ない感じでした。

独り身の私は辛いところではありましたが、そこはあまり気にせずに登壇社の方々の近くに近づいては聞き耳を立ててました。
聞いておくだけでも貴重な時間ですよね。
酔いが回ってくれば相互にご機嫌になるので、なんとかなります。

身の程をわきまえずにカトジュンさんにも話しかけてみましたが、やはり何か自分が提供できる話もなく時間を浪費させてしまうだけになるので心苦しものです。
人と話すためにも勉強しないとダメですね。

1日目まとめ

1日目はこんな感じで話を聞いており、だいたいよくわかってなかったです。
ただこれはScalaMatsuri云々以前に、技術のイベント楽しもうと思ったら一定の技術ないとダメだよっていう当たり前の準備が不足してたにすぎないとおもってます。

またなんとなく感じたのは、中級者とか「なんとなくScala使えます」みたいな、中間層の?エンジニアがあんまりいないのかなぁということ。
そもそもScalaを選んでいる人ってそこそこ技術力あったり、技術好きな人が多いと感じます。
Swiftとかに比べて、なんだろう、とっつきやすいくらいの技術力を持ってる人がいないっていうかね?

良くも悪くもそのへんからもScalaを感じました。
また、1日目の私の知力低すぎるわからないことメモが以下
[code]
・プログラムにおける、マクロってなに
・Dottyとはなんぞや
・みんなslack使っててかっこE
DSLってなんぞや
・green, blueデプロイ
・DDD
・POC (コンセプト検証)
・規模が大きくなるとやっぱりネックはIOなんだなぁ
・ライブマイグレーション??
・Resiliency??
・CQRS?? ES??
・シャーディング??
[/code]

いやぁ、技術やらないとやばいよねこれマジで。

2日目

2日目はサクッと寝坊しました。
金曜日に出張して徹夜だったので、そんな気はしてましたがやっぱり寝坊しました。

2日目はアンカンファレンスとなってました。
そもそもアンカンファレンスってなんだよ、っていう僕みたいな人も他にいますかね?

未だに定義がよくわかってませんが、前日に募った内容から人気があったものをみんなで話してカンファレンスの内容を決めたようです。
午前中にそのやりとりがあったみたいなので、僕は参加できていません。

一人のスピーカーの方が前で話をするスタイルもあれば、全員で自由に発表するブレストみたいなスタイルの部屋もあったっぽい?
これも私は話に混ざるほどの状態ではなかったので、傍聴してました。
まだしっかりやれてないので、そもそも質問もなければ話せる内容もないというねぇ。
辛いよね〜。

瀬良さん Scala入門

で、私はいくつか参加したのですが特に話すことが書けないので瀬良さんの入門のお話。

私が今年Scalaの勉強を始めて、今も諦めずにいられるのは瀬良さんのSkinny Frameworkがあったおかげなんですね。
Playを始めたらちょうど新しいバージョンが出てすぐくらいで、せっかくだしと新しいので始めたら思いの外下位互換なくて過去の記事が役に立たず。
自力で解読していくほどの時間も知識も足りず、無駄にslickを選定し詰まりまくって死にそうだったときにSkinnyFrameworkに乗り換えました。
ほんとにSkinnyさんの直感的なわかりやすさに助けられました。

講座自体はプロジェクト作成やsbt, scalaのバージョンやライブラリなどのバイナリー指定の話等々、まさに入門という内容。
実際にコードを書くというところの前段の話ですね。
さすがに内容的に新しいことはありませんでしたが、おさらいとして良かったです。

このプログラムが終了した後に、瀬良さん本人に直接
「SkinnyFrameworkのおかげでScala続けられました。ありがとうございます」
ということが伝えられたので、とても満足です。

あとは自分がちゃんとScala使いになって社内で仲間見つけて、プロジェクトで使うことですね。

企業ブース

SalaMatsuriには企業ブースが出ていて、入場の時にもらえるバッグの中に各々企業さんからのグッズが入ってます。
グッズだと、セプテーニさんの技術読本はいいですね。
ScalaAndroid開発いけるんだ〜、って感じです。貴重なノウハウだ〜と思って読みます。

あとブースはありませんでしたが、地味にM3さんのマスクが助かりました。
花粉症の季節ですからね。ほんとね、助かるよね。

またアイテム系でいうのであれば、FCODEさんのMacBookProプレゼント企画は良かったですね。
ScalaMatsuriの参加者は大体300人くらいのはずなので、興味ない振りしつつも「実は俺が当たる予感がする」というワクワク感が楽しめました。
当たりませんでした。

他にもいくつかのブースがあり、私はほぼほぼ全部のブースにお邪魔してお話を聞いてみました。
Scalaでの事例や使用感とか聞けて良かったです。

ブースについて一つ思うところがあるとすると、この人たちの立ち位置がよくわからないという点でしょうか。
転職、新卒採用なのか単純に広報なのか、Scala大好きで応援したいのか。
全部なんでしょうけど、転職全く考えていないのにブースにお邪魔していいもんか? と思って近づきづらかったです。

多分同じように思ってた人結構いるんじゃないかな。

総括

基本的には「楽しかったし参加者ともボッチなりに話せたので満足」です。

満足できなかったことがあるとすると、私の場合には個人的な問題ですね〜。

素直な心の声は
「もっとScalaやその周辺技術に触れていれば楽しさ倍増だったのに!!」
これにつきます。

とはいえ、参加をすることでScala以外の技術動向や最近の技術トレンド、ワードを知ることができることと、技術を学ぶためのモチベーションを向上させてくれるので、間違いなく参加して良かったと思えるイベントだと思います。

運営の方々もScala勢だろうにカンファレンスの話を聞かずに、運営をしてくださっているわけですから本当に感謝しないといけないなぁと。
感謝を示すなら自分がScala利用者になって、会社なりどこかで布教してユーザ増やすことだよねと。

来年にはちゃんと技術者としてイベントが楽しめるように、改めて今年一年有意義に使わないといけないと感じさせてもらえたのは良かったです。
また今日からコツコツ頑張ります。

追記

今回のScalaMatsuriで何か難しいと思い続けていた感覚があるのですが、それってたぶんアーキテクチャの話が凄く多いということなんだろうと思いました。

Scalaを利用する人は社内で発起人になったり、新しく言語採用をしていく立場の方が多いため、アーキテクチャから構築していく方が多いのでしょう。
話している内容が「Scala言語」ではなく「Scalaプロジェクト環境」であることが多く、言語は当然使える+αでScalaを取り巻くツールやフレームワーク、ライブラリ、教育、概念の話がメインになっていることが多いと感じます。
なので、付け焼き刃や経験から肌感で理解したつもりになってることが通用しない印象です。

そのため「耳に入ってくるし、言わんとしている雰囲気わかるんだけど全然わからない」という状態になるのかなって思いました。

Scalaは敷居が高い、と言われることが指していることって言語のことじゃなくてこっち側の話なんだろうなって思うと、個人的には非常にしっくりきますね

RaspberryPI3にCentOS7をインストール (mac利用)

いつの間にやらRaspberryPI 3が発売し、さらにはCentOSまでもがraspberry piに対応していました。
pi2用のcentosイメージもあるみたいです。

piを初代から購入している私としては3も買わないわけにはいかないということで新たに3も購入しました!
ディスク作成から初期設定までの手順を記載しようと思います。

とはいえ、今回は他のサイトで見たのをほぼそのままやってるものも多いです。
特に参考(引用)とさせていただいたのはRaspberry Pi 3 へCentOS7導入からWifi無線LAN接続まで設定メモのサイト様になります。

ディスクの作成

まずはディスクを作成します。
raspberry piのディスクにするためのmicro sdは事前にフォーマットしておきましょう。
フォーマットの方法は先ほどの参考サイトを見ていただくと、わかりやすいと思います。
Raspberry Pi 3 へCentOS7導入からWifi無線LAN接続まで設定メモ

ディスクフォーマット後はイメージの取得です。
イメージは以下のURLから取得できますので、raspberry pi3用のものを取得してください。
http://mirror.centos.org/altarch/7/isos/armhfp/

ファイルがダウンロードできたらあとはコンソールからコマンドで対応できます。
ちなみに以下はmacにて作業しています。

$ xzファイルを展開するためにインストール  
$ brew install xz  
$ xz -d CentOS-Userland-7-armv7hl-Minimal-1603-RaspberryPi3.img.xz   
  
$ ディスク確認  
$ df  
Filesystem    512-blocks      Used Available Capacity  iused   ifree %iused  Mounted on  
/dev/disk1     234586112 202543136  31530976    87% 25381890 3941372   87%   /  
devfs                371       371         0   100%      642       0  100%   /dev  
map -hosts             0         0         0   100%        0       0  100%   /net  
map auto_home          0         0         0   100%        0       0  100%   /home  
/dev/disk2s1    60614144      4800  60609344     1%        0       0  100%   /Volumes/PI_CENTOS  
  
$ 一旦microsdのディスクをアンマウント  
$ diskutil umount /dev/disk2s1   
Volume PI_CENTOS on disk2s1 unmounted  
  
$ イメージを書き込み  
$ sudo dd if=CentOS-Userland-7-armv7hl-Minimal-1603-RaspberryPi3.img of=/dev/disk2  bs=8192  
Password:  
  
393216+0 records in  
393216+0 records out  
3221225472 bytes transferred in 1472.442878 secs (2187674 bytes/sec)  

これで一旦ファイル作成が完了します。

パーティション修正

以前Raspberry Pi2にfedoraを入れた際もパーティション修正が必要になりましたが、今回も必要なようです。
これは起動したRaspberry PI上で実行しています。

OS自体は最初から初期設定がされた状態のようで、起動したらすぐそのまま利用できました。
以下、パーティションを設定していきます。

# dfでディスクを確認後以下  
$ parted /dev/mmcblk0  
  
(parted) p                                                                  
モデル: SD SA32G (sd/mmc)  
ディスク /dev/mmcblk0: 31.0GB  
セクタサイズ (論理/物理): 512B/512B  
パーティションテーブル: msdos  
ディスクフラグ:   
  
番号  開始    終了    サイズ  タイプ   ファイルシステム  フラグ  
 1    1049kB  316MB   315MB   primary  fat16             lba  
 2    316MB   852MB   537MB   primary  linux-swap(v1)  
 3    852MB   3000MB  2147MB  primary  ext4  
  
# 3番を一旦削除  
(parted) rm 3                                                               
エラー: パーティション 3 (/dev/mmcblk0 上)  
に書きこまれましたが、カーネルに変更を伝えることができませんでした。おそらく、使用中だったのが原因だと思われます。そのため、古いパーティション情報がそのまま使われます。さらなる変更をする前に再起動してください。  
無視(I)/Ignore/取消(C)/Cancel? i                                            
(parted) p                                                                  
モデル: SD SA32G (sd/mmc)  
ディスク /dev/mmcblk0: 31.0GB  
セクタサイズ (論理/物理): 512B/512B  
パーティションテーブル: msdos  
ディスクフラグ:   
  
番号  開始    終了   サイズ  タイプ   ファイルシステム  フラグ  
 1    1049kB  316MB  315MB   primary  fat16             lba  
 2    316MB   852MB  537MB   primary  linux-swap(v1)  
  
# 上にある ディスク /dev/mmcblk0が31GBなのを確認  
# そこに記載のある要領で改めてパーティションを作成  
(parted) mkpart primary 852M 31.0GB                                         
エラー: パーティション 3 (/dev/mmcblk0 上)  
に書きこまれましたが、カーネルに変更を伝えることができませんでした。おそらく、使用中だったのが原因だと思われます。そのため、古いパーティション情報がそのまま使われます。さらなる変更をする前に再起動してください。  
無視(I)/Ignore/取消(C)/Cancel? i                                            
(parted) p                                                                  
モデル: SD SA32G (sd/mmc)  
ディスク /dev/mmcblk0: 31.0GB  
セクタサイズ (論理/物理): 512B/512B  
パーティションテーブル: msdos  
ディスクフラグ:   
  
番号  開始    終了    サイズ  タイプ   ファイルシステム  フラグ  
 1    1049kB  316MB   315MB   primary  fat16             lba  
 2    316MB   852MB   537MB   primary  linux-swap(v1)  
 3    852MB   31.0GB  30.2GB  primary  ext4  
  
(parted) quit                                                               
通知: 必要であれば /etc/fstab を更新するのを忘れないようにしてください。  

ここまでで一旦前準備が完了します。
まだこのままではディスクの設定は完了していません。

#  /dev/rootに、まだ要領が未反映  
$ df -h  
ファイルシス   サイズ  使用  残り 使用% マウント位置  
/dev/root        2.0G  683M  1.2G   38% /  
devtmpfs         459M     0  459M    0% /dev  
tmpfs            463M     0  463M    0% /dev/shm  
tmpfs            463M   12M  451M    3% /run  
tmpfs            463M     0  463M    0% /sys/fs/cgroup  
/dev/mmcblk0p1   300M   67M  234M   23% /boot  
tmpfs             93M     0   93M    0% /run/user/0  
  
# ディスク確認  
$ fdisk -l /dev/mmcblk0  
Disk /dev/mmcblk0: 31.0 GB, 31046238208 bytes, 60637184 sectors  
Units = sectors of 1 * 512 = 512 bytes  
Sector size (logical/physical): 512 bytes / 512 bytes  
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト  
Disk label type: dos  
ディスク識別子: 0x000a4da3  
  
  デバイス ブート      始点        終点     ブロック   Id  システム  
/dev/mmcblk0p1            2048      616447      307200    c  W95 FAT32 (LBA)  
/dev/mmcblk0p2          616448     1665023      524288   82  Linux swap / Solaris  
/dev/mmcblk0p3         1665024    60637183    29486080   83  Linux  
  
# サイズの設定  
$ resize2fs /dev/mmcblk0p3  
resize2fs 1.42.9 (28-Dec-2013)  
Filesystem at /dev/mmcblk0p3 is mounted on /; on-line resizing required  
old_desc_blocks = 1, new_desc_blocks = 4  
The filesystem on /dev/mmcblk0p3 is now 7371520 blocks long.  
  
# 要領が増えていることを確認  
$ df -h  
ファイルシス   サイズ  使用  残り 使用% マウント位置  
/dev/root         28G  687M   26G    3% /  
devtmpfs         459M     0  459M    0% /dev  
tmpfs            463M     0  463M    0% /dev/shm  
tmpfs            463M   12M  451M    3% /run  
tmpfs            463M     0  463M    0% /sys/fs/cgroup  
/dev/mmcblk0p1   300M   67M  234M   23% /boot  
tmpfs             93M     0   93M    0% /run/user/0  

これでディスクの要領は確保できました。

ネットワーク設定

次はwifiの設定です。
私は事情があり設定に苦戦しましたが、おそらく通常であれば以下のように設定すればwifiが利用できると思います。

wifiバイスの有効化

Raspberry piのCentOS7では最初無線デバイスが有効になっていないようです。

$ nmcli d  
デバイス  タイプ    状態      接続   
eth0      ethernet  接続済み  eth0   
lo        loopback  管理無し  --    

これを以下の流れで有効化します。

これでraspberry piファームウェアが更新されます。

$ yum -y install git  
$ git clone https://github.com/RPi-Distro/firmware-nonfree.git  
$ mv /lib/firmware/brcm{,.org}  
$ cp -R firmware-nonfree/brcm80211/brcm /lib/firmware/brcm  
$ curl -L --output /usr/bin/rpi-update https://raw.githubusercontent.com/Hexxeh/rpi-update/master/rpi-update  
$ chmod +x /usr/bin/rpi-update  
$ rpi-update  
$ reboot  

再起動したらデバイスの確認です。

$ nmcli d  
デバイス  タイプ    状態      接続   
eth0      ethernet  接続済み  eth0   
wlan0     wifi      切断済み  --     
lo        loopback  管理無し  --    

これでwifiが使えます。

wifiの設定追加

以後サーバ起動時に自動でwifiを有効にできるよう設定していきます。

# ssidには自分が利用するwifiのssidを設定してください。  
$ nmcli c add ifname wlan0 con-name wlan0 type wifi ssid hogehoge  
接続 'wlan0' (95db4014-f3f2-4729-a71b-8854c9293b71) が正常に追加されました。  
  
# ipv4.addresses, gateway, dnsなどは適宜自分の環境に合わせて設定します。  
# 私の家だと以下のようになっています。  
$ nmcli c m wlan0 ipv4.method manual ipv4.addresses 192.168.11.15/24 ipv4.gateway 192.168.11.1 ipv4.dns 8.8.8.8  
  
# 有線接続は不要になるため、私は落としています。  
$ nmcli c m etn0 connection.autoconnect no  
  
# ipv6についても使わないので一旦落としました。  
$ nmcli c m wlan0 ipv6.method ignore  
  
# 以下の設定を行うことで、wifi接続時のパスワード入力が自動化できます (たぶん)  
$ nmcli con mod wlan0 wifi-sec.key-mgmt wpa-psk  
$ nmcli con mod wlan0 wifi-sec.psk fugafuga  

パスワード設定が (たぶん) になっているのは、私は設定前に先に手動でファイルを作ってしまっていたからです。
私は以下の手順を実行しつつ、いろいろ他の試行錯誤をする中で上記の設定も行っているため、どちらが正なのか正直不明な状態です。

$ vi /etc/sysconfig/network-scripts/keys-wlan0  
$ cat /etc/sysconfig/network-scripts/keys-wlan0  
WPA_PSK=fugafuga  

ただなんにしても、keys-<デバイス名>のファイルを参照してパスワードを補完してくれているのは間違いないかと思います。

これでreboot後も最初からwifiに繋がっていれば設定は完了です

無線同士のssh接続がうまくいかない場合

今回私がハマったのこの件です。
おそらく発生する方は少ないと思いますが、私の環境では無線のみとしたraspberry piに、無線を利用しているmacからsshが繋がらなくなってしまいました。

その時にいろいろ動作を試したところ、以下のような動きになっていました。
[現象]
wifi接続中のmacからwifi接続のみとしたraspberry pisshが繋がらない
tcpdumpで通信をみたところ、そもそもraspberry piに通信が届いていない
raspberry piからmacへも通信が届いていなさそう
・家にある他の有線サーバからraspberry piへは繋がる
raspberry piを有線接続にすると繋がる
・有線の時無線側のipを指定してsshしても、有線側で通信が行われている
firewallを無効化しても変わりなし

正直意味がわからず、なんとなくルータが怪しいのではないかと思いいろいろ見ていましたがルータの設定は問題なさそうでした。
プライバシーセパレータも無効になっていました。

結果的には以下の対応で解消しました。
・ルータのファームウェアを最新に更新

どうも、バッファローのルータでは昔無線同士の通信がうまくいかないというバグがあったようです。
それがファームウェア更新を怠っていたために今になって発生したということです。

サーバの設定を見ても何が何だかわからないわけですね。
ハマりました。

参考サイト

今回は参考というか、wifi設定以外は引用しているだけといっていいレベルなので指摘されたらすぐ消そうと思います。

[参考/引用元]
Raspberry Pi 3 へCentOS7導入からWifi無線LAN接続まで設定メモ

雑感

ついにお手軽centosが使えるようになるということで本当にいい時代になりました。
久しぶりのブログ更新になりますが、私は生きています。

エンジニアというよりも「システムのわかる便利屋さん」みたいなことばかりしていますが、早くエンジニアリングを勉強しなおしたいですね。
仕事をご一緒させていただいたエンジニアさんがモンスター系の方で、刺激を受けました。
あぁレベル違うわ、世界レベルの人だわこれ、という感じです。

私はその頃フロントとしてお客様と電話、メール、エクセルをやりとりしまくる日々なのでした。
あとコード読んでバグ発見と原因調査。

ZabbixでSSL証明書期限チェック

zabbixは初期状態でhttps系の監視が微妙なため、証明書期限の監視設定などを行ってみたいと思います。

私が利用しているZabbixは2.2系になります。

SSL証明書期限チェック設定

今回は監視用のシェルを配置し、それをzabbixから有効にするという流れで設定を行います。

シェル配置フォルダ設定

Zabbix内で利用するshellを配置するフォルダを設定していきます。

root@raspberrypi:~# mkdir /etc/zabbix/externalscripts  
root@raspberrypi:~# vi /etc/zabbix/zabbix_server.conf  
root@raspberrypi:~# diff -u /etc/zabbix/zabbix_server.conf.org /etc/zabbix/zabbix_server.conf  
--- /etc/zabbix/zabbix_server.conf.org  2015-10-26 01:02:41.151018462 +0900  
+++ /etc/zabbix/zabbix_server.conf  2015-11-21 17:34:48.699559203 +0900  
...  
@@ -455,6 +456,7 @@  
 # Mandatory: no  
 # Default:  
 # ExternalScripts=${datadir}/zabbix/externalscripts  
+ExternalScripts=/etc/zabbix/externalscripts  
  
root@raspberrypi:~# systemctl restart zabbix-server  

ExternalScripts用のフォルダを作成して、そこを指定していますね。
もともとのコメントでは何か変数が埋め込まれているのですが、その変数がどこに記述されているのかよくわからなかったのでベタで記述しました。

監視時利用シェルを取得

おそらくどこか海外の方が作成してくれているシェルを拝借していきます。

root@raspberrypi:~# cd /etc/zabbix/externalscripts  
root@raspberrypi:/etc/zabbix/externalscripts# wget http://www.pixelbeat.org/scripts/timeout  
root@raspberrypi:/etc/zabbix/externalscripts# wget http://prefetch.net/code/ssl-cert-check  

シェルはあまり強くないのでちゃんと読んでいないのですがtimeoutスクリプトでは、実行したコマンドが無限ループしてしまったりwaitしてしまったときにjobをkillするっぽいですね。
ssl-cert-checkスクリプトではsslの状態をチェックしているのですかね。

監視用のシェルを作成
先ほど取得した2つのシェルを利用して、zabbix用のシェルを作成します。
作成しますといいますが、既に作成してくれている方がいるのでそれを利用しました。

nekoruri/ssl-cert-check.sh
こちらのリンク先にあるシェルをサーバに配置しましょう。
私はviでコピーしちゃいました。

root@raspberrypi:/etc/zabbix/externalscripts# vi ssl-cert-check.sh  
root@raspberrypi:/etc/zabbix/externalscripts# chmod 755 *  

また最後に取得したシェルの権限を変更しています。
私は面倒だったので755としていますが、本当は以下の方がよいかと思われます。
あってるか検証はしていません。

chown www-data:www-data *  
chmod 700 *  

ここまででファイル作成は完了です。

Zabbix管理画面から設定

こちらについては補充.infoさんの記事を参考にして行いました。

画面が少し違いますが、だいたい同じです。
zabbix管理画面のメニューから[設定] -> [ホスト]と遷移し、監視を行いたいホストを選択。
その後、ホストの管理画面にあるタブから[アイテム]のリンクを選択し、[アイテムの作成]からアイテムを作成します。

一応設定を行った画面を貼ります。
zabbix_証明書アイテム設定

これにて完了です。

あとがき

一応忘れないように、個人のredmineにも期限は登録しているのですが監視させるのが一番安心ですよね。
ドメインの期限についてもできたらいいなぁと思うのですが、それは果たしてできるのでしょうか。

RaspberryPi2のFedora22にOpenVPN構築

コツコツと以前購入してoverclockしたraspberry pi2にOpenVPNを構築していました。
iPhoneでしか動作検証していませんが、iPhoneで繋がるならPCも繋がるでしょう。
Proxyサーバ立てておけばよかったと思った瞬間ですね。

今回は以下のものに導入してみました。
[VPNサーバ]
・Fedora22
・RaspberryPi2

今回は主にVPNサーバー構築(OpenVPN)を参考にしております。fedora22とかcenots7系だとfirewall等細かい部分が違いますが、全体としては同じような手順を踏んでいます。

まえがき

せっかくなので、最初に私が何故vpnを構築しようと考えたかということを記述しておきます。
私なりに調べた結果、そう思っているだけなので間違っているのか正しいのかは定かではありません。

  1. vpnが構築したかった。
  2. 屋内のサーバ複数あるため、いろいろ構築しているとルータのポートフォワードが増えてしまう
  3. 屋内のサーバそれぞれにhttps設定をするのが面倒臭い

1は手段と目的が逆なので置いておきます!

2ですが、屋内にいろいろ立てていくと家にあるルータに設定するポートフォワードの設定が増えていってしまいます。
1箇所開けておくだけなら良いのですが、これが4個、5個と増えていくとそれだけ脆弱になっていくということです。
また穴ごとにセキュリティ対策が必要になり、面倒だったり漏れが出たりしそうで管理しきれない(したくない)と感じました。
そこでvpnを構築してしまえば空いているのでvpnのポートとvpnサーバへのアクセスだけになり、その部分だけセキュアにしておけば基本大丈夫となるわけですね。
という割には、設定が細かく調べきれてないんですけどね。

3についてはssl証明書入れてないので通信がhttpで危ないので、ポートフォワードだとどうなの? ということです。
vpntls通信にしてしまえば、その通信の中でhttpを利用していてもvpn部分で暗号化されているのでhttpsになっているのと同じことになる(はず)。

というわけで、vpn導入に踏み切りました。
本音のところは1が動機の90%なんですけどね!

OpenVPNのインストール

パッケージのインストール

まずOpenVPNのインストールをしていきます。
構築時の2015/11/23時点ではFedora22のdnfでインストールできるopenvpnのバージョンは2.3.8です。

公式サイトからダウンロードできる最新も2.3.8のようでしたので、今回はdnfから導入を行なっていきます。
と言ってはいますが、wgetからインストールしようとしたらビルドで落ちてしまい原因が全く解決できなかったので諦めてdnfにしたというのが本音です。

[root@fedora-pi ~]# dnf install openvpn openssl  

認証局構築ツールのインストール

OpenVPNではeasy-rsa3という認証局構築のパッケージを利用しますので、そちらを導入していきます。

[root@fedora-pi ~]# wget https://github.com/OpenVPN/easy-rsa/archive/master.zip  
[root@fedora-pi ~]# unzip master.zip  
[root@fedora-pi ~]# cp -r easy-rsa-master/easyrsa3/ /etc/openvpn/  
  
# 不要となったファイルを削除  
[root@fedora-pi ~]# rm -rf easy-rsa-master/  
[root@fedora-pi ~]# rm -f master.zip  

認証局作成

まずは導入したeasy-rsa3を初期化します。

[root@fedora-pi ~]# cd /etc/openvpn/easyrsa3/  
[root@fedora-pi easyrsa3]# ./easyrsa init-pki  
  
init-pki complete; you may now create a CA or requests.  
Your newly created PKI dir is: /etc/openvpn/easyrsa3/pki  

出力を見ると分かりますが、認証局によって出力されるファイルを配置するフォルダを作成してくれているようです。
続いて認証局を作成します。
また途中でパスフレーズの入力を求められます。
ここで入力したものは今後何かと入力をすることが出てくるのでちゃんと覚えておきましょう。

[root@fedora-pi easyrsa3]# ./easyrsa build-ca  
Generating a 2048 bit RSA private key  
....+++  
...........................................+++  
writing new private key to '/etc/openvpn/easyrsa3/pki/private/ca.key.8BIwtMglzh'  
Enter PEM pass phrase:  
Verifying - Enter PEM pass phrase:  
-----  
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.  
-----  
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:hogehoge  
  
CA creation complete and you may now import and sign cert requests.  
Your new CA certificate file for publishing is at:  
/etc/openvpn/easyrsa3/pki/ca.crt  

途中でCAを入力する箇所がありますが、自分で指定しても良いですし、未入力のままエンターでも良いです。
これでcaファイルが作成されました。

DH鍵の生成

鍵通信を行う際に利用するDH鍵を作成します。
なんでこれを行うのかというのはDH鍵交換に存在する脆弱性「Logjam」、HTTPSなどのプロトコルに影響のページをご確認ください。
これに限らず、仮に通信を傍受されても解読されづらく、もしくは実質解読不可能にするために行なっているということでしょうかね。

# logjam等の脆弱性への防衛手段としてdhパラメータを生成  
[root@fedora-pi easyrsa3]# ./easyrsa gen-dh  
Generating DH parameters, 2048 bit long safe prime, generator 2  
This is going to take a long time  
()  
..++*++*  
  
DH parameters of size 2048 created at /etc/openvpn/easyrsa3/pki/dh.pem  

ちなみにOCしたraspi2で、だいたい45分くらいかかったんじゃないかと思います。
結構時間がかかるものみたいです。

サーバ用秘密鍵と証明書作成

次にサーバ側の秘密鍵と証明書を作成します。
今回はパスフレーズはなしで実行しています。
パスフレーズを設定する場合にはnopassオプションを外せばOKです。

[root@fedora-pi easyrsa3]# ./easyrsa build-server-full server nopass  
Generating a 2048 bit RSA private key  
.................+++  
........................................................................................+++  
writing new private key to '/etc/openvpn/easyrsa3/pki/private/server.key.newe37otTg'  
-----  
Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf  
Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:  
Check that the request matches the signature  
Signature ok  
The Subject's Distinguished Name is as follows  
commonName            :ASN.1 12:'server'  
Certificate is to be certified until Nov  7 15:50:09 2025 GMT (3650 days)  
  
Write out database with 1 new entries  
Data Base Updated  

証明書廃止リストの作成

証明書の廃止リストを生成するには廃止された証明書が必要なので、リスト作成のために一旦ダミーの証明書を作成してリストの種にしていきます。

まずダミーの証明書を作成します。

[root@fedora-pi easyrsa3]# ./easyrsa build-client-full dummy nopass  
()  

続いて証明書を廃止します。

[root@fedora-pi easyrsa3]# ./easyrsa revoke dummy  
()  

最後に廃止リストを作成します。

[root@fedora-pi easyrsa3]# ./easyrsa gen-crl  
Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf  
Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:  
  
An updated CRL has been created.  
CRL file: /etc/openvpn/easyrsa3/pki/crl.pem  
[root@fedora-pi easyrsa3]# chmod o+r /etc/openvpn/easyrsa3/pki/crl.pem  
[root@fedora-pi easyrsa3]# chmod 701 pki  

最後の権限設定を行わないと、open vpnからファイルが見えなくなってしまい接続時にエラーとなるので忘れないよう気をつけて下さい。
別のフォルダに移動させて管理しても良いです。

これで認証局や証明書作成等については一通り準備完了です。

OpenVPNの設定

最初にインストールしたOpenVPNの設定を行っていきます。
ちなみに使うdiffに-uオプションつけるようにしました。こっちの方が変更がわかりやすいので。

# tls認証鍵作成  
[root@fedora-pi ~]# openvpn --genkey --secret /etc/openvpn/ta.key  
[root@fedora-pi ~]# cp /usr/share/doc/openvpn/sample/sample-config-files/server.conf /etc/openvpn/  
[root@fedora-pi ~]# diff -u /usr/share/doc/openvpn/sample/sample-config-files/server.conf /etc/openvpn/server.conf   
--- /usr/share/doc/openvpn/sample/sample-config-files/server.conf   2015-07-17 14:43:32.000000000 +0900  
+++ /etc/openvpn/server.conf    2015-11-23 18:16:18.139362405 +0900  
@@ -75,14 +75,20 @@  
 # Any X509 key management system can be used.  
 # OpenVPN can also use a PKCS #12 formatted key file  
 # (see "pkcs12" directive in man page).  
-ca ca.crt  
-cert server.crt  
-key server.key  # This file should be kept secret  
+;ca ca.crt  
+;cert server.crt  
+;key server.key  # This file should be kept secret  
+  
+ca easyrsa3/pki/ca.crt  
+cert easyrsa3/pki/issued/server.crt  
+key easyrsa3/pki/private/server.key  
   
 # Diffie hellman parameters.  
 # Generate your own with:  
 #   openssl dhparam -out dh2048.pem 2048  
-dh dh2048.pem  
+#dh dh2048.pem  
+;dh dh.pem  
+dh easyrsa3/pki/dh.pem  
   
 # Network topology  
 # Should be subnet (addressing via IP)  
@@ -140,6 +146,7 @@  
 # back to the OpenVPN server.  
 ;push "route 192.168.10.0 255.255.255.0"  
 ;push "route 192.168.20.0 255.255.255.0"  
+push "route 192.168.11.0 255.255.255.0"  
   
 # To assign specific IP addresses to specific  
 # clients or if a connecting client has a private  
@@ -241,7 +248,7 @@  
 # a copy of this key.  
 # The second parameter should be '0'  
 # on the server and '1' on the clients.  
-;tls-auth ta.key 0 # This file is secret  
+tls-auth ta.key 0 # This file is secret  
   
 # Select a cryptographic cipher.  
 # This config item must be copied to  
@@ -264,8 +271,8 @@  
 #  
 # You can uncomment this out on  
 # non-Windows systems.  
-;user nobody  
-;group nobody  
+user nobody  
+group nobody  
   
 # The persist options will try to avoid  
 # accessing certain resources on restart  
@@ -288,6 +295,7 @@  
 # or the other (but not both).  
 ;log         openvpn.log  
 ;log-append  openvpn.log  
+log-append  /var/log/openvpn/openvpn.log  
   
 # Set the appropriate level of log  
 # file verbosity.  
@@ -302,3 +310,6 @@  
 # sequential messages of the same message  
 # category will be output to the log.  
 ;mute 20  
+  
+management localhost 7505  
+crl-verify easyrsa3/pki/crl.pem  

基本的には参考にさせていただいたサイトの通りです。
ファイルの配置場所だけ、ちょっと変えています。

またuser, groupの権限をnobodyに設定しているのはroot権限で動作するのを防ぐためのようです。
万が一の際にroot権限で動作しているとサーバをグチャグチャに攻撃されてしまうので影響範囲を可能な限り少なくするのが大切ということですね。

またmanagementの設定をするとt、telnet localhost 7505などで現在接続中のクライアントを切断したりの管理機能が使えるみたいです。

ログ設定

ログフォルダの指定などをしたので、フォルダを作成します。

[root@fedora-pi ~]# mkdir /var/log/openvpn  
[root@fedora-pi ~]# vi /etc/logrotate.d/openvpn  
[root@fedora-pi ~]# cat /etc/logrotate.d/openvpn   
/var/log/openvpn/openvpn.log {  
    missingok  
    notifempty  
    sharedscripts  
    postrotate  
        systemctl restart openvpn 2>&1 > /dev/null || true  
    endscript  
}  

ついでにlogrotateも設定します。
そのうちlogrotateも全体的にしっかりと設定して、バックアップとったりしておきたいですね。

firewalld設定

この設定ですが、正直ちゃんと理解していません。
後々もう少し範囲を絞った適切な設定をしていきたいと思います。

[root@fedora-pi ~]# firewall-cmd --add-service=openvpn --permanent  
[root@fedora-pi ~]# firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE  
[root@fedora-pi ~]# firewall-cmd --zone=trusted --add-interface=tun0  
[root@fedora-pi ~]# echo 1 > /proc/sys/net/ipv4/ip_forward  
[root@fedora-pi ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf  
  
# 私個人的な設定。homeネットワーク以外からssh等を排除  
[root@fedora-pi ~]# firewall-cmd --add-source=10.8.0.0/24 --zone=home --permanent  
success  
[root@fedora-pi ~]# firewall-cmd --add-source=192.168.11.0/24 --zone=home --permanent  
success  
[root@fedora-pi ~]# firewall-cmd --remove-service=ssh --zone=public --permanent  
success  
[root@fedora-pi ~]# firewall-cmd --reload  
success  

firewall-cmd --zone=trusted --add-interface=tun0」の設定あたりから、よくわからないからフルオープンという匂いがしています。
一応この設定で、vpn接続後に家にある他のサーバ上にあるredmine等に接続できています。

OpenVPNの起動

何気に私はここでつまづきました。

[root@fedora-pi src]# ln -s /lib/systemd/system/openvpn\@.service /etc/systemd/system/multi-user.target.wants/openvpn\@server.service  
[root@fedora-pi src]# systemctl -f enable openvpn@server.service  
Removed symlink /etc/systemd/system/multi-user.target.wants/openvpn@server.service.  
Created symlink from /etc/systemd/system/multi-user.target.wants/openvpn@server.service to /usr/lib/systemd/system/openvpn@.service.  
[root@fedora-pi src]# systemctl start openvpn@server.service  

というのもサービスの名前に@が入っているなんて今まで経験したことがなかったので、コンパイルミスで残ってる途中生成ファイルか何かだと思い込んでいたのです。
普通にそのまま名前だったみたいです。

以上で、openvpnのインストール設定は完了です。
次はクライアント証明書を作成して接続です。

クライアント設定

open vpnサーバに接続するためにクライアントの設定を行います。

iPhoneの設定

まだPCは試してないので、今回はiPhoneから接続してみます。
もし家のwifiに繋いでいる方は、一旦wifiではなくキャリアの回線に戻してくださいね。

クライアント証明書作成(サーバ側)

まずは証明書を作成します。これはサーバで実行します。

[root@fedora-pi easyrsa3]# ./easyrsa build-client-full iphone nopass  
Generating a 2048 bit RSA private key  
...........................................................................................................+++  
.......+++  
writing new private key to '/etc/openvpn/easyrsa3/pki/private/iphone.key.wQQzrNJXXe'  
-----  
Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf  
Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:  
Check that the request matches the signature  
Signature ok  
The Subject's Distinguished Name is as follows  
commonName            :ASN.1 12:'iphone'  
Certificate is to be certified until Nov 19 15:38:32 2025 GMT (3650 days)  
  
Write out database with 1 new entries  
Data Base Updated  

iPhoneOpenVPNアプリはパスフレーズに対応していないようなので、nopassで作成します。

client用設定ファイル作成

続いてiPhonevpnクライアント用の設定ファイルを作成します。

[root@fedora-pi ~]# cp /usr/share/doc/openvpn/sample/sample-config-files/client.conf /etc/openvpn/client.conf  
[root@fedora-pi ~]# vi /etc/openvpn/client.conf  
[root@fedora-pi ~]# mv /etc/openvpn/client.conf /etc/openvpn/iphone_client.conf  
[root@fedora-pi ~]# diff -u /usr/share/doc/openvpn/sample/sample-config-files/client.conf /etc/openvpn/iphone_client.conf  
--- /usr/share/doc/openvpn/sample/sample-config-files/client.conf   2015-07-17 14:43:32.000000000 +0900  
+++ /etc/openvpn/iphone_client.conf 2015-11-23 01:51:49.059753830 +0900  
@@ -39,8 +39,9 @@  
 # The hostname/IP and port of the server.  
 # You can have multiple remote entries  
 # to load balance between the servers.  
-remote my-server-1 1194  
+;remote my-server-1 1194  
 ;remote my-server-2 1194  
+remote hogehoge.ddns 1194  
   
 # Choose a random host from the remote  
 # list for load-balancing.  Otherwise  
@@ -85,9 +86,9 @@  
 # a separate .crt/.key file pair  
 # for each client.  A single ca  
 # file can be used for all clients.  
-ca ca.crt  
-cert client.crt  
-key client.key  
+;ca ca.crt  
+;cert client.crt  
+;key client.key  
   
 # Verify server certificate by checking that the  
 # certicate has the correct key usage set.  
@@ -105,7 +106,8 @@  
   
 # If a tls-auth key is used on the server  
 # then every client must also have the key.  
-;tls-auth ta.key 1  
+;tls-auth [inline] 1  
+key-direction 1  
   
 # Select a cryptographic cipher.  
 # If the cipher option is used on the server  
@@ -122,3 +124,101 @@  
   
 # Silence repeating messages  
 ;mute 20  
+  
+  
+<ca>  
+-----BEGIN CERTIFICATE-----  
()  
+-----END CERTIFICATE-----  
+</ca>  
+<cert>  
+-----BEGIN CERTIFICATE-----  
()  
+-----END CERTIFICATE-----  
+</cert>  
+<key>  
+-----BEGIN PRIVATE KEY-----  
()  
+-----END PRIVATE KEY-----  
+</key>  
+<tls-auth>  
+-----BEGIN OpenVPN Static key V1-----  
()  
+-----END OpenVPN Static key V1-----  
+</tls-auth>  

remoteには接続しに行くopen vpnサーバを指定します。
私の場合は、dnsddnsを利用しているのと家にルータがあるのでそこからポートフォワードの設定をしています。
特に問題なく通信は通っているので、家にネット環境に合わせた指定をしてもらえればだいたい動くと思います。

また証明書などのファイルはファイルそのものを指定して記述することもできるのですが、今回は設定ファイルに直接記述してみました。
ちょっと前までは tls-auth [inline] 1 の部分のように[inline]という指定が必要だったりしたみたいなのですが、現在はタグがあれば良いみたいです。
key-direction設定がないとtls-authが有効にならないようなので、忘れないようにしましょう。

私の場合にはファイルの中身はそれぞれ以下から取っています。
ca: /etc/openvpn/easyrsa3/pki/ca.crt
cert: ls /etc/openvpn/easyrsa3/pki/issued/iphone.crt
key: ls /etc/openvpn/easyrsa3/pki/private/iphone.key
tls-auth: /etc/openvpn/ta.key

あとは作成したファイルを自分のPCにダウンロードして、iTunesからiPhoneに転送してください。
そのときファイルの拡張子をovpnにするのを忘れないように。
細かい手順はiPhoneやiPad (iOS) でOpenVPNを使ってみよう!を参考にしていただいた方がわかりやすいかと思います。

以上でopen vpnの設定は完了です。

あとがき

今回はopen vpnの導入ということでコマンドを打ち込むぶんにはそんな大した量ではないのですが、そもそもvpnってなんだとか、通信が安全なのかとか調べてたら時間がかかりました。

もしうまく繋がらないということがあればtcpdumpなどを利用して通信がそもそも届いているか等調べてみましょう。

[root@fedora-pi ~]# dnf install tcpdump  
[root@fedora-pi ~]# tcpdump -i eth0 -n port 1194  

tcpdumpは何かと便利なので、まだあまり使ったことがない方はぜひ使ってみてください。

また今後はvpnに接続があったときにメールで通知したりしたいなぁと思っています。
できるのかなぁ?

DDNS(No-IP)をcronで更新

DDNSを利用してzabbix agentを導入できないかと思い、ひとまずDDNSの設定を行いました。
でもopen vpn導入も考えているのですが、これだと結局ルータのポートフォワード用の穴が増えてダメじゃん、と思わなくない。

では、早速導入。

DDNSとは

このタイトルで明確に検索している方にはもはや説明は不要ですがダイナミックDNSの略になります。
DDNSで実現できることは「固定IPがなくても名前解決で自宅を特定可能にする」ことです。

DDNSを提供してくれているサービスに、特定のドメインサブドメインをお借りしてAレコードを登録するわけですね。

そこで何がダイナミックかというと、TTLの短さです。(と僕は勝手に言います。)

dig mydns.jp  
# mydns.jp.        300 IN  SOA mydns.jp. root.mydns.jp. 1420604081 600 180 600 300  

こんな感じで、TTLが5分と短いです。
ダイナミックだ。

これにより、いつ変動してしまうかわからない家の動的IPに対して5分以内で追随可能になるわけですね。

DDNSサービス

DDNSサービスにはいくつか、有名どころがあります。
例えば、mydnsですね。
これは非常に有名で、日本語サイトでもあるので利用者も多いのではないでしょうか?

ですが、今回はNo-IPという海外のサービスを利用していきます。
理由は単純明快。
MyDNSは通信がhttpだから。

ユーザ登録も、定期実行する通信も全部丸見えです。
戦慄します。無料で提供してくださっているので、余計な経費はかけられないということでしょうかね。

No-IP設定

正直参考サイトがいくつかあるので、ここでは割愛します。
PC遠隔操作に便利な無料ダイナミックDNS『no-ip』のアカウント・設定方法

こちらのサイトが、比較的今のサイトに近くわかりやすかったです。

onamae.comなどDNSを自分で利用したことがある人参考サイトがなくともなんとなく操作がわかると思います。
そうでない方は、ちょっとわかりづらいかも?

cronの設定

アカウントの作成が完了したら、今度はcronの設定です。
家庭内にあるサーバでもなんでも、常時起動しているマシンに対して定期実行のコマンドを登録しましょう。
私はraspbianで定期実行させています。

# crontab -e  
# crontab -l  
*/5 * * * * curl -s "https://login_id:password@dynupdate.no-ip.com/nic/update?hostname=yourdomain" > /dev/null  

登録時のlogin idやpassword、取得したドメインを指定していきます。
ドメインというかホストという方が正しいのかな。

またcronに登録する前に以下の部分のみを実行して、正しく反応があるかどうか確認することをお勧めします。

$ curl -s "https://login_id:password@dynupdate.no-ip.com/nic/update?hostname=yourdomain"  

これで設定は完了です。
またCentOS7以降を利用している場合には、デフォルトがanacronで過去のOSであったnoanacronとは違うのでお気をつけください。

これにて設定は完了です。

あとがき

DDNSの設定をしてはみましたが、外にサーバが増えるたびにポートを解放していくことを思うと現実的じゃないなと考えています。
監視サーバは外で借りた方がいいんですかねぇ。
月額1000円前後としたって、台数が増えてくると地味に出費が痛いところです。

apache2.4でBOTからのアクセスを排除

私は何か数字が動くものを見るのが好きでgoogle analyticsのリアルタイム情報をよく見ているのですが、そこで不思議なアクセスに気づきました。
リファラがよくわからないサイトになっていて、サイトトップを表示しているものたちです。

どうやらこれがbotらしいということなので、アクセス制御を行ってみようと思います。

排除すべきアクセス

まずは排除すべきアクセスですが、私のサイトにアクセスしていた不思議なリファラを検索したら以下のページがでてきました。
https://w3g.jp/blog/block_referer-spam-bots

こちらにたくさんの怪しげなアクセスが列挙されていましたので、これを参考に設定を行ってみます。

apache2.4での設定方法

参考とさせていただいたサイトの設定方法を見たところどうやらapache2.2系のようです。
CentOS7以降はyumではデフォルトで2.4以降が入るのため、微妙に設定方法が違います。

今回はapache2.4系の方法で設定してみたいと思います。

# set env用設定ファイル作成  
[root@metal ~]# vi /etc/httpd/conf.d/drop-spams.conf  
  
# サイト設定の修正  
[root@metal ~]# diff /etc/httpd/conf.d/virtual-wordpress.conf.2015-11-11 /etc/httpd/conf.d/virtual-wordpress.conf  
7a8,12  
>   
>     <RequireAll>  
>       Require all granted  
>       Require not env spambot  
>     </RequireAll>  
21a27,31  
>   
>     <RequireAll>  
>       Require all granted  
>       Require not env spambot  
>     </RequireAll>  
[root@metal ~]# apachectl configtest  
Syntax OK  
[root@metal ~]# systemctl restart httpd  

まずは参考サイトにあったSetEnvをひたすら記述するファイルを作成して、排除したいspambotを管理します。
次に、virtual host設定をしてあるファイルに対してRequire設定を行います。

まずall grantedで全てのアクセスを許可して、そのあとにspambotになるものについては拒否しています。
diffの設定が二つあるのはhttp, httpsの両方に設定を行っているためです。
これ正直httpsの方だけで十分ですよね。

あとがき

最近バタバタしており、更新ができていなかったので簡単にですが更新。
現在Redmineの調整をしたり、OpenVPNの導入を行っているところです。
その前にDDNS設定が必要だったりと、しばらくは更新するための手順蓄積が必要そうです。