以下省略!

タイダルウ(ry ほぼ毎日1記事執筆運動実施中。 ※記事に広告(アフィリエイト)リンクを掲載している場合があります。

nginx+DockerでLiskウォレット(公開)を動かしてみた

f:id:abyssluke:20160614070041p:plain:w200:leftLiskはDockerでもウォレットを動かすことができ、設定すればHTTPSにも対応する。というわけで試しにVPSにDockerとnginxでウォレットを入れてインターネット上に公開してみた(ただしURLはまだ公開しないチキン)。ポート443はすでにnginxが使っているのでnginxをウォレットが動いているコンテナへのリバースプロキシとして利用することにした。ちょっと長いので続きを読むから。

目次

通信の流れっぽいの

こういう感じで。

|-----------外部-----------|-------------------内部---------------------|
Client ←(HTTPS)→ VPS nginx( ←(内部での通信/HTTP)→ Docker Container(Lisk) )

※環境によってはずれるかも

クライアントからLiskウォレットに対してVPSのnginxにHTTPSでアクセスがあるとnginxはHTTP(VPS内部での通信)でVPS内Dockerのコンテナで動作しているLiskウォレットに接続、その結果をクライアントに返すという構図。

コンテナを立ち上げる

公式の方法にならって。初回起動時はコケることがあるのでrunしたらしばらくしてコンテナの再起動かnodeプロセスの強制終了をしたほうがいいかも。

$ docker pull lisk/mainnet
$ docker run -d --restart=always -p 0.0.0.0:8000:8000 lisk/mainnet

※「0.0.0.0:」は不要か??

localhost:8000でコンテナ内にアクセスできるようポートマッピングをしておく。
念の為ホスト側の8000ポートはiptablesで外部からアクセスできないようにしているが、塞がないほうがいいのかは不明。

最低限的なアレ

テストのためHTTPでリバースプロキシの設定をしてみる。SSL証明書を取得するまでの最低限の設定なので通常運用時は激しく非推奨。

server {
	listen 80;
	listen [::]:80;
	server_name lisk.example.com;
	location / {
		proxy_pass http://localhost:8000/;
		proxy_redirect default;
	}
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Real-IP $remote_addr;
}

※lisk.example.comは実際のホスト名に置き換える

sudo nginx -s reload後、アクセスしてみて無事にLiskの画面が出てくれば大丈夫。

リバースプロキシ設定の注意

LiskウォレットはSocket.IOを使っているので、

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;

の記述をしておくべし。locationディレクティブを使い/socket.io/に対してのみ適用でもいいかも。

Let's Encryptで証明書を取得できるようにしておく(webrootモードの場合)

HTTPのserverディレクティブ内のlocation /の前に以下のような記述をしておく。これによりドメイン認証用のファイルにリバースプロキシを通さずにアクセスすることが可能になる。

location ^~ /.well-known/acme-challenge/ {
	root /path/to/siteroot;
}
location = /.well-known/acme-challenge/ {
	return 404;
}

※/path/to/siterootはnginxが読み書き可能な適当なディレクトリでいいと思う

あとは普通にwebrootモードで証明書を取得する。筆者がベータ版からLet's Encryptを使っている関係上、以下ではletsencryptと記述しているが、今はcertbotという名前でもあるので必要に応じて読み替えること。

$ cd letsencrypt
$ ./letsencrypt-auto certonly --webroot -w /path/to/siteroot -d lisk.example.com

使っているconfigの例(証明書取得後)

証明書を取得したあとは以下のように設定。少し改善したほうがいい所はあると思うが。

server {
	listen 80;
	listen [::]:80;
	server_name lisk.example.com;
	return 301 https://$server_name$request_uri;
}
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name lisk.example.com;

        access_log /var/log/nginx/lisk.example.com.access.log;
        error_log /var/log/nginx/lisk.example.com.error.log;
	ssl_certificate /etc/nginx/ssl/fullchain_lisk.pem;
	ssl_trusted_certificate /etc/nginx/ssl/chain_lisk.pem;
	ssl_certificate_key /etc/nginx/ssl/privkey_lisk.pem;
	ssl_stapling on;

        add_header Strict-Transport-Security max-age=15768000;
	location ^~ /.well-known/acme-challenge/ {
		root /path/to/siteroot;
	}
	location = /.well-known/acme-challenge/ {
		return 404;
	}
	location / {
		proxy_pass http://localhost:8000/;
		proxy_redirect default;
	}
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Real-IP $remote_addr;
}

そういえば

  • テスト中にメインウォレットのパスフレーズをHTTPで垂れ流してしまったので安全上新たにウォレットを作りなおしたのは秘密。もちろん残高も移し替え済み。
  • ホスト〜コンテナ間の通信もHTTPSじゃなきゃいやだという場合は適当にオレオレ証明書でも作ってLiskの設定ファイルとか弄ればいいかもしれない(nginxはオレオレ証明書でも普通に通信するんだっけ?)。
  • HTTP2を有効化しているが有効化されていない罠。それどころか他のサイトのHTTP2も無効化されているっぽい…
    • いろいろ調べたがよくわからない。streamディレクティブとかを組み合わせたらいいのか?
    • 何か情報があればこっそり教えて欲しいのです。。
    • 2016/06/16 07:42 追記: Chromeが51よりTLS-NPNのサポートを取りやめたことが原因っぽい。ALPNに対応できるようOpenSSLを更新してnginxをカスタムビルドすればなんとかなるっぽい。Firefoxで接続したところHTTP/2で繋がった。