2013/02/24

Kansai.pm 第15回ミーティングに行ってきた&初LTさせてもらった

今日は、Kansai.pm 第15回ミーティングに行ってきました。
さらに図々しく、はじめてのLTもさせていただきました
主催者の若林さん(@nqounetさん)や懇親会主催者の@__papix__さんに
あらためてお礼申し上げます。ありがとうございました。 m(_ _)m♪

会場は大阪富国生命ビルにあるYahoo!さんのセミナールームでした!

早速、感想と反省文を書きたいと思います ><

私にとって今回が初の勉強会なのですが、まず...なんといっても...
刺激を受けることができ、開発意欲があがりましたw
(でも事実、自分の勉強の無さと浅さが...身に染みました...(;´д`)…。)
特に印象に残った発表を、書いていきたいと思います。

"「Webサービスのつくり方」のつくり方" @yusukebe さん

(えっと、まず、○ノアールやコメ○はノマドワークに最適という情報がww なるほどw)
http://www.slideshare.net/yusukebe/web-16710062

書籍 "Webサービスのつくり方" を執筆された話+もっと言いたかった事 でした。
この本は、perl本からのテーマ変更を経て、3年越しに実現された夢なのだとか...。
perlを使ったWebプログラミングの仕方ではなく、
自分たち(極少人数チーム)でWebサービスを立ち上げるお話になっていて...
Webサービスをいかに生み出し、それがどれだけ楽しいことか!”を教えてくれる本だそうです。

まだ私自身、この本は、Amazonのなか見検索でぱらっと見て、
目次を読んで....おもしろそうwwwと思って、ウィッシュリストに追加していた状態だったので...持っていないのです...。早速入手して読もうと思います。
(そして...読んでみたら?と本気で友人に推したい・・・。(切実))

原稿を執筆する際にMarkdownで書いてDropboxで共有管理していたこと。
Dropdownという自作アプリで原稿をHTML化して共有していたこと...。
(ちょうど、自分のLTネタでText::Markdownをにわかに使わせていただいたこともあって、タイムリーだなぁ〜...しかしアイデアが自分とは違うなぁ....(´・ω・`)とも思ったり...)

運営会社となるオモロキを立ち上げた際の話も勉強になりました。
  • 話し合いルールを暗黙の了解で。
    • みんながリーダーシップを発揮する。
    • 打ち合わせをダラダラしない。
    • 最初はメンバーの意見を否定しない。
    • マネタイズは後から。
楽しくやるのが一番.
私もやはり、そういうウェブ開発を仲間とやりとげたいなぁ...。
(ちなみに、ボケての開発はバックエンドはyusukebeさん 1人なのだとか。
プロジェクト的な
人数は7人、タイアップ企画などは3人とかで、その方がやはり意思決定が高速なのだそうです。ふむふむ。)

あと...yusukebeさんはMojolicious推しだということで!
  • Modelが不可知なのが良い
    (私も、好きなCPANモジュールを使おうという気楽さが好きです。)
  • MVCモデルで、PC/モバイルサイトを分けるときも、Modelにビジネスロジックを実装して共通化できるということ。
  • Modelの構造の組み方 (バックエンドのデータベースへのモジュール構造)も事例紹介がありました。
    (実際、私も迷っていたりするので...こういう事例はとてもありがたいんですw)
  • "Mojolicious本をKindle出版で出したい"という話も。めちゃくちゃ期待!
サーバの運用についての話もありました。
  • 当初はVPSで運用していたそうですが、VPSは2台程までがベスト
    それ以上はAWSなどクラウドのほうが良いとのこと。
    (なぜなら、管理も面倒だし、スケールするのに支払いの手間と時間が...。確かにめんどくさいですね...。)


"コピペと闘う (perlコピペコード検出器)" goccy さん


perlのソースコードを、独自のパーサで解析し、
ソースコードのコピペ(重複)部分を検出できるツールです。
検出結果はブラウザ上でもできて・・・コードに対して点数が表示され、
グラフという形で視覚的に閲覧できるというスグレモノでした。(しかも解析が高速。)

今回は、Mojoliciousと、Catalystのコードを例にして解析。
(うわっ!Riedelさ〜んwww!!>< )
Namespaceごとに解析が行われて、10秒ほどで、検出された行が出力されました。

それにしても、"Only perl can parse Perl"という言葉があるように、
Perlの構文解析は他言語より格段に難しいのですが...
そのパーサを作られたことがまずすごいww
(Perlのパーサ開発は正規表現まわりが特に辛いのだとか。この方はmixiでお仕事されているそうで。
パーサ書いちゃうってスゴイ!!のに...さらにすごい人がいっぱいいるとか...。mixi恐るべし。

ちなみに、mixiはNamespaceごとに開発してるので、問題があったNamespaceごとに、その担当グループにリファクタリングをお願いするんだそうです。)


"Cinnamon (simple deploy tool)" @shiba_yu36 さん


Capistranoがややこしいということで作られたデプロイツールだそうです。
シンプルで設定も楽、DSLで書けるぞ!!ということです。
https://github.com/kentaro/cinnamon

サンプルがこれ。
https://github.com/shibayu36/cinnamon-deploy-sample
(サーバの起動、再起動、最新状態の反映、依存モジュールのインストールなんかがサッと実行できます。)
任意のコマンドを実行するようになっているので、応用が効きそうですね。

Role=対象サーバ、Task=処理(実行したい任意のコマンド群) を定義し...
$ cinnamon production update
例えば、これで、productionなサーバに対して、アップデートTaskが一括実行できると。

実は...私、デプロイツールという言葉は知っているものの、
実際に使ったことは無かったのです。この機会に早速使ってみたいと思います。
(私など、単純に2台目以上ある〜などで、もうめんどくさくなるタイプですしw
ちなみに...あんまり”デプロイツール”を使っている人はいらっしゃらないようでした。・・・だけど、もう使わない手は無い。便利そうです。)

でも、shiba_yu36さんが言うに、
Capistranoも本当に使いこなせれば、やっぱり相当便利に使えてるのだけど、そこまでなかなか...なのだとか。



他のトークやLTも興味深いもの、面白いものがありましたww

Perl Ocean、既存や開発中のサービスにも連携したチャットサービスなどを容易に組み込めそう。
→ http://www.slideshare.net/lapis25/kansaipm15-perl-ocean

PerlはAcmeも楽しいですね!!エラーメッセージをネコにしたいwww

Unicodeな話は...私にはちょいと難しかったです(´;ω;`)

DBIx::Letency、O/Rマッパのベンチマーク!
Kansai.pmでORMのパフォーマンスチェッカの構想についてLTしてきた - ゆううきブログ
(それにしても、私のと比べものにならないくらい...役に立つ思い付きだ...。
私、若干気になるとか言いつつも他人ソース任せでしたから・・・自分でやるのは大切ですね。)


MTをCMSとしてもっと活用する。
プラグインが豊富 (&比較的難しくなく作れるらしい)
→ 一例: https://github.com/ogawa/mt-plugin-Minifier

あと、Kansai.pmの活動と、Perl入学式の話など。
特に今期(4月から)のPerl入学式には友人を誘って行ってみたいなぁ...という希望と、私も何かお手伝いできたらなぁ...と思ったり。


あ、ちなみに・・・私のLTネタは...
"半日で Markdown+SQLite3なWiki を作ってみた"でした。
普段使っているWikiクローンがMarkdownで書けないということで、そのまま話にした感じです。

約半日で、Markdown Wikiとしての基本機能は実装できました。CPANモジュール様々です! (認証機能こそ無いですが、世代管理や衝突チェックは実装済み。)

ひどいコードですが...(拙作 mojo_template についている、OAuth認証の残骸を残していたり)
https://github.com/mugifly/LtWiki

でも、Markdownのperl製Wikiクローンって見かけませんし、
SQLiteデータベースを使うものはさらに無いと思うので・・・
また時間がかかってもマトモなWikiに作り直せたらなぁ...と思ったりしています。
尚、安全性を考えた上でサンプルを一時的に公開していますが、さっさと認証機能実装して差し替えます。

まず反省から書くと・・・
  • 実は当初、ふつうにGoogle Driveのプレゼンテーションで作成していたのですが、どうもPreziが気になって...作りかけていたのを丸ごと捨ててww、初めてPreziを使いました。が、まだ自分でうまく扱えなくて...動きすぎ...見づらかったですね...。
  • ともかく、適切でない表現があったり、話す内容がまとめられていなかったりとプレゼンという面でも反省点は多かったです。内容も悪ふざけが...すみません。初なのにこのようなLTになってしまって。(また、perl本をもっと出してほしいなどと偉そうなことを言ってしまい申し訳ありませんでした。初心者故の希望です...。)
スライドを張っておきます:


それと...今回、boketeのステッカーをいただきましたw
早速、PCに貼っておきます。

あと、LTのドーナツ美味しかったです!ww

懇親会も楽しかったです。
私みたいなショボい学生ですが....。何より、エンジニアの方と話せて良かった!!
(内心、Webサービス系企業の興味が...。企画も....バックエンドも...やりたいな...。)

以上。勢いでガガッと記事を書いたら、長くなってしまいましたww
※間違い、勘違い等ありましたら、ご指摘をお願い致します。

紹介いただいたもの(特に気になったもの)は、休み中に試していけたらな〜と思います。

参加された皆さん、ありがとうございました m(_ _)m♪
次回もぜひ参加したいです。今度は...もっと勉強を深めていきます...。
(...マトモなCPANモジュールも一つでも思いついてリリースできれば...。)

p.s.
ここまで書いて、気づきましたw! 写真が一枚もないorz
カバンにコンデジ(S110)入れて持っていったのになぁ。...私としたことが。

[2013/02/24 12:00 一部追記]

2013/02/18

Jenkinsのスレーブノードを追加してみた

先日の記事(Hello, Jenkins. GitLab+Jenkins+perl(Mojolicious)でCIをしてみた)では
GitLab(Gitolite)を使っている環境に、Jenkinsをインストールして、
CIのためのシステム構築を行いましたが...
さらに他のマシンをスレーブとして追加することで、ビルドの負荷分散ができます。

今回は新しいVPSにもJenkinsをインストールして、スレーブにしてみました。
この記事では、スレーブを構築&設定する手順を、書いておきます。(自分用メモとしてw)
  • スレーブ側では、Jenkinsサービスを起動しておく必要はありません。
  • ビルドを行う度に、マスターのJenkinsがSSHを介してスレーブのシェルに接続し、スレーブ上のJenkinsの"スレーブエージェント"を実行する仕組みです。(sshを介して通信するので、特に両者間でVPNを張る必要もありません。)
    参照: Distributed builds - 日本語 - Jenkins Wiki
  • 今回、CIを行う対象のプロジェクトは、マスター上のGitLab(Gitolite)にリポジトリがあるものとします。(先日の記事の続きなので。)
尚、今回は鍵を2つ作成することになります。
  • [マスター側で作成する鍵] カギA  - 手順3で作成
    • マスターのJenkinsが、スレーブに接続するため の鍵。
    • 作成されたカギの公開鍵は、スレーブのauthorized_keysに登録します。
  • [スレーブ側で作成する鍵] カギB  - 手順5で作成
    • スレーブのJenkinsが、Gitリポジトリに接続するため の鍵。
    • 作成されたカギの公開鍵は、GitlabもしくはGitoliteに登録します。
(※ もっと良い手順がありましたら、ご教授お願いします!)


  1. [スレーブ] Jenkinsをインストール。
    (先日の記事 "Hello, Jenkins. GitLab+Jenkins+perl(Mojolicious)でCIをしてみた" を参照のこと。jenkinsサービスを開始する必要はありません。)
  2. [スレーブ] JREをインストール。
  3. [マスター] カギAを .sshディレクトリ(/var/lib/jenkins/.ssh/)に作成。
    $ sudo -u jenkins ssh-keygen
    > /var/lib/jenkins/.ssh/id_rsa_con_slave
  4. (マスター側の.sshディレクトリには既に、マスター自身のJenkinsが Gitリポジトリに接続するための鍵があるわけですので、今回は別の名前にします。)
  5. [スレーブ] カギAの公開鍵(id_rsa_con_slave.pub)の中身を、スレーブ上のJenkinsユーザのauthorized_keys (/var/lib/jenkins/.ssh/authorized_keys) に記述。
    $ sudo -u jenkins vi /var/lib/jenkins/.ssh/authorized_keys
    ssh-rsa ~~~~ jenkins@xxx
    ※ 但し、jenkinsユーザは、/etc/passwd上 で /bin/falseに設定されているので、/bin/bashに変更する。
    もしくは、他のユーザを作成する。(セキュリティ的には後者のほうが安全...か?)
  6. $ sudo -u root vi /etc/passwd
    ~~~~
    jenkins:x:xxx:yyy:Jenkins Continuous Build server:/var/lib/jenkins:/bin/bash
  7. [スレーブ] カギBを .sshディレクトリ(/var/lib/jenkins/.ssh/)に作成。
    $ sudo -u jenkins ssh-keygen
    > /var/lib/jenkins/.ssh/id_rsa
  8. [スレーブ] カギBをGitリポジトリへの接続に使えるよう、.ssh/configに記述。(先日の記事でのマスター側と同様。)
    $ sudo -u jenkins vi /var/lib/jenkins/.ssh/config
    Host example.com
        User gitolite
        Port xx
        Hostname example.com
        IdentityFile /var/lib/jenkins/.ssh/id_rsa
  9. [クライアント] カギBの公開鍵(id_rsa.pub)の中身を、GitLab(もしくはGitolite)のJenkinsユーザのSSH鍵に登録。
    (GitLabを使っているならば、先日の記事と同様に、Webブラウザからjenkinsアカウントでログインして、SSH Keys画面から鍵の追加を行います。)
  10. [スレーブ] known_hostsにGitリポジトリサーバの情報を登録するために、一旦、手動でgit cloneをします。
    $ cd /var/lib/jenkins/
    $ sudo -u jenkins git clone ssh://gitolite@example.com:xx/hoge.git
    > Are you sure you want to continue connecting (yes/no)? yes
    $ sudo -u jenkins rm hoge/ -R
    (cloneしてくるリポジトリは、jenkinsアカウントでgit cloneできるものなら何でもOK。cloneされたディレクトリは、すぐに削除して構いません。)
  11. [クライアント] マスターのJenkinsのノード管理画面で、ノードを追加する。

    • "ノード名": 適当
    • "同時ビルド数": 適当 (スレーブのコア数にするのが妥当)。
    • "リモートFSルート":  "/var/lib/jenkins/"
    • "起動方法":  "SSH経由でLinuxマシンのスレーブエージェントを起動"
    • "ホスト": スレーブのホスト名 or IPアドレス
    • "ユーザ名": "jenkins"
    • "ポート" スレーブのSSHデーモンのポート
    • "秘密鍵":  カギAの秘密鍵 ("/var/lib/jenkins/.ssh/id_rsa_con_slave")
  12. [スレーブ] 各プロジェクトのビルド環境を構築する。
    とりあえず手順9まで終えて、ビルドを実行してみると、まだ失敗することがわかると思います。
    ですので、例えば perlのプロジェクトをCIするのであれば、cpanmのインストールなり、perlのモジュールインストールなりを行います。先日の記事の後半どおり、マスター側と同様。
といった感じです。

スレーブ側では、JenkinsのWeb画面での設定も、ジョブ作成も必要ありません。
その都度、マスターのJenkinsがスレーブへ自動的に転送してくれます。

尚、さらに2台目、3台目のスレーブ...と追加していく場合には、
この記事の手順3は不要ですね。

2013/02/16

以前に作ったUNIX系サーバ用バックアップスクリプト (AmazonS3対応)

以前に作った"UNIX系サーバ用バックアップスクリプト"を公開しました。
任意のディレクトリとMySQLデータベースを、Amazon S3へバックアップできます。
一応、世代管理が可能です。また、ファイルは SquashFSでアーカイブされます。

ちょっと昔に必要に迫られて作ったものだったので...。
かなりのやっつけ仕事で...汚すぎるソースコードですが、一応、今もきちんと動きますので、公開することにしました ヘ(゚∀゚ヘ)w (CentOS 6.3で動作確認済。)
squashfs-tools と perlがあれば動きます。

https://gist.github.com/mugifly/4966246

改造してサーバのcrontabに登録するなり、印刷してゴミ箱にダンクするなり...
よろしければ、ご自由にどうぞ( ´∀`)b


このとおり、Gistに置いておきます。

2013/02/15

VPS複数台をL2TP/IPSec(xl2tpd+openswan)で接続 on CentOS 6

複数台のVPS(さくらのVPS)を、L2TP/IPSecでVPN接続することにしましたので、
自分用メモとして記事にします。今回は、とりあえず2点間接続を行います。
尚、3点間以上も同じ手順でクライアントを追加していくだけです。
(ちなみに目的は、MongoDBでReplicaSet、Shardingを行う為だったりしますw)
  • L2TPの実装: xl2tpd
  • IPSecの実装: openswan
    (昔はFreeS/WanというIPSecの実装があったそうですが、開発が止まっていて・・・。
    そこから派生して現在の主流となっているのが、openswanなんだそうです。なるほど。
サーバは、さくらのVPS (Cent OS 6.x 64bit) です。

記事の内容は試行錯誤の結果であり、間違っている可能性もあります。
もしご指摘、アドバイス等ありましたら、よろしくお願いします m(_ _)m

今回、以下の内容については、
を参考にさせていただきました。(感謝です!! m(_ _)m♪!)


まず、サーバ/クライアント共通の環境構築から。


はじめに、必要なパッケージをインストールします。
既に入っているものも多いかと思いますが...念の為。

$ sudo yum install gcc gmp gmp-devel flex bison libpcap-devel ppp
ところで、この記事では行いませんが・・・
openswanは
NSS(Mozillaによる証明書ライブラリ)による証明書認証に対応しています。後々から証明書に対応できるよう、NSSをインストールしておきましょう。
$ sudo yum install nss nss-devel nss-tools
(実際のところ、VPNを実運用するには、文字列だけでの認証では心許ないです。)

次に、openswanをソースコードからビルドしてインストールします。
(執筆時の最新版は、openswan-2.6.38です。 Amazon S3から配布されているんですね〜。
また...余談ですが、
openswanのサイトには自己署名の証明書が使われているようで、SSLエラーとなりました。ご注意を。)
$ wget https://s3-ap-northeast-1.amazonaws.com/openswanjp/openswan-2.6.38.tar.gz
$ tar zxf openswan-2.6.38.tar.gz
$ cd openswan-2.6.38/
ここでも、後々から証明書を使えるようにNSSサポートを有効にしておきましょう。
ドキュメント(docs/README.nss)によると、Makefile.incのオプションを弄るそうです。
$ vi Makefile.inc
~~~~
# Support for NSS crypto library (does not requires HAVE_THREADS)
# USE_LIBNSS uses pthreads by default.
USE_LIBNSS?=true
~~~~
(372行目付近に2箇所ありますが、USE_LIBNSS?をtrueにしておきます。)

あとはmakeしてインストールです。
$ make programs
$ sudo make install
次に、xl2tpdをビルドしてインストールします。
(執筆時の最新版は、xl2tpd-1.3.1です。ちなみに...EPELリポジトリからインストールする方法もありです。)
$ cd ..
$ wget https://github.com/xelerance/xl2tpd/archive/v1.3.1.tar.gz -O xl2tpd-v1.3.1.tar.gz
$ tar zxf xl2tpd-v1.3.1.tar.gz
$ cd xl2tpd-1.3.1/
$ make
$ sudo make install
さらに、起動用のコマンドをコピーしておきます。
$ su
# cp packaging/fedora/xl2tpd.init /etc/init.d/xl2tpd
# chmod +x /etc/init.d/xl2tpd
(※以降、シンタックスハイライトの都合上、コマンド文の色が黒色ですが、特にお気になさらずに(汗;))
また、/usr/local/sbin にインストールされたので、/usr/sbinからリンクを張ります。 
 # ln -s /usr/local/sbin/xl2tpd /usr/sbin/xl2tpd
サービスも登録しておきます。
 # chkconfig --add xl2tpd
# chkconfig --add ipsec
# chkconfig xl2tpd on
# chkconfig ipsec on
これでインストールは完了です。
(ここまで、サーバ側、クライアント側ともに同じです。)




次に、サーバ側の設定です。


まず、xl2tpd(L2PT)の設定を行なっていきます。
# mkdir /etc/xl2tpd
# cp examples/xl2tpd.conf /etc/xl2tpd/
# cp examples/ppp-options.xl2tpd /etc/ppp/options.xl2tpd
# vi /etc/xl2tpd/xl2tpd.conf
~~~~
[global]
[lnsdefault]
;ip range = 192.168.1.128-192.168.1.254
ip range = 192.168.253.128-192.168.253.254
;local ip = 192.168.1.99
local ip = 192.168.253.1
name = %L2TPNAME%
require chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
(%L2TPNAME%は適当に。以降使っていきます。
ここで指定したip rangeの範囲が、VPN上でクライアントに割り当てられます。
またlocal ipがVPN上でのサーバのプライベートIPアドレスとなります。)
# vi /etc/ppp/options.xl2tpd
name %L2TPNAME%
ms-dns ns1.dns.ne.jp
ms-dns ns2.dns.ne.jp
#ms-dns 192.168.1.1
#ms-dns 192.168.1.3
#ms-wins 192.168.1.2
#ms-wins 192.168.1.4
#noccp
auth
nobsdcomp
crtscts
idle 1800
mtu 1410
mru 1410
nodefaultroute
debug
lock
persist
#proxyarp
connect-delay 5000
refuse-pap
refuse-chap
require-mschap-v2
logfile /var/log/xl2tpd.log
(ns*.dns.ne.jpは、さくらのDNSです。それ以外のDNSサーバを使っている場合は、変更してください。
ただし、今回の場合、ms-dnsは要らないかもしれないです・・・。
 pppの各オプションの意味はググって
ドキュメントを探すか、man pppdで参照できます。)

chap-secrets(ユーザ認証)の設定も行います。
また大事なファイルなので、root以外の閲覧ができないよう権限を設定します。
# vi /etc/ppp/chap-secrets
"%USERNAME%" "%L2TPNAME%" "%CHAP-PASSWORD%" *
(%USERNAME%%CHAP-PASSWORD%も適当に。といっても管理は大切に。)
# chmod 600 /etc/ppp/chap-secrets

次に、openswan(IPSec)の設定を行なっていきます。
# vi /etc/ipsec.conf
version2.0

config setup
    dumpdir=/var/run/pluto/
    nat_traversal=yes    virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
    oe=off
    protostack=netkey
    nhelpers=0
    plutostderrlog=/var/log/pluto

include /etc/ipsec.d/l2tp-psk.conf
次に、Pre-shared Key(共有鍵)の設定も行います。
また、こちらも大事なファイルなので、権限設定します。

# vi /etc/ipsec.secrets<
%SERVER-IPADDRESS% %any : PSK "%PSK-PASSWORD%"
(%SERVER-IPADDRESS%は、サーバのグローバルIPアドレスです。)
# chmod 600 /etc/ipsec.secrets
さらに、L2PTを扱う設定も行います。
# cp /etc/ipsec.d/examples/lt2p-psk.conf /etc/ipsec.d/
# vi /etc/ipsec.d/l2tp-psk.conf
conn L2TP-PSK-NAT
    rightsubnet=0.0.0.0/0
    also=L2TP-PSK-noNAT

conn L2TP-PSK-noNAT
    forceencaps=yes
    authby=secret
    pfs=no
    auto=add
    keyingtries=3
    rekey=yes
    dpddelay=40
    dpdtimeout=130
    dpdaction=clear
    ikelifetime=8h
    keylife=1h
    type=transport
    left=%SERVER-IPADDRESS%
    leftnexthop=%defaultroute
    leftprotoport=17/1701
    right=%any
    rightprotoport=17/%any

#conn passthrough-for-non-l2tp
#    type=passthrough
#    left=YourServerIP
#    leftnexthop=YourGwIP
#    right=0.0.0.0
#    rightsubnet=0.0.0.0/0
#    auto=route
最後に、sysctl.confを変更します。
# /etc/sysctl.conf
~~~~
#net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
~~~~
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
# sysctl -p
あとは起動して・・・<
# service xl2tpd start
# service ipsec start
動作確認を行います。
# ipsec verify
エラーが出ていなければ、とりあえず問題ないということで。
iptablesも設定しておきます。
# vi /etc/sysconfig/iptables
*filter
~~~~
-P FORWARD DROP
-A INPUT -p udp -m udp --dport 1701 -i eth0 -d %SERVER-IPADDRESS% -j ACCEPT
-A INPUT -p udp -m udp --dport 500 -i eth0 -d %SERVER-IPADDRESS% -j ACCEPT
-A INPUT -p udp -m udp --dport 4500 -i eth0 -d %SERVER-IPADDRESS% -j ACCEPT
-A FORWARD -i ppp+ -o ppp+ -s 192.168.253.0/24 -d 192.168.253.0/24 -j ACCEPT
-A FORWARD -i ppp+ -o eth0 -s 192.168.253.0/24 -j ACCEPT
-A FORWARD -i eth0 -o ppp+ -d 192.168.253.0/24 -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
*nat
-A POSTROUTING -s 192.168.253.0/24 -j MASQUERADE
COMMIT
(参考元: http://www.manabii.info/2012/08/debian-gnu-linux-l2tp-ipsec-vpn-nat.html)
また、必要に応じて、VPN間でアクセス可能なポートなどを設定するといいかもしれません。


# service iptables restart
これでサーバ側の設定は完了です。


さて...次はクライアント側の設定です。


まずは、xl2tpd(L2TP)の設定を行なっていきます。
# mkdir /etc/xl2tpd
# cp examples/xl2tpd.conf /etc/xl2tpd/
# vi /etc/xl2tpd/xl2tpd.conf
[global]

[lac L2TP1]
lns = %SERVER-IPADDRESS%
require chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd.conn-1
length bit = yes

;[lns default]
;ip range = 192.168.1.128-192.168.1.254
;local ip = 192.168.1.99
;require chap = yes
;refuse pap = yes
;require authentication = yes
;name = LinuxVPNserver
;ppp debug = yes
;pppoptfile = /etc/ppp/options.xl2tpd
;length bit = yes
(lns defaultのセクションはすべてコメントアウトします。
L2TP1は、xl2tpd-controlで接続する際の接続名になります。そのままでも構いません。
次に、こちらもサーバ側と同じようにchap-secretsの設定を行います。
また、root以外の閲覧ができないよう権限を設定します。
# vi /etc/ppp/chap-secrets
"%USERNAME%" "%L2TPNAME%" "%CHAP-PASSWORD%" *
# chmod 600 /etc/ppp/chap-secrets
さらに接続設定を行います。
# vi /etc/ppp/options.xl2tpd.conn-1
name %USERNAME%
noauth
crtscts
mtu 1410
mru 1410
nodefaultroute
lock
#proxyarp
logfile /var/log/xl2tpd.conn-1.log
(どうもこのnoauthが引っ掛かりますが...これを他に変更すると動かないという。
サーバのほうはauthにしていますし、実際認証は行われているのですが・・・。
pppdのドキュメントによれば、noauthは"相手に認証を要求しない"オプションなので、サーバ側に対する話なのか? でもそもそも、CHAPだとサーバから認証を開始しますから...。(イマイチ...よくわかりませんw))


次に、openswan(IPSec)の設定を行なっていきます。
# vi /etc/ipsec.conf
config setup
    dumpdir=/var/run/pluto/
    nat_traversal=yes
    virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
    oe=off
    protostack=netkey
    nhelpers=0
    plutostderrlog=/var/log/pluto
~~~~
include /etc/ipsec.d/connection.conf
# vi /etc/ipsec.d/connection.conf
conn %PEER_L2TP%
    authby=secret
    pfs=no
    rekey=yes
    keyingtries=3
    type=transport
    left=%CLIENT-IPADDRESS%
    leftprotoport=17/1701
    right=%SERVER-IPADDRESS%
    rightprotoport=17/1701
    auto=add
(%PEER_L2TP%は、ipsec autoで接続する際の接続名になります。そのままでも構いません。
%CLIENT-IPADDRESS%は、クライアント側のグローバルIPアドレスです。%defaultrouteでもいいかも。
)

またサーバ側と同じ形式でPre-shared Keyを設定します。
# vi /etc/ipsec.secrets
%CLIENT-IPADDRESS% %any : PSK "%PSK-PASSWORD%"
(%SERVER-IPADDRESS%は、サーバのグローバルIPアドレスです。)
# chmod 600 /etc/ipsec.secrets
最後にこちらも、sysctl.confを変更します。
# /etc/sysctl.conf
~~~~
#net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
~~~~
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
# sysctl -p
サーバ側と同様にサービスを起動して・・・
# service xl2tpd start
# service ipsec start
ipsec_setup: Starting Openswan IPsec U2.6.38/xxx
・・・とここで...(´・ω・`)
いつまで経ってもスクリプトが終了しない(ターミナルの制御が戻らない)現象が。
どうやら今回は、新調したサーバですのでエントロピープールが足りないようです。
そんなことがあるんですね〜・・・w
# cat /proc/sys/kernel/random/entropy_avail 6
確かに足りないw そんな時には・・・なんか処理をしてもらいます。
# find /# cat /proc/sys/kernel/random/entropy_avail
499
(`・ω・´)シャキーンw これでOKですね。
気を取り直して...

設定確認を行います。
# ipsec verify
問題なければ・・・
いよいよ、IPSecの接続を行います。
# ipsec auto --up PEER_L2TP
続けて、L2TPの接続を開始します。(これでppp0が作成されます。)
# echo "c L2TP1" > /var/run/xl2tpd/l2tp-control

接続確認をしてみましょう。
まずは、クライアント側→サーバ側へping。
# ping 192.168.253.1
・・・ OKでした。
サーバ側→クライアント側へping。
# ping 192.168.253.128
・・・ダブルOK\(^o^)/(←

ちなみに、ifconfigをクライアント側で実行すると、こんな感じに表示されます。
# ifconfig
eth0      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:133.242.142.23  Bcast:133.242.143.255  Mask:255.255.254.0
          inet6 addr: xxxx::xxxx:xxx:xxxx:xxxx/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:xxxxxx errors:0 dropped:0 overruns:0 frame:0
          TX packets:xxxxxx errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:xxxx (xx MiB)  TX bytes:xxxx (xx MiB)

lo        (略)

ppp0      Link encap:Point-to-Point Protocol
          inet addr:192.168.253.128  P-t-P:192.168.253.1  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1410  Metric:1
          RX packets:19 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:2540 (2.4 KiB)  TX bytes:1504 (1.4 KiB)
(この設定では、クライアント側のppp0のinet addrは、
VPN上でのプライベートIPアドレスとなっているはずです。
また、P-t-Pは、VPN上でのサーバのプライベートIPアドレスとなります。)


以上です。
今回はこれでとりあえず開通させることができましたw

他サイトを参考にさせていただき...。この記事は一応整理した後に書きました。
ただ...実際のところは、何かと嵌ってしまったり(´・ω・`)...
ログファイル(/var/log/secure、/var/log/pluto、/var/log/xl2tpd、/var/log/xl2tpd.conn-1.log あたり)や、設定ファイルとにらめっこしながら、1日以上...試行錯誤していました(^^;)ゞ(笑)
うまくいくときは、すんなり行くんでしょうけどね...(;´д`)トホホ…。

ちなみに...1つ注意しておきたいのですが、ipsec auto --up して接続したときにエラーになると、一旦、ipsec auto --downしないと、再接続しようとしても何も表示されない...ということがありました。
...当然なのかもしれないですが、注意です(><)

あとは...このままで実用するとセキュリティがどうかと思うこともありますので、また設定をさらに弄っていこうと思いますw (X.509証明書認証も。)
ご指摘などありましたら、宜しくお願いします m(_ _)m
今回は以上ということで...それではっ。

[追記]
本記事中には反映していませんが、早速、証明書(X.509)認証に変更してみました。
こちらは大変すんなりと行きましたε-(´∀`*)♪ 本記事の最初のほうに書いたとおり、openswanのビルドを行う際にNSSを有効にしておくと・・・あとは証明書を作成して設定を行うだけです。
NSSでの証明書作成/openswanへの設定はこちらがとても参考になりました:
→ openswanでIPsec VPN(トランスポート・X.509認証) [Fedora14]  (感謝♪)

[2013/04/04 修正]
鍵まわりの問題により、一定時間で接続が切断される不具合があったため、pppまわりの設定を修正しました。

[2013/05/01 追記]
クライアントに割り当てるプライベートIPアドレスの範囲はサーバ側の/etc/xl2tpd/xl2tpd.confで設定しますが、
このプライベートIPアドレスをクライアントごとに固定としたい場合は...
双方の /etc/ppp/chap-secrets で、以下のように指定します。

# vi /etc/ppp/chap-secrets
"%USERNAME%" "%L2TPNAME%" "%CHAP-PASSWORD%" "192.168.253.128"

(この例では、192.168.253.128が割り当てられる。)

2013/02/13

node.jsをソースからビルドしてインストール(簡単) on Fedora17

以前の記事ではnaveを使ってnode.js環境をセットアップしましたが、
今回はソースコードからビルドしてインストールする話です。
といっても特に何のことはなく、とっても簡単です。
コーヒー飲んでたら終わる手軽さです♪

尚、今回利用した環境は、Fedora 17 (64bit)です。

まずはnode.jsのソースコードのアーカイブを取得して...
(執筆時の最新版は、node-v0.8.19でした。尚、Githubからgit cloneしてもOKです。)
$ wget http://nodejs.org/dist/v0.8.19/node-v0.8.19.tar.gz
展開してビルドし、インストールします。 (尚、g++, openssl-devel、pythonなど必要なものは、前もってインストールしておいてください。)
$ tar zxf node-v0.8.19.tar.gz
$ cd node-v0.8.19/
$ ./configure
$ make
$ sudo make install
これで、nodeとnpmがインストールされました。
/usr/local/bin にインストールされたので、/usr/binからリンクを張ります。
$ sudo ln -s /usr/local/bin/node /usr/bin/node
$ sudo ln -s /usr/local/bin/npm /usr/bin/npm
終わりです ( ̄ー ̄)b

2013/02/10

Hello, Jenkins. GitLab+Jenkins+perl(Mojolicious)でCIをしてみた

こたつ最高(>ω<)♪ こたつで丸くなっております、Masanoriです(笑)

公開しているプロジェクトではTravis-CIを使わせていただいていたりするのですが
今回は、自前のGitLabで管理しているプロジェクトにもCIを...ということで...

Jenkinsをインストールして、GitLab上のGitリポジトリ、
および nginx(リバースプロキシとして...)と組み合わせる話(※自分用メモ)です。
また、
Jenkinsを用いて、perl(Mojolicious)のプロジェクトをテストします。
(加えて、CPANモジュールの一時的な自動インストールも行えるようにします。[追記: 2013/02/11])


※尚...Gitlabには、Gitlab CIというシンプルなソフトウェアが提供されており、通常はそちらを使うと良いと思います。今回は Jenkinsを使うこととしました。
Jenknsをちゃんと使ってみたかった!という動機がw
  • サーバはいつも通りのCentOSです。JDKなどもセットアップ済みです。
  • nginxをリバースプロキシとして、Jenkinsを /jenkins 下で動作させます。
    (毎度お断りしておきますが、以下にある設定内容は実際の運用サーバとは異なります。)
  • プロジェクトはすでにGitLabで作成済みで運用中、nginxも運用中です。
以下、
madroom project: Gitoliteに触れずにGitLabのhookからJenkins側でビルドする
を参考にさせていただきました。感謝! m(_ _)m♪
(Gitoliteを弄らない方法になっています。)


まずはJenkinsのウェブサイトからRPMをダウンロードしてインストール。
(LTS版もあるみたいですが、最新のJenkins-1.500を選択。)
$ wget http://pkg.jenkins-ci.org/redhat/jenkins-1.500-1.1.noarch.rpm
$ sudo rpm -ivh jenkins-1.500-1.1.noarch.rpm
これでJenkinsのインストールは完了です。とても楽ちんでありがたいですね。

次にJenkinsからGitリポジトリへアクセスできるよう鍵を作ります。
(今回はサーバ上でなくクライアント上で作って転送したほうが、GitLabでの登録がうまく行くそうです。)
$ ssh-keygen
Enter file in which to save the key (~~~): id_rsa_jenkins
Enter passphrase (empty for no passphrase): (空)
Enter same passphrase again: (空)
作成した鍵は、/var/lib/jenkins/.ssh/ 下に置いておきます。

さらに /var/lib/jenkins/.ssh/config を記述します。
$ sudo vi /var/lib/jenkins/.ssh/config
Host example.com
    User gitolite
    Port xx
    Hostname example.com
    IdentityFile /var/lib/jenkins/.ssh/id_rsa_jenkins
またknown_hostsも手動で記述しておきますw
$ sudo vi /var/lib/jenkins/.ssh/known_hosts
[example.com]:xx,[xxx.xx.xxx.xxx]:xx ssh-rsa ~~~~
次にJenkinsの設定ファイル(/etc/sysconfig/jenkins)を開いて
ポート設定およびディレクトリパスを変更します。

$ sudo vi /etc/sysconfig/jenkins
~~~~
# JENKINS_PORT="8080"
JENKINS_PORT="8888"
~~~~
#JENKINS_ARGS=""
JENKINS_ARGS="--prefix=/jenkins"
さらにnginxの設定ファイルにリバースプロキシのための設定を追加しておきます。
$ sudo vi /etc/nginx/nginx.conf
http {
    ~~~~
    upstream Jenkins.backend {
        server 127.0.0.1:8888;
    }
 ~~~~
    server {
        ~~~~
        location ~ ^/jenkins.* {
                proxy_pass      http://Jenkins.backend
                break;
        }
        ~~~~
    }
}
次に、Gitlabにブラウザからアクセスし、Jenkinsのユーザアカウントを作成します。
またCIを行うプロジェクトの"Reporter"権限をそのアカウントに対し設定します。

さらに、プロジェクトのWebHooks画面で JenkinsのURL (http://example.com/jenkins/git/notifyCommit?url=gitolite@example.com:xxx/yyy.git)
を登録しておきます。

また、作成したアカウントでGitlabにログインして、
さきほど作成した公開鍵を登録します。


次に...Jenkinsを起動します。
$ sudo service jenkins start
これでブラウザからアクセスできるようになっているはずです。 http://example.com/jenkins

早速、"新規ジョブ作成"へ進....
...といいたいところですが、その前に...Git Pluginのインストールです。
これがWebのUIで取得〜適用まで可能になってるんですね〜...素晴らしいです! (ちょっと違うところでは、TracとかRedmineもそうなってきてますが、手軽でありがたいことですw
 以下スクリーンショット付きですw)


まず、"Jenkinsの管理"をクリック。
"プラグインの管理"をクリック。
"利用可能"タブをクリックして...
"Git Plugin"にチェックを入れ、"再起動せずにインストール"をクリック。
(※"Git Server Plugin"などありますが、またこれとは別です。
 "Git Plugin"だけ、フィルタをかけてもうまくヒットしないときがありました。 "高度な設定タブで、設定をいじったり、何回か更新処理を実行した後に正しく表示されました。)

(それにしても...他にも色々おもしろそうなプラグインがwktk)

"インストール完了後、ジョブがなければ〜再起動"にチェックを入れて待ちます。
インストールが終われば、ダッシュボードから再度、"Jenkins"の管理をクリックし、 "システムの設定"をクリックします。

"Git plugin" セクションの"Global Config user.name Value"と、
 "Global Config user.email Value"を入力し、"保存"をクリック。


次に、再度ダッシュボードに戻り、
"新規ジョブ作成"をクリック。
ジョブ名を入力し"フリースタイル・プロジェクトのビルド"を選択。
"OK"をクリック。

"Git"にチェックを入れ "Repositories"の
"Repository URL"に ssh://~なURLを入力して・・・

さらに、"ビルド・トリガ"セクションの "SCMをポーリング"にチェックを入れ "保存"をクリックします。

また最後であれですが..Jenkinsで認証を設定しておきましょう(※最初にやるべきか(汗;
"Jenkinsの管理"→"グローバルセキュリティの設定"から、設定できます。
 [追記:2013/02/11]
"アクセス制御"セクションの "行列による権限設定"を選択して、表を編集することで、非ログインユーザーによる閲覧をブロックすることが可能です。
(※尚、"ログイン済みユーザーに許可"のほうを選択してしまうと、非ログインユーザでも閲覧はできますので注意。)
尚、このグローバルセキュリティの設定ですが、設定ミスによりアクセスできなくなった場合は、
一時的に無効化しましょう (→ Jenkins パスワードのリセット方法 - エンジニアきまぐれTips (感謝♪))


さらにもし必要ならば、別途、nginx側などで閲覧認証をつけてください。

これでプロジェクトを取り込む設定は、ひとまず完了です。

あとは、GitLab上でTest Hookを実行するか、リポジトリにプッシュすれば
Jenkins側で、ひとまずビルドが走ります.........



さて、これではまだ、テストケースを実行して評価することができません。

今回CIを実施したいプロジェクトは、
perlのMojoliciousというWAFで開発しているWebアプリケーションなのですが、
これをJenkinsでテストできるよう設定したいと思います。

Tatsuya Blog » PerlのテストコードをJenkinsで動かすのページを
参考にさせていただきました。感謝です m(_ _)m♪
  • 但し、今回の記事では、テスト実行の際、一時的にCPANモジュールを自動インストールできるようにしておきます
    インストールされるモジュールは、Makefile.PLに定義します。
  • テストスクリプト(t/*.t)とMakefile.PLについては、作成済みです。
    Makefile.PLは、以前の記事: Travis CIでPerl(Mojolicious)アプリケーションを自動テストを参照。
    また、Mojoliciousでのテストスクリプトの書き方は、Test::Mojoなどを参考に。
まず cpanmを Jenkins用に、
Jenkinsのホームディレクトリ(/var/lib/jenkins)下へインストールします。

$ sudo -u jenkins mkdir /var/lib/jenkins/bin
$ cd /var/lib/jenkins/bin
$ sudo -u jenkins curl -LOk https://raw.github.com/miyagawa/cpanminus/master/cpanm
$ sudo chmod +x ./cpanm

次に、cpanmで、TAP::Formatter::JUnit をインストールします。
$ sudo cpanm TAP::Formatter::JUnit

次に、Jenkins上のプロジェクトの設定画面を開きます。


ここでは、"ビルド"セクションで、"シェルの実行"を選び、
"シェルスクリプト"欄に次のコマンドを記述します。
/var/lib/jenkins/bin/cpanm -l dlibs --installdeps .
prove -Idlibs/lib/perl5 -b --formatter=TAP::Formatter::JUnit -lvr t > test_results.xml
(最初にcpanmを使って、dlibsフォルダ下にモジュールを自動ダウンロードしています。
尚、proveコマンドについては、詳細なログが不要であれば-v オプションを取り除くといいです。
オプションについて詳しくは...prove についてのおさらいを参照するとよいでしょう。(感謝♪))


さらに、"テスト後の処理"セクションで、"JUnitテスト結果の集計"を選び、
 "テスト結果XML"欄に次のファイル名を入力します。
test_results.xml
"保存"ボタンをクリックして設定完了です。

あとはプッシュすれば、ビルドが自動的に行われ、テスト結果が生成されます。
また手動でもビルド実行が可能です。

無事通過(PASS)したテスト。Jenkinsでは青色のマークが表示されます。
通知設定などはまた別途行ってください。
それにしても...Jenkinsおじさん、ステキですwww

[2013/02/18 追記]
今回の続きとして...Jenkinsへスレーブを追加してみました。
Masanoriのプログラミング日誌++: Jenkinsのスレーブノードを追加してみた

2013/02/05

WebAPIドキュメント作成サービス apiary.ioを使ってみた

apiary.ioを使ってみました。
WebAPI(REST API)のドキュメントをサクっと書けるサービスです。
http://apiary.io/

去年(2012)年にローンチされたサービスで、何かに使いたいな〜と思いつつ...。
今回、開発中のWebサービスにWebAPIを実装することとなったので使わせていただいております。 (そのドキュメントはまだ公開してないです。すみません(汗;))

以下のように、API Blueprintという簡単な文法で、
"リクエスト"と"レスポンス"の例を記述するだけで
便利なドキュメントができあがります。

HOST: http://api.example.com/
--- ほげほげ API v2 ---
---
Welcome to our API. Comments support [Markdown](http://daringfireball.net/projects/markdown/syntax) syntax.
---
-- Shopping Cart Resources --
GET /shopping-cart
> Accept: application/json
< 200
< Content-Type: application/json
{ "items": [
    { "url": "/shopping-cart/1", "product":"2ZY48XPZ", "quantity": 1, "name": "New socks", "price": 1.25 }
  ] }
(ちなみに、descriptionなどの項目は、Markdownベースの記法を利用できるようになっています。)
作成されたドキュメントページ: http://docs.test0mugifly.apiary.io/
(ドキュメント上に記載されたWebAPIは実在しません。あしからず。)
簡単に使い方を説明しておきますと・・・。
まず...何が便利なのかというと・・・

この記述をもとにして、
テストリクエストを受けるための"Mock Server"を自動で用意してくれます。
このように Mock Serverが自動的に使えるようになる。
このMock Serverはドキュメントに記述したままのレスポンスを返すことができる他、
Proxyとして動作させることもでき、テスト用アクセスを識別するためのHTTPヘッダを自動付加して、productionなWebAPIサーバへアクセスさせる事も可能です。
(つまり、ドキュメント(仕様書)のリクエスト/レスポンスと、実際のクライアントによるリクエスト / 実際のWebAPIによるレスポンスを比較することができるわけです。)

"Inspector"タブでは、全てのリクエストの履歴一覧と詳細確認が行える。
リクエストヘッダ、レスポンスヘッダ、レスポンスボディについて各々、
ドキュメント(仕様書)に記述されたものと、実際の結果との比較が可能。
apiary.ioのドキュメント設定画面。
Cross-Origin Requestのヘッダを付加したり、Mock ServerをProxyにすることが可能。
また、JavaScriptやpythonによるアクセスのためのサンプルコード表示ができたり...
ドキュメントページの"Example"タブでは、
各プログラミング言語によるサンプルコードの表示を行える。
(個人的には...perlによるサンプルコードは用意されていないのが少々不満(笑))
ブラウザ上でXMLHTTPRequestによるテストリクエストを行えたり...
おなじく、ドキュメントページの"Try it"タブでは、
XMLHTTPRequestによるテストリクエストをその場で行える。
また、コメントによるディスカッションもでき...結構至れり尽くせりな気がします。
おなじく、ドキュメントページの"Comment"タブでは、
各resourceごとにスレッドを立ててコメントが書ける。
この手軽さでありながら、大手サービスのWebAPIドキュメントにも引けをとらないレベルといっても良いかもしれませんね。

作成したドキュメントは、一部登録メンバーのみ閲覧可能なように、Privateにすることもできます。
また、GitHubのリポジトリでドキュメントを管理することもでき、プッシュするだけで更新が可能になっています。複数人編集も楽ですね。
(apiary.io上のエディタで編集したほうが、完全なライブプレビューが出来るので便利かもしれませんが。)

"WebAPIドキュメントを書こうと思っても...ふつうのWikiページなどに書くのは面倒くさいな〜"という場合も、使ってみるとかなり便利だと思います。
今のところベータバージョンですが、これで無料ですし、試してみてはいかがでしょうか。