新しくなった さくら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サーバを立ててしまったほうが色々と融通が利いて良さげだったりします。

Gitのインストール

Gyazo関連のソースコードGithubからひっぱってくる必要があるので、まずはGitをyumからインストール。

$ sudo yum install git

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

Sinatra のインストール

次はSinatraをgemでインストール。こちらも特に問題なく通るはず。

$ sudo gem install sinatra

gyazo-sinatraソースコードを取得

GyazoGithubリポジトリには、以下のようなアップロード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'
...
Macの場合

以下のリポジトリからソースコードをclone。
GitHub - gyazo/Gyazo: Gyazo: the simplest and fastest screenshot uploading tool
Gyazo.app/Contents/Resources/script が、Linux版と同様のrubyスクリプトになっているので、HOST/CGIの両変数を変更すればOKです。

Windowsの場合

以下のリポジトリからソースコードをclone。
GitHub - gyazo/Gyazowin: Gyazo for Windows
Visual C++ 2010だとビルドが通らなくて少しハマったのですが、プログラムの実体はgyazowin.cppにあるので、新規プロジェクトを作り直してgyazowin.cppの中身をコピーすればコンパイル出来た記憶が…。ここらへんは次回あたりに説明します。

各クライアントからスクリーンショットのアップロードに成功すれば作業完了です!おつかれさまでした!

おわりに

このエントリでは、新しい「さくらのVPS」をプライベートGyazoサーバとして活用するための環境構築手順を紹介しました。

リニューアルされた「さくらのVPS」は、一番下の「さくらのVPS 1G」プランでもHDDが100GBも用意されているので、ディスク容量を気にすることなく、PCのスクリーンショットをガンガンアップロードすることが出来るようになりました。

この機会にあなたも自分専用のGyazoサーバを構築してみませんか?