SmallStyle


2011-07-02

_ 自宅サーバーが起動しなくなったので,さくらのVPSへお引越し

先週,雷がすぐ近くで落ちた影響なのか,実家のルーターや自宅サーバーの電源まわりに異常が発生したようです.ルーターの方は結構古い有線ルーターだったので,この機会に無線ルーターに変更しました.このサイトを動かしていた自宅サーバーのほうも同時期に起動しなくなってしまい,この間,約 1 週間ほどアクセスできない状態でした.

週末になって実家のネットワーク環境の変更やらサーバーの様子を見に帰ってきましたが,サーバーの方はスイッチをいれても電源が入らず,まったく起動しない状態でした.幸い, HDDの方は無事だったので,必要なデータはすべて救出.

かれこれ 8 年ほど稼働させていましたが,そろそろ限界も近かっただろうし.自宅サーバーをリプレイスするよりも,安価に VPS を利用できるようになっているので,さくらインターネットの VPS に引越ししました.

NEC Aterm WR8700N(HPモデル) PA-WR8700N-HP

NEC
¥ 9,450


2011-07-03

_ ふらっと金沢にいってきた

城端 SA ではヤギにあえたりします

温泉に行きたいな,ということで,今回は金沢方面へ.日曜の午前中,以前ならひるがの高原 SA とか入るのに待たなきゃいけないとかいう状態だったけど,高速道路 1000 円も終わったからか,すんなりと入れた.ここに立ち寄る目的はソフトクリームを食べたいから.城端 SA ではヤギにあえたりします.

この日は以前と同じく,昼に寿司を食べに行ってそのまま,早めに宿にチェックイン.まだ,昼のお客の団体がいるようで,いつもはほぼ貸し切りな感じの大浴場も客が多めだった.

夜に部屋から蛍が見えるということで,外を見てみると 3 匹ほど確かに光ってた.


2011-07-04

_ 白山スーパー林道から白川郷へ

ふくべの大滝

石川県の観光企画で『温泉に泊まって』白山スーパー林道片道無料キャンペーン(PDF)というのをやっていて,石川県内の温泉旅館に宿泊すると「白山スーパー林道」の片道分の通行料金が無料になるとのこと.特に予定もなかったので帰りは白山スーパー林道を使って帰ることにしました.チェックアウト時に申請書に必要事項を書いて無料利用券をもらいました.

白山スーパー林道へ向かう途中の道の駅「瀬女」に立ち寄ったところ,そばのお店「山猫」があったので,ちょうどお昼に近かったのもあって,ここでそばを食すことに.せいろは細切りそばでしたが,しっかりとした麺でおいしかったです.個人的にはちょっとツユが辛めだったかなぁ.そんなに量はないので,空腹時はセットなどを頼んだほうがいいかも.

合掌造り

白山スーパー林道は石川県側はいくつかの滝を見ることができ,ふくべの大滝が名所のようです.岐阜県側に入ると,眺めは緑が多く遠くに山々が見え,石川県側とはまた違って景色を見られます.岐阜県側の展望台からは遠くに白川郷の合掌造りを眺められます.そういや途中はまだこの時期でも雪が残っているところもあった.

白山スーパー林道を通って岐阜県側に出てくると,白川郷にでてきます.せっかくなので立ち寄ってみることに.合掌造りは大きなものだと 4 階まであるとか,知らなかったけど大きいんですね.


2011-07-07

_ 校正プラグインを更新

さくら VPS に移転してから校正プラグインの結果表示が正しくなかったのと,編集エリアへのカーソル移動も正常に動作していなかったので修正した.

JavaScriptについては js ファイルにわけたので更新された場合は js ファイルも有効にするのをお忘れなく.


2011-07-11

_ Devise で認証が必要な URL に対して .NET のアプリケーションからアクセスする

Rails3 + Devise で認証が必要なサービスに対して,.NET で作った Windows アプリからアクセスする方法について,認証が必要な Web インターフェースと,Web API の提供を同時に実現した場合に,Devise を利用していて動作させるための自分なりの整理.

作成する Windows アプリは特定の URL にデータを POST するアプリケーション.そのサービスはユーザー認証が必要なサービスで,データの POST にも当然認証が必要となる.サービス側は Rails で構築していて,認証エンジンには Devise を利用し, Devise が標準で対応している Basic 認証を利用することにした.(実際にサービスとして外に出すのであれば,Basic 認証を利用する場合は SSL 通信での利用も考えないといけない).

Rails3 + Devise で簡単な Web アプリを作る

まずは Rails3 と Devise を使って簡単な Web アプリケーションを作る.確認のためのサンプルなので,単純なテキストデータの CRUD アプリケーションとする.

$ rails new sample
$ cd sample

Gemfileに "gem 'devise' を追記して,bundle install を実行する.

$ bundle install

依存するライブラリのインストールがすんだら,Devise のイニシャライザーをインストールする.

$ rails generate devise:install

ユーザー管理をするモデルを作成する.ここでは User クラスとする.作成できたらデータベースの migrate を行う.またログインに必要な画面についても,標準的なものが Devise で用意されているのでそれを利用する.

$ rails generate devise user
$ rake db:migrate
$ rails generate devise:views

あとはアプリケーションとして必要なものを作成していく.ここではごく簡単なテキストを追加していくようなものなので scaffold でサクっと作ってしまう.

$ rails generate scaffold memo message:text user:references
$ rake db:migrate

root を MemosController の index とするため,config/route.rb に root :to => "memos#index" と定義し, public/index.html は削除しておく.あとは認証が必要となるように設定する.MemosController クラスに対して,before_filter を定義し,あとはログインしたユーザーの情報のみを返すようにそれぞれ修正します.

class MemosController < ApplicationController
	
	before_filter :authenticate_user!
	
	# GET /memos
	# GET /memos.xml
	def index
		@memos = current_user.memos
		respond_to do |format|
			format.html # index.html.erb
			format.xml  { render :xml => @memos }
		end
	end
	
	# GET /memos/1
	# GET /memos/1.xml
	def show
		@memo = current_user.memos.find(params[:id])
		respond_to do |format|
			format.html # show.html.erb
			format.xml  { render :xml => @memo }
		end
	end
	
	# GET /memos/new
	# GET /memos/new.xml
	def new
		@memo = Memo.new
		respond_to do |format|
			format.html # new.html.erb
			format.xml  { render :xml => @memo }
		end
	end
	
	# GET /memos/1/edit
	def edit
		@memo = current_user.memos.find(params[:id])
	end
	
	# POST /memos
	# POST /memos.xml
	def create
		@memo = current_user.memos.build(params[:memo])
		respond_to do |format|
			if @memo.save
				format.html { redirect_to(@memo, :notice => 'Memo was successfully created.') }
				format.xml  { render :xml => @memo, :status => :created, :location => @memo }
			else
				format.html { render :action => "new" }
				format.xml  { render :xml => @memo.errors, :status => :unprocessable_entity }
			end
		end
	end
	
	# PUT /memos/1
	# PUT /memos/1.xml
	def update
		@memo = current_user.memos.find(params[:id])
		respond_to do |format|
			if @memo.update_attributes(params[:memo])
				format.html { redirect_to(@memo, :notice => 'Memo was successfully updated.') }
				format.xml  { head :ok }
			else
				format.html { render :action => "edit" }
				format.xml  { render :xml => @memo.errors, :status => :unprocessable_entity }
			end
		end
	end
	
	# DELETE /memos/1
	# DELETE /memos/1.xml
	def destroy
		@memo = current_user.memos.find(params[:id])
		@memo.destroy
		respond_to do |format|
			format.html { redirect_to(memos_url) }
			format.xml  { head :ok }
		end
	end
end

また,現在のログインユーザーなどがわかるようにヘッダーなどを layout/appliation.html.erb に追記しておく.

...
<div>
<% if user_signed_in? %>
<%= current_user.email %> でログイン中です.<%= link_to "ログアウト", destroy_user_session_path %>
<% else %>
<%= link_to "ログイン", new_user_session_path  %> | <%= link_to "新規登録", new_user_registration_path%>
<% end %>
</div>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
...

ここまでできたらとりあえず起動してみてサービス側は一通り動作することが確認できる.

$ rails server

新規ユーザーの登録,ログイン,ログアウトなどが可能となっていることがわかる.

この時点ではまだ Devise は Basic 認証に対応させていないため,試しに curl などでアクセスしてみるとログイン画面に転送されることが確認できる.

$ curl --basic --user foo@example.com:password -d memo[message]=hello http://127.0.0.1:3000/memos.xml
<?xml version="1.0" encoding="UTF-8"?>
<errors>
  <error>You need to sign in or sign up before continuing</error>
</errors>

Devise を Basic 認証でも利用出来るようにするには,config/initializers/devise.rb で,config.http_authenticatable = true を設定する.設定を変更したら,サーバーを再始動し再度 curl などでアクセスしてみると,ログイン後の画面が取得できることが確認できます.これでサービス側は完了.

<?xml version="1.0" encoding="UTF-8"?>
<memo>
  <created-at type="datetime">2011-06-29T00:00:00Z</created-at>
  <id type="integer">1</id>
  <message>test</message>
  <updated-at type="datetime">2011-06-29T00:00:00Z</updated-at>
</memo>

C#.NETクライアントアプリを作る

今回は Basic 認証が動作するか確認するためだけなので,ユーザー名とパスワード,送信するテキストメッセージは固定として以下のようなアプリケーションにしてみる.

using System;
using System.Text;
using System.Net;
using System.Collections.Specialized;
class MemoClient
{
  static void Main()
  {
    WebClient client = new WebClient();
    //client.Credentials = new NetworkCredential("foo@example.com", "password");
    client.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("foo@example.com:password")));
    client.Encoding = Encoding.UTF8;
    NameValueCollection kv = new NameValueCollection();
    kv.Add("memo[message]", "Hello World!");
    client.UploadValues(new Uri("http://127.0.0.1:3000/memos"), kv);
  }
}

アプリケーションを実行すると,正しく認証されてメッセージが DB に書き込まれていることが確認できます..Net での開発に非常に疎いので,これが正しいのかわかりませんが,検索してみつかる NetworkCredential を利用した認証情報では,サーバー側では認識されず認証が通りませんでした.そこでリクエストヘッダーに直接 Authorization を追加してユーザー名とパスワードを送信したところ,正しく動作しました.

Devise で Basic 認証を有効にした場合,ブラウザでアクセスした場合は,設定変更前と変わらないフォーム認証のままになっています.通常,Basic 認証を利用する場合は,認証のダイアログが表示され,そこにユーザー名とパスワードを入力しますが,この辺がどうやら異なるようです.試しに,サービス側の認証を Devise ではなく,ActionController の authenticate_or_request_with_http_basic を利用するようにしてみました.こちらの方法だとブラウザでアクセスしたときもダイアログが表示され,クライアントアプリでも NetworkCredential を利用した認証情報を利用することができました.

curl での Basic 認証では問題なく利用できたのに Windows クライアントアプリからだと NetworkCredential が利用できないというのがいまいち理解できないのだけれどなんでなんだろう….


2011-07-13

_ tDiary を fcgi での運用に変更した

サーバーのレスポンスタイムのグラフ

さくらのVPSに移ってからしばらく cgi で動作させていたのを fcgi に変更した.

体感的にも早くなったのが感じらる.外部からの監視サービスに Site24x7 を以前から利用していて,そこからはレスポンスタイムについてもレポートしてくれて,ちょうど切り替えたところでレスポンス時間がグッとよくなっているのがグラフからもよくわかる.

切り替え前のレスポンスタイムが平均して 1,700ms だったものが,平均して 893ms となっている.


2011-07-14

_ qpdf を使って PDF のパスワードを除去する

給与明細が PDF で送られてくるけど手元に保存しておくのにパスワードがついてると面倒なので,パスワードを除去した状態にしたいと思って,なんとかできないか探してみた.やり方は何種類かあるみたいだけど,OS X の環境では homebrew でインストールできるパッケージで簡単に使えそうな qpdf を利用してみることに.qpdf をインストールしたら以下のように実行する.

$ qpdf --password=PASSWORD --decrypt input.pdf output.pdf

これだけで,パスワードが除去された PDF にすることができる.なんともあっさりできるもんだ.


2011-07-19

_ VPS 上の日記データを QNAP へ rsync+ssh で定期的にバックアップする

いつ何時,何が起こるかはわからないので,バックアップって大事ですね.ここのところは歯抜けが多いものの,なんだかんだで 8 年以上もここで Web 日記を書いてきているものなので,このデータが失われるとやっぱりショックは大きいだろうし.これまでは手元にマシンがあって,ふと思い立ったときに外付けHDDにバックアップをとるとか気まぐれでやってたけど,VPSに移行したので定期的に手元にバックアップデータをとるようにした.

ということで,我が家のデータのバックアップはすべて QNAP に集めているので,VPS 上のデータもこちらにバックアップするようにした.最初は,VPS 側は lsyncd を導入して,日記のデータを更新したらすぐにバックアップをとるようにしようかとも考えたけれども,まずは無難に QNAP 側から定期的に VPS に対して rsync + ssh で同期することにした.

rsync用の鍵ファイルを準備する

QNAP から VPS のデータを取得する処理は定期的に自動で実行されるので passphrase なしの秘密鍵を作成する.

# ssh-keygen

鍵ファイルは例えば rsync_id_rsa とか.QNAP上で作成する場合,ファームウェアのバージョンによっては,鍵ファイルの作成がデフォルトでは /share/homes/admin/.ssh 以下となっているけどディレクトリが存在しない場合もあるので,その場合は鍵を作成するときのパスは /root/.ssh/rsync_id_rsa などにしておくといい.後ほど出てくるけど,最終的には /root のシンボリックリンクを /share/homes/admin にはることで対応している.

VPSにログインできるようにする

VPS側はすでに SSH でのアクセスができることを前提として,先ほど作成した鍵ファイルでアクセスできるように設定する.今回は日記データは www-data ユーザーとしてログインしてデータを取得することにしてみた.Ubuntu の場合,/var/www 以下に .ssh ディレクトリを作成して,authorized_keys に公開鍵を追記しておく.

また,authorized_keysにcommandオプションを追加することで,接続時に指定したコマンドを実行することができるので,ここでは試しに ls コマンドを指定しておく.

command="/bin/ls" ssh-rsa AAA...

QNAPから VPS にアクセスしてみる

QNAP から VPS に接続してみる.

# ssh -i /root/.ssh/rsync_id_rsa www-data@sakura
dir1 dir2 file1
Connection to sakura

command で指定した処理が実行され接続が切断されれば問題なし.また,known_hosts ファイルのパスが /share/homes/admin となっている場合で,実際にディレクトリが存在しない場合は,シンボリックリンクを作成しておく.

# mkdir /share/homes
# ln -s /root /share/homes/admin

再起動するとこれは消えてしまうので,autorun.sh に記述しておく.

rsyncでデータをとってくる

QNAP で以下の rsync コマンドを実行すると以下のような表示がされます.これは必ずエラーになる.保存先のディレクトリはここでは例として /share/sakura/www とする.

# rsync -avvz -e "ssh -2 -i /root/.ssh/rsync_id_rsa" --exclude "/www/data/cache/" www-data@sakura:/var/www/www /share/sakura/www
opening connection using: ssh -2 -i /root/.ssh/rsync_id_rsa -l www-data sakura rsync --server --sender -vvlogDtprze.is . /var/www/www 
protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(171) [receiver=3.0.6]

ここで opening connection から始まる行に記載されている以下のコマンドを VPS の authorized_keys の command オプションに記述します.

rsync --server --sender -vvlogDtprze.is . /var/www/www

再度,QNAPから rsync コマンドを実行すると問題なければ同期がはじまります.8 年分の日記データは画像も含めると約 100 Mほど.思ったよりも多くてちょっとびっくり.初回はデータ量によっては時間がかかりますが,2回目以降は差分のみとなるため短時間ですむと思います.

cronに設定する

/etc/config/crontab に追加して,/tmp/cron/crontab/admin にも記入.あとは /etc/init.d/crontab.sh restart すれば定期的にバックアップできる.ログに出力するなりしてうまく動いているかは確認しておく.


2011-07-22

_ 絵日記プラグインで複数ファイルアップロードに対応させる

ファイルの選択で複数ファイルをサポートした場合

HTML5 では input タグに対して multiple 属性を指定すると複数の値を入力,選択できるようになります.tDiary の絵日記プラグインではまだサポートされていなくて,一つづつアップロードするのもそろそろ面倒になってきたので,複数ファイルアップロードできるようにしてみました.

ファイルダイアログから複数を選択すると,1 つだけの場合はファイル名が表示されますが,2 つ以上のファイルを選択すると "2 ファイル"といった表示がされます.サポートしているブラウザは http://www.findmebyip.com/litmus/#mdz_input_multiple で確認してみたところでは,最近のブラウザであれば IE 以外なら使えるみたいです.

来週 29 日にリリースされる予定の, tDiary 3.1.0 にはちょっと間に合わなかったので,リリース後に取り込みをお願いすることにしよう.

追記 merge されました.


2011-07-29

_ tDiary 3.1.0 がリリースされたのでアップデートした

tDiary 3.1.0 がリリースされたのでアップデートした.といっても比較的さきっちょ追いかけてたので特に問題はなさそう.…ということで更新テストもかねて.


about me

いろいろと興味を持ったことを書いてます.ちょっとしたことは hb(@smallstyle) on Twitter で書いてます.

Archive

2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|12|