なっく日報

技術やら生活やらのメモ

Node.jsをunix domain socketでlistenしたときにNginxからプロキシできない

という現象に対応した際のメモ。

環境

CentOS 7 on VirtualBoxです。

Nodeのソース

// express使っている
var sockPath = '/tmp/node.sock';
var server = app.listen(sockPath, function() {
  console.log('Listening on port %d', server.address().port);
});

nginx.conf

worker_processes  1;

events {
  worker_connections  1024;
}

http {
  upstream app {
    server unix:/tmp/node.sock;
  }

  server {
    location / {
      proxy_pass http://app;
    }
  }
}

現象

curl localhost

すると 502Bad Gatewayが返る。

nginxのerror.logには

2015/07/29 11:05:16 [crit] 10781#0: *1 connect() to unix:/tmp/node.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/node.sock:/", host: "localhost"

とな。

対処方法

とりあえず、ググってみたところ、下記のページがひっかかりました。

serverfault.com

/tmpをプロセス間のコミュニケーションに使ってはいかんと最近はなっているとのこと。

試しに、/tmp/var/lib/appに変更してみました。

すると今度はPermission deniedと怒られました。

2015/07/29 11:26:03 [crit] 10995#0: *15 connect() to unix:/var/lib/app/node.sock failed (13: Permission denied) while connecting to upstream, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/var/lib/app/node.sock:/", host: "localhost"

更にググったところ

stackoverflow.com

な回答があったので、

以下のコマンドでnginxをnode.jsのアプリのフォルダに触れるようにし、

chown nodeuser:nginx /var/lib/app
chmod g+rxs /var/lib/app # これでnginxグループのrxがnode.sockにも継承される!

さらに、

var sockPath = '/var/lib/app/node.sock';
try {
  fs.unlinkSync(sockPath);
} catch(e) {
}
var server = app.listen(sockPath, function(err) {
  if (err) throw err;
  fs.chmodSync(sockPath, '660');
  console.log('Listening on port %d', server.address().port);
});

な感じで、なんとか動くようにはなりました。

なお、node.sockにはnginxグループのwrite権限が必要なので、chmodSyncは必要です。

が、イマイチスマートでない。。納得いかない。。

※追記:こちらの方法でいけるかもしれない(試してはいない)

lxyuma.hatenablog.com