新しくなった さくらVPS + nginx + Sinatra でプライベート Gyazo サーバを構築しよう
写真・カメラ関連のエントリばかりを投稿しているので、このまま写真ブログになってしまうのではと自分でも危惧していたところです。今日は久しぶりに技術系のエントリを書いてみようと思います。
はじめに
突然ですが、みなさんは さくらのVPS 使っていますか?
月額たったの980円で、root権限付きの専用サーバが持てるということもあり、サービス開始あたりからずっと愛用してきておりました。
これまでは旧プラン(さくらのVPS 512)を契約していたのですが、このたび新しいプランにリニューアルされ、同じ月額980円で、RAM1GB、HDD 200GB(旧プランではメモリ512MB、HDD50GB)というスペックアップしたVPSサービスが利用出来るようになりました。
そこで今回は、さくらのVPS上に「プライベートなGyazoサーバ」を構築する手順について説明していきたいと思います。
Gyazo · Free Screenshot App · Capture, Share, & Search Easier
Gyazoは、手元のPCのスクリーンショットを切り取って瞬時にインターネット上に公開できるサービスです。Gyazo自体は、誰でも自由に使うことが出来るサービスなのですが、Proアカウントでないと画像の削除が自由に出来なかったりする上に、Github上でサーバ・クライアントのソースコードが公開されている為、プライベートな自分専用のGyazoサーバを立ててしまったほうが色々と融通が利いて良さげだったりします。
Rubyのインストール
Rubyをソースからインストールします。
VPSが提供される初期状態のCent OSでは、zlib-devel やら readline-devel やら、Rubyの拡張ライブラリをコンパイルするにあたり必要になるいくつかのyumがインストールされていません。
これにより、あとでnginxやら各種gemやらを入れるときに怒られてしまい、あとからRubyの拡張ライブラリをmakeし直すことになるので、最初にあらかじめyumでインストールしておきます。
$ sudo yum install zlib-devel readline-devel curl-devel openssl-devel
ライブラリのインストールが完了したら、Rubyのソースをダウンロードしビルドします。
当然 rvm を使用しても問題はないのですが、今回は /usr/local 配下にRubyをインストールします。
$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p125.tar.gz $ tar xvfz ruby-1.9.3-p125.tar.gz $ cd ruby-1.9.3-p125 $ ./configure --prefix=/usr/local $ make $ sudo make install $ ruby -v ruby 1.9.3p125 (2012-02-16 revision 34643) [i686-linux]
sudo secure_path 設定の無効化
リニューアルされたVPSではCentOSのバージョンが新しくなっている為か、/etc/sudoers に secure_path の設定が追加されています。
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
要は、「sudo経由でコマンドを実行したときに限り、ここで指定されているPATHのみを使用しますよ」ということらしく、この指定が有効になっている限りは、/etc/sudoers の env_keep にPATH環境変数を追加したとしても、secure_pathの設定のほうが有効になってしまうみたいです。
このままだと、/usr/local 配下にインストールされた gem コマンドが当然使用出来ません。secure_path に /usr/local を追加するという手もあるのですが、そもそも sudo時のPATH環境変数を制限することのどこがsecureなのか全く理解が出来ない(詳しい方、ツッコミおねがいします)ので、今回はこいつを思い切ってコメントアウトして、/etc/sudoers の env_keep に PATH 環境変数を追加します。
これにより、sudo 経由で gem コマンドが実行出来るようになります。
$ su # visudo
Defaults env_reset Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS" Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE" Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES" Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE" Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" Defaults env_keep += "PATH" # ←この行を追加 ... # Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin # この行をコメントアウト
Passengerのインストール
ここまでで、gemコマンドを実行出来るようになったので、Passenger gem をインストールします。
$ sudo gem install passenger
nginxのインストール
Passnger添付の passenger-install-nginx-module コマンドを使って、nginxをインストールします。
$ sudo passenger-install-nginx-module
途中、nginxのインストールパスの入力を促されます。デフォルトでは /opt/nginx/ にインストールされるようになっているようなのですが、ここでは /usr/local/nginx にインストールしてみます。単なる好みの問題ですけどね。
nginx起動スクリプトの作成
nginxをインストール後、起動スクリプトを作成しておきます。
$ sudo touch /etc/rc.d/init.d/nginx $ sudo vi /etc/rc.d/init.d/nginx
起動スクリプトには以下のような内容を記載。
#!/bin/sh # # nginx - this script starts and stops the nginx daemin # chkconfig: 345 85 15 # description: Nginx # export GEM_HOME=/usr/local/lib/ruby/gems/1.9.1/gems # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 nginx="/usr/local/nginx/sbin/nginx" prog=$(basename $nginx) NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf" [ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx lockfile=/var/lock/subsys/nginx start() { [ -x $nginx ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 echo -n $"Starting $prog: " daemon $nginx -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { configtest || return $? stop start } reload() { configtest || return $? echo -n $"Reloading $prog: " killproc $nginx -HUP RETVAL=$? echo } force_reload() { restart } configtest() { $nginx -t -c $NGINX_CONF_FILE } rh_status() { status $prog } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) rh_status_q && exit 0 $1 ;; stop) rh_status_q || exit 0 $1 ;; restart|configtest) $1 ;; reload) rh_status_q || exit 7 $1 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" exit 2 esac
作成したら、実行権限を付与しておきます。
$ sudo chmod 755 /etc/rc.d/init.d/nginx
gyazo-sinatra のソースコードを取得
GyazoのGithubリポジトリには、以下のようなアップロードCGIが用意されています。
https://github.com/gyazo/Gyazo/blob/master/Server/upload.cgi
ですが、単なるcgiではあまり芸が無いので、今回はSinatra上で動作するgyazoサーバを使います。
GitHub - send/gyazo-sinatra: A Gyazo server using Sinatra.
上記のリポジトリから、ソースコードをcloneします。
ここでは仮に、nginxの実行ユーザを「aquarla」とするものとして、ディレクトリの所有ユーザを変更します。
$ cd /var/www $ sudo mkdir gyazo-sinatra $ sudo chown aquarla:aquarla gyazo-sinatra # nginxの実行ユーザを「aquarla」とする場合 $ git clone https://github.com/send/gyazo-sinatra
ソースコードをcloneしたら、app.rbをエディタで開き、VPSのドメイン名に合わせてファイルの内容を変更します。
$ vi /var/www/gyazo-sinatra/app.rb
require 'rubygems' require 'sinatra' require 'rack' require 'digest/md5' require 'sdbm' module Gyazo class Controller < Sinatra::Base configure do set :dbm_path, 'db/id' set :image_dir, 'public/images' set :image_url, 'http://gyazo.send.sh/images' # ←この行のドメインを変更する! end post '/' do id = request[:id] data = request[:imagedata][:tempfile].read hash = Digest::MD5.hexdigest(data).to_s dbm = SDBM.open(options.dbm_path, 0644) dbm[hash] = id File.open("#{options.image_dir}/#{hash}.png", 'w'){|f| f.write(data)} "#{options.image_url}/#{hash}.png" end end end
ちなみにこのままのプログラムだと、任意のユーザがこのサーバに対してアップロード操作を行うことが出来てしまうので、それが嫌な場合は必要に応じてアクセス制限などの策を講じる必要があります。ここではその説明は割愛します。
nginxの設定を変更する
上記のgyazo-sinatraディレクトリ上でsinatraアプリが動作するように、nginxの設定ファイルを変更します。
$ sudo vi /usr/local/nginx/conf/nginx.conf
a. nginxの実行ユーザを、gyazo-sinatraディレクトリの所有ユーザ(ここでは aquarla)と同一になるように変更
要は、nginxプロセスがgyazo-sinatraディレクトリ配下に書き込み操作を行うことが出来ればよいのですが、ここでは分かりやすくnginxの実行ユーザを変更してしまいます。
user aquarla;
b. バーチャルホストの設定
gyazo-sinatra/public のディレクトリがバーチャルホストのドキュメントルートになるように、バーチャルホストの設定を追加します。
注意すべきは2点。
- 当たり前ですが「passenger_enabled on;」の記載を忘れると Passengerが動作しません。
- client_max_body_sizeの指定を省いてしまうと、大きめのスクリーンショットをアップロードした場合にエラーとなってしまいます。デフォルトは1MBとなっているので、余裕を持って10MBに増やしておきます。
server { listen 80; server_name gyazo.aquarla.net; root /var/www/gyazo-sinatra/public; access_log logs/gyazo_access_log; error_log logs/gyazo_error_log; client_max_body_size 10m; passenger_enabled on; }
nginx を起動
ここまで設定したら、nginxを起動します。
$ sudo /etc/rc.d/init.d/nginx start
アップロード用クライアントの準備
Linuxの場合
以下のリポジトリからソースコードをclone。
GitHub - gyazo/Gyazo-for-Linux: Gyazo for Linux
gyazoスクリプトをエディタで開き、HOST変数、CGI変数を修正します。
$ git clone https://github.com/gyazo/Gyazo-for-Linux gyazo_for_linux $ cd gyazo_for_linux $ vi gyazo
... HOST = 'gyazo.aquarla.net' # 'gyazo.com' CGI = '/' # 'upload.cgi' ...