Laravel4、インスタントLaravelの紹介

Tags : Laravel4   AWS   DigitalOcean   Linode  

チュートリアルの環境をクラウドベースのVPS上へ構築するため、単純な共有サーバーを簡単に構築するためのシェルです。Ubuntu14.04のサーバー上に、PHP5.5、NginxでWebサーバーを構築し、必要なソフトのインストールとセットアップを行います。

作成した経緯は、FacebookのLaravel JPグループにも書きましたが、ここでも簡単に説明します。

地方に住んでいると、なかなか都会で開かれるチュートリアルやミートアップに参加できないものです。参加するにしても時間とお金がかかります。そこでオンラインでハンズオンイベントをどうにか開けないかと思いました。

ハンズオンとなると、参加者に「自分で環境を用意してください。」という状況が多くなるでしょう。イベントの時間を有効に使用するためです。ところがハンズオンを必要とする初心者には、ターゲットをインストールし、動作できるようにする環境を整えるのが難しいのも事実です。大抵の場合、ツールは揃っているのですが、まだ知識が足りません。このため、事前準備の要求は参加の障壁となってしまいます。

LaravelにはHomesteadが存在しますが、全ての潜在ユーザーがVagrant環境を整えているわけでもありません。

そこで、イベント開催時にVPSにLaravelの環境を予め作成し、それを使用してもらうことを考えました。最初はSSHで接続してもらうかとも思いましたが、それもまたSSHの知識を押し付けます。そこで、オンラインエディターを準備し、参加から、コードの編集、結果の確認を全部ブラウザーからやってもらう仕組みを考えました。

一度、探究心に火が付けば、人間は壁を越えようとするものです。Laravelを面白いと思ってもらえば、インストールが多少難しくても、自分で調べ、乗り越えてくれるでしょう。もしくは、誰かに質問し、答えを得てくれるでしょう。

私以外にも希望する方に、オンラインのハンズオンイベントを開いてもらうため、プロビジョニング(事前準備)ができるようにしました。当初はプロビジョニングツールを勉強兼ねがね使うつもりでしたが、意外と構築に手間取るため、それは別の機会として、Bashシェルにまとめました。そして完成したのがInstantLaravelです。

"InstantLaravel"という言葉には、いくつかの意味があります。

1.環境生成Bashスクリプト

クラウド上の仮想サーバーで、ハンズオン環境を構築するBashスクリプトです。GitHubのInstantLaravel/InstantLaravelリポで公開しています。

2.構築されたチュートリアル環境

作成されるハンズオン環境のドメインは3つで構成されています。一つはユーザー登録、もう一つはコードエディター、最後の一つは結果を確認するために使用します。

ユーザー登録ページはLaravelを使用し構築しています。ロジックのほとんどは、ファットコントローラーで、routes.phpの中にあります。Viewコンポーサーのみ、app/start/global.phpに追加しています。ユーザーを登録し、新規ユーザーのために環境を作成しています。現状、新規ユーザー登録さえできれば、認証は必要ではないのですが、エディターのCodiadとの連携を行うために、コードが入っています。一度、連携させたのですが、ログイン後のエディターが一定時間ごとに再描写されるようになったため、連携部分のコードは外しています。

エディターにはCodiadというPHP製のIDEをそのまま使用しています。UI日本語化のためのリソースを作成し、オリジナルのTerminalプラグインを改造した、Jailed-Terminalを用意しました。

結果を確認するために特別なソフトウェアを使用していません。多少セキュリティーをアップするため、各ユーザーの権限で実行しており、そのためNginxとPHP-FPMの設定が多少複雑になっています。それでも、各設定はできるだけシンプルになるようにしました。

3.instantlaravel.com

このドメインは、Laravelのオンラインチュートリアルイベントを紹介するためのハブサイトです。InstantLaravelで作成された環境をどのように使用するのかを説明していますが、他の手段を利用したものでもOKです。オンラインチュートリアル・オンラインハンズオンイベントの予定をお持ちの方はhirokws@gmail.comまでご連絡ください。掲載させていただきます。

環境の作成

Ubuntu14.04が動作するクラウドかVPSサービスを用意してください。もちろん、自宅サーバーでもかまいません。

想定しているのは、数時間のハンズオンです。ですから、準備を含めた時間だけ環境を借りられれば良いため、AWSのEC2、Linode、DigitalOceanのDropletなどのサービスの使用をおすすめします。この3つのクラウドサービスで動作を確認してあります。

準備に時間をかけたい場合や、前日に準備しておきたい場合は、DigitalOceanを利用することをおすすめします。Dropletを停止し、そのスナップショットを取り、Dropletを破棄してしまえば、料金がかからなくなります。スナップショットには現在課金が始まっていませんので、動かしていない時間はコスト0です。(料金形態は決まっているのですが、課金はまだされていません。)もちろん、スナップショットからDropletを立ち上げれば、元の状態へ復帰します。

チュートリアル目的の短時間ハンズオンではなく、開発目的のハンズオンなどに利用する場合は、EC2をおすすめします。料金が多少割高なぶんだけ、上流回線でのDDos対応など、セキュリティー的に強くできます。(当然ながら、もろもろのセキュリティーホールは塞いでおきましょう。)参加するメンバーを事前に確認するなど、運用面でもセキュアにしておきましょう。

短時間のチュートリアルで、このInstanlLaravelをそのまま使用するような場合は、Linodeをおすすめします。日本にサーバーがありますし、他のVPSにくらべスペック以上の速度が出せるようです。アウトの回線スピードの制限が他より厳しいのですが、このシステムを使用したハンズオンでは、余程の参加者がいない限り、先ず問題にはならないでしょう。

これらの時間貸しVPSを活用するというのは最初からアイデアとして持っていました。主催者が費用的な負担を負うというのが、日本の勉強会やITイベントでは当たり前になっているようです。時間とお金を主催するためにたくさん費やしてしまうのであれば、長期的に持続し、開催するには辛いものがあります。これらの時間貸しVPSを活用するのであれば、余り高性能なサーバーを用意する必要もなく、通常2時間程度使っても100円かからないでしょう。時間的にも、サーバーを立ち上げ、シェルを流し、エディターのプラグインをセットし、イベントの内容に必要なPHP拡張を追加インストールし、Laravelのプロジェクトにも必要な外部パッケージを入れても、30分内に収まります。

後述しますが、InstantLaravelをローカルに試してみるために、Vagrantを使用してみることも可能です。

準備したUbuntu14.04サーバーでルートユーザーになり、GitHubのInstantLaravel/InstantLaravelリポに含まれる、ubuntu-provisioning.shを取得してください。

シェルの先頭に設定項目がまとまっています。Laravelのチュートリアルでしたら、3つのドメイン名と"base"ユーザー(管理ユーザー)のパスワードを変更してください。

続いて、シェルを実行しましょう。

bash -v ubuntu-provisioning.sh

10分ほどで、環境が出来上がります。

**注意: ** EC2を使用する場合、シェルを流す前にapt-get update、続いてapt-get upgradeを実行してください。EC2のUbuntu14.04だけ、どうやら設定が異なっているようで、upgradeのデフォルト動作ででコアやGrubのアップデートまで取り込まれるようです。そのため、選択オプションの選択や確認が表示されてしまいます。シェルで流すと、この選択画面でフリーズしてしまいます。そのため、予めアップグレードを先に実行しておいてください。(避ける方法はあるのですが、今回は取り込みませんでした。)

Vagrantで試す

Vagrantfileの存在するディレクトリーに、ubuntu-provisioning.shを用意してください。

Vagrantfileは以下のようになるでしょう。

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/trusty32"
  config.vm.network "private_network", ip: "192.168.33.10"
  config.vm.provision :shell, :path => "ubuntu-provisioning.sh"
end

32ビット版(ubuntu/trusty32)でも64ビット版(ubuntu/trusty64)でも動作します。(事前にbox addで取り込んでおきましょう。)

ドメイン名でプライベートIPへアクセスできるように、ホストマシン(親のコンピューター)のhostsを設定してください。LinuxやMacであれば、/etc/hostsでしょう。以下の1行を付け加えてください。

192.168.33.10   top.instant.com editor.instant.com check.instant.com

もちろん、Vagrantfileで指定したIPや、シェル中で指定したドメイン名に値を合わせてください。

後は、vagrant upを行い、プロビジョニングが終了し、端末に制御が戻ってきたら、ブラウザからアクセス可能です。

エディター(Codeiad)プラグイン設定

エディターのCodiadはインストール時の状態で、プラグインは含まれていません。

開催するハンズオンのタイプに合わせ、必要なプラグインをインストールしてください。"base"ユーザーでログインすると、右のナビに「マーケットプレース」が表示されます。これがプラグインマネージャーです。プラグインのインストールと削除を行います。

プラグインを選び、"Install"ボタンをクリックすれば、インストールされます。多くの場合、制御が戻ってこないことが多いようです。30秒はかからないはずですので、待ってもマーケットプレースが再描写されない場合は、一度ウィンドウを閉じ、再度マーケットプレースのリンクをクリックしましょう。

デフォルト(標準的な)環境としては、以下の3プラグインを推奨します。

  • Toogle(チャット)
  • CodeSetting(キーバインド)
  • Jailed-Terminal(端末)

"Toogle"プラグインは、音声チャット、テキストチャットを追加します。コラボレーション機能もありますが、Codiadのような認証が必要なサイトでは、認証の仕組みをいじる必要があるらしく、動作しません。

"CodeSetting"はキーバインドを変更できるプラグインです。標準的なキーバインドがブラウザのホットキーと衝突する場合があるため、変更できるように入れておくのが良いでしょう。(ちなみに、Codiadを作成している方は、Windows 7ユーザーだそうです。)

"Jailed-Terminal"はマーケットプレースに登録されているTerminalを日本語化し、プロジェクトのトップディレクトリーより上部へ移動できないように改造したバージョンです。また、オリジナルは禁止コマンドの登録にブラックリスト方式を利用していますが、セキュリティー上、多くのコマンドを使用させない必要がありますので、ホワイトリスト形式による指定も追加しています。また、コマンドエイリアスの指定もできます。改造版のため、マーケットプレースには登録されていません。一番下の入力欄に、https://github.com/InstantLaravel/Codiad-Jailed-Terminal.gitを入力し、右横のInstall Manuallyボタンをクリックしてください。

その他、同じプロジェクトを開いている人のカーソル位置と入力を反映させるCollaborative(余り安定していない様子)や、Gitの統合、カラーピッカー、Emmet、less、ToDoリストなどもあります。

また、プラグインとは関係ありませんが、教える立場の参加者を「ユーザー」のプロジェクトアイコンから、全プロジェクトアクセス可能(Access All Projects)へ指定しておきましょう。参加者のコードをチェックすることもあるでしょうから、必要でしょう。ただし、この指定により、その参加者の人はプラグインなども操作できる「管理者」扱いになります。

Laravelの設定

InstantLaravelの仕組みは簡単です。/home/codiad/workspace下にユーザーごとのLaravelプロジェクトが存在しています。

新規ユーザーが登録されると、"base"ユーザーのLaravelプロジェクトをその新しい参加者のためにコピーします。ですから、baseユーザーのプロジェクトに必要なリソースを予め用意しておけば、新しい参加者のプロジェクトに含まれますので、予め何かを用意してもらう必要はありません。

デフォルトでは、ペジネーション(ページ操作)のために、Bootstrapをインストールしてあります。また、それを表すため、sampleブレードビューとbootstrap-layoutレイアウトビューを用意しています。デモのために定義されている、ルートページのindexビューをsampleビューに変更してもらえば、表示されます。

このように、イベントに必要なリソースは、/home/codiad/workspace/base下のLaravel環境に用意してください。後は参加者が増えるたびに、自動的にコピーされます。

デフォルト環境では、セキュリティーとメモリの節約のため、必要最低限度のPHP拡張しか入れていません。ですからイベントの内容に応じて、apt-get installで追加する必要があるでしょう。

InstantLaravelの仕組み

InstantLaravelでは、ドメインごとにPHPの動作ユーザーを切り替えています。登録ページでは"home"ユーザー、エディターは"codiad"、確認ページではURIの最初に指定されるユーザーとして動作します。

各ユーザーの環境は、先ほど説明した通り、/home/codiad/workspace下に存在しています。本来、これを各ユーザーのホームディレクトリーなどに設置できれば一番わかり易いのですが、Codiadの仕様により、workspace外に設置しているプロジェクトは、エディターのページより「ダウンロード」できない仕様になっているため、ワークスペース下にまとめる必要がありました。

各ユーザーのプロジェクトは、そのユーザーが所有者、グループはcodiad所属になっています。そして同じグループにも読み書きのパーミッションを付加しています。エディターはcodiadグループで動作しているため、エディターはどのユーザーのグループでも編集可能になっています。

あるユーザーのプロジェクトを確認する場合は、そのユーザーとしてPHPが実行されるため、他のユーザーの領域を荒らせません。(書き込めません。)

問題

ファイヤーウォークの設定や、新入監視などは、イベントの長さと重要性を考慮し、開催者さんが準備するべきだろうと考え、プロビジョニングしていません。

現在、InstantLaravelのシステムとして認識している、未解決の問題が一つあります。端末プラグインはエディターから起動されます。エディターはCodiadユーザーで動作しており、全ユーザーのプロジェクト下のファイルシステムはcodiadグループ所属で、グループへの書き込み権限を与えています。

そのため、端末から実行するコマンドでは、他のユーザーの環境を変更できてしまいます。Jailed-Terminalで、ホワイトリストに載せるコマンドを制限すれば、ある程度影響は防げますが、完全に防ぐためにはphpやaritsanの実行も制限する必要があります。セキュリティーを完全にしようとするとPHPやArtisanコマンドの実行もできないように設定する必要があります。

これを解決するには、エディター(Codiad)自体を各ユーザーとして動作させることが必要です。そのためにはNginxで切り分けられるように、エディター用のドメインのサブドメインか、もしくはサブディレクトリーとしてユーザー名を指定する必要があります。

ところが、Codiadでは自分自身を表すURLを設定ファイル内に指定する必要があります。

それに実現するには、Codiadを各ユーザー専用として個別に用意する必要があります。すると今度は、コラボレーション機能やチャット機能が動かなくなります。別の環境として動作させることになるためです。

私は今のところ、これを完全に解決する必要性を感じていません。どの程度のセキュリティーにするかは、「有料か無料か」、「どの程度の人数に影響があるか」、「どの程度の期間サービスするか」、「サービスの内容」などを考慮したトレードオフで決まります。

「無料のチュートリアルオンラインハンズオンイベントで、多分参加者は0から、多くても30名程度」と推測されます。ですから、求められるセキュリティーレベルはさほど高くなく、現状で十分であろうと考えています。

もちろん、不届き者が毎回参加し、他のユーザーのプロジェクトを壊しまわるかも知れません。そうなったら、事前登録制にし、何らかの手段で身元確認ができる人だけに参加してもらうように、運営方法を変更すれば良いと考えています。