さくらのVPSを契約してnginx+Node.js+MongoDBを動かすまでのメモ
従来はさくらインターネットのレンタルサーバーのスタンダードプランしか契約してなくて、cgiしか動かせないのでちょっと大変だった。そこで思い切ってVPSを契約して動かしてみた。とりあえずメモ。
さくらのVPSを契約
- CPU仮想2コア
- メモリ1GB
- HDD100GB
- 月額980円(年額10,780円)
というプラン(一番安いやつ)にした。
契約後、すこし待つと、メールでrootの初期パスワードが送られてきた。
コントロールパネルに入り、マシンを起動させる。
ユーザーまわり
Macのターミナルから、
$ ssh root@(サーバーのIP) Password: (初期パスワード)
これでつながった。
まずはrootのパスワードを自分で考えたものに変更し、さらに一般ユーザー「nacookan」を作り、これにもパスワードを設定する。 そして権限を与える。
# passwd (rootの新しいパスワードを2度入力) # useradd nacookan # passwd nacookan (nacookanの新しいパスワードを2度入力) # usermod -G wheel nacookan # visudo (%wheel ALL=(ALL) ALL の行のコメントを外す) # vi /etc/pam.d/su (auth required pam_wheel.so use_uid の行のコメントを外す)
Macのターミナルからnacookanでつなぎなおす。
$ ssh nacookan@(サーバーのIP) Password: (nacookanのパスワード)
そして、鍵認証の設定。ちなみに公開鍵をまだ作ってないならMac上でssh-keygenして作っておく。
$ mkdir .ssh $ chmod 700 .ssh $ vi .ssh/authorized_keys (公開鍵をコピペ) $ chmod 600 .ssh/authorized_keys
rootに切り替えて、sshdの設定
$ sudo vi /etc/ssh/sshd_config (PermitRootLogin no と PasswordAuthentication no を追加) $ sudo service sshd restart
nacookanの鍵でつなぎなおしてみて確認。他にも、パスワード認証ができないことと、rootでは接続できないことも確認しておく。
Node.jsのインストール
nvmでやってみた。
$ git clone git://github.com/creationix/nvm.git ~/.node $ source ~/.node/nvm.sh $ nvm install v0.10.13 $ vi ~/.bash_profile (source ~/.node/nvm.sh と use "v0.10.13" を追加) $ node -v v0.10.13
MongoDBのインストール
バイナリをダウンロードしてきて展開。
$ sudo su - # cd /usr/local/src/ # wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.4.5.tgz # tar zxf mongodb-linux-x86_64-2.4.5.tgz # mv mongodb-linux-x86_64-2.4.5 /usr/local/mongodb # ln -s /usr/local/mongodb/bin/mongo /usr/local/bin/mongo # mkdir /data # mkdir /data/db
MongoDBの起動は以下。
# /usr/local/mongodb/bin/mongod --logpath=/var/log/mongodb.log &
終了は kill -2 (プロセスID) で。
アプリを作ってみる
一通り入れたと思うので、さっそく動くものを作ってみる。
nginxの設定
名前ベースのバーチャルホストにするので、わかりやすいようにホスト名でconfファイルを作ってみた。置き場所は、自動的に読み込まれる設定になってるconf.dにした。
$ sudo vi /etc/nginx/conf.d/(ホスト名).conf
中身は以下のようにする。ポート80で、ホスト名にマッチしたとき、127.0.0.1:8080にproxyするような感じで。
server { listen 80; server_name (ホスト名); location / { proxy_pass http://127.0.0.1:8080; } }
再起動しておく。
$ sudo service nginx restart
Node.js
準備。アプリのディレクトリを作って、npmでexpressとmongooseを入れる。
$ cd ~/ $ mkdir hello $ cd hello $ npm install express $ npm install mongoose
コードを書く。
$ vi server.js
server.jsの中身は以下。
var express = require('express'); var app = express(); var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/hello'); mongoose.model('Message', new mongoose.Schema({ message: String })); Message = mongoose.model('Message'); app.get('/in', function(req, res, next){ var m = new Message(); m.message = req.query.message; m.save(function(err){ res.send('OK'); }); }); app.get('/out', function(req, res, next){ Message.find({}, function(err, messages){ var list = []; messages.forEach(function(m){ list.push(m.message); }); res.send(list); }); }); app.listen(8080);
モデルは、helloっていうDBの、messagesというコレクションが、messageというフィールドを持っているという感じ。/inでは、QUERY_STRINGで渡されたデータを1件登録してOKを返す。/outでは、登録されたデータを全件出力。ポートは8080。
起動しておく。
$ node server.js
MongoDB
MongoDBは、特に設定は不要。起動だけしておけばいい。
よくあるRDBMSみたいに、データベースやテーブルを事前に作っておく必要も無い。Node.jsのコードでモデルの定義をしているので勝手に作られる。
動かしてみる
ブラウザで、
http://(ドメイン)/in?message=hoge http://(ドメイン)/in?message=fuga http://(ドメイン)/in?message=piyo
それぞれにアクセス。いずれも「OK」と返るだけだと思う。
次に、
http://(ドメイン)/out
にアクセス。さっき登録した3つが表示されれば成功。
データベースを直接見てみる
mongoコマンドを使うと、MongoDBの中を直接操作できる。
$ mongo > use hello switched to db hello > db.messages.find() { "message" : "hoge", "_id" : ObjectId("51e56f41d15d665a09000001"), "__v" : 0 } { "message" : "fuga", "_id" : ObjectId("51e56f4ad15d665a09000002"), "__v" : 0 } { "message" : "piyo", "_id" : ObjectId("51e56f4cd15d665a09000003"), "__v" : 0 } > quit()
ちゃんと3つのデータが登録されている。
ここから追記
追加で以下の作業をやった。
コンソールを日本語に
manとかでヘルプを見た時に日本語で出たほうがうれしいので、コンソールを日本語にしておく。
$ sudo vi /etc/sysconfig/i18n (LANG="C" をコメントにして、LANG="ja_JP.UTF-8" を追加)
一度ログアウトしてログインしなおす。
SSHのポートを変更
22のままだと攻撃がたくさん来てしまう。鍵認証にしてるからセキュリティ的には特に問題なくても、サーバーへの負荷という意味で困るので、ポートを変えておく。
$ sudo vi /etc/ssh/sshd_config (Port 22222を追加) $ sudo service sshd restart
22222というのは適当に書いた。マネしない方がいいし、自分も実際は違う番号にしている。各自が1024〜65535の間の好きな番号にすればいい。
他とかぶらない番号にする(たとえば8080とかは避ける)ことと、自分で設定した番号を忘れないようにするのが重要。
設定を変えたら確認してみる。Macのターミナルから、
$ ssh nacookan@(サーバーのIP) -p 22222 -i 鍵のパス
こんな風にしてつなぐ。
iptables
iptablesはデフォルトでは全開放の状態らしい。とりあえず今回は、上記で許可したSSHのポートと、HTTPの80番だけを許可するようにする。
$ sudo vi /etc/sysconfig/iptables
最初はファイルがないので新規作成。内容は以下。
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :RH-Firewall-1-INPUT - [0:0] -A INPUT -j RH-Firewall-1-INPUT -A FORWARD -j RH-Firewall-1-INPUT -A RH-Firewall-1-INPUT -i lo -j ACCEPT -A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT -A RH-Firewall-1-INPUT -p 50 -j ACCEPT -A RH-Firewall-1-INPUT -p 51 -j ACCEPT -A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22222 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited COMMIT
正直よくわからないんだけど、たぶんスタンダードな設定のはず。
- INPUTとFORWARDを「RH-Firewall-1-INPUT」というところに流して(名前はなんでもいい)、以降はRH-Firewall-1-INPUTに対する設定としている
- lo(ループバック)を許可
- icmpを許可
- プロトコル番号50と51を許可(よくわからないけどみんなやってるのでマネした)
- マルチキャストDNSを許可
- TCPとUDPの631番、プリンタの通信を許可(これは無くてもいい気がする)
- stateモジュールを使う
- 新規接続の22222を許可(SSHのポートね)
- 新規接続の80を許可(HTTPのポートね)
- それ以外は拒否
こんな感じの意味だと思う。
sudo service iptables restart
これで新しい設定が反映される。
アップデート
インストールされているもろもろについて、最新版の状態に更新しておく。
$ sudo yum --security update
やってみたけど、自分の場合は特に更新はなかった。さくらのVPSは最新版が入った状態で提供されてるってことかな。今後、定期的にこれを実行して最新版を維持する必要がある。自動更新する仕組み等もあるらしいけど試してない。
ちなみにセキュリティ関連だけじゃなく、すべてのパッケージのアップデートをしたいなら、--securityを外せばいい。
追記ここまで
これで一通りやることはやった気がする。