LoginSignup
16
17

More than 5 years have passed since last update.

ExpressでもLet's Encryptしたい

Posted at

ExpressでもLet's Encryptでhttps通信をしたい

対象

httpsで公開するために無料でサーバー証明書を発行してくれるLet's Encryptを利用する際、公式ページを含めapacheやnginxの設定事例は数多く発見できます。
ですが、お手軽サイトはわざわざnginxをたてるまでの必要もない、Expressでサクッと公開してサクッとhttps化できればいい、という方が対象です。

実は、単なるletsencrypt-expressの紹介で、なにも目新しいものはありません・・・

環境

CentOS 7.2
Node v5.9.1
Express v4.13.4
ですが、それほど環境は選ばないと思います。

導入

letsencrypt-expressとは?

公式ではcertbotを導入して・・・というのが本筋ですが、node.jsでexpressを使用するのであれば、letsencrypt-expressという素晴らしいツールが公開されているので、それを利用します。

このletsencrypt-express、以下の利点があります。

  • 自動でLet's Encryptへの登録をしてくれます
  • Let's Encryptは90日で期限が切れるため、cron等で自動再認証のプロセスをしてくれますが、この更新作業も自動でしてくれます
  • vhost / virtual hostingを自動でしてくれます

といった特徴があります。特に、自動更新をしてくれるならラクチンです。

letsencrypt-expressのインストール

npm install --save letsencrypt-express

で一発です。

インストール後、expressコードへの埋め込み

下記のごく単純なexpress用のコードをサンプルとしていじっていきます。

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(80);

ここに、letsencrypt-expressの初期化コードを挿入します。

var express = require('express');

// letsencrypt-express用の初期化コード開始

// 次の行の.testing()は本番環境では外して下さい
var LEX = require('letsencrypt-express').testing();

// 以下の2行は環境に合わせて変更して下さい!
var DOMAIN = 'myservice.example.com';
var EMAIL = 'user@example.com';

var lex = LEX.create({
  configDir: require('os').homedir() + '/letsencrypt/etc'
, approveRegistration: function (hostname, approve) { // leave `null` to disable automatic registration
    if (hostname === DOMAIN) { // Or check a database or list of allowed domains
      approve(null, {
        domains: [DOMAIN]
      , email: EMAIL
      , agreeTos: true
      });
    }
  }
});

// ここまで初期化用コード

var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(80);

更に、letsencrypt-expressの実行部を挿入します。

var express = require('express');

// letsencrypt-express用の初期化コード開始

// 次の行の.testing()は本番環境では外して下さい
var LEX = require('letsencrypt-express').testing();

// 以下の2行は環境に合わせて変更して下さい!
var DOMAIN = 'myservice.example.com';
var EMAIL = 'user@example.com';

var lex = LEX.create({
  configDir: require('os').homedir() + '/letsencrypt/etc'
, approveRegistration: function (hostname, approve) { // leave `null` to disable automatic registration
    if (hostname === DOMAIN) { // Or check a database or list of allowed domains
      approve(null, {
        domains: [DOMAIN]
      , email: EMAIL
      , agreeTos: true
      });
    }
  }
});

// ここまで初期化用コード

var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

// ここからlets用の実行部コード
lex.onRequest = app;

lex.listen([80], [443, 5001], function () {
  var protocol = ('requestCert' in this) ? 'https': 'http';
  console.log("Listening at " + protocol + '://localhost:' + this.address().port);
});

通常は上のコードで動くはずです。以下は別サンプルで、80番ポートでアクセスしてきたら、443にリダイレクトさせたい場合です。http、spdyモジュールを利用します。npm install --save spdyでspdyモジュールをインストールしたあと、

var express = require('express');
var http = require('http');
var https = require('spdy');

// letsencrypt-express用の初期化コード開始

// 次の行の.testing()は本番環境では外して下さい
var LEX = require('letsencrypt-express').testing();

// 以下の2行は環境に合わせて変更して下さい!
var DOMAIN = 'myservice.example.com';
var EMAIL = 'user@example.com';

var lex = LEX.create({
  configDir: require('os').homedir() + '/letsencrypt/etc'
, approveRegistration: function (hostname, approve) { // leave `null` to disable automatic registration
    if (hostname === DOMAIN) { // Or check a database or list of allowed domains
      approve(null, {
        domains: [DOMAIN]
      , email: EMAIL
      , agreeTos: true
      });
    }
  }
});

// ここまで初期化用コード

// リダイレクト用
function redirectHttp() {
  http.createServer(LEX.createAcmeResponder(lex, function redirectHttps(req, res) {
    res.setHeader('Location', 'https://' + req.headers.host + req.url);
    res.statusCode = 302;
    res.end('<!-- Hello Developer Person! Please use HTTPS instead -->');
  })).listen(80);
}

// 通常の443接続
function serveHttps() {
  var app = express();

  app.use('/', function (req, res) {
    res.end('Hello World!');
  });

  https.createServer(lex.httpsOptions, LEX.createAcmeResponder(lex, app)).listen(443);
}

redirectHttp();
serveHttps();

・・・サンプルそのまんまです・・・

実行

あとはnode app.js等で実行すれば、自動でサーバー証明書をダウンロードの上、サーバーを立ち上げてくれます。
CentOS7の場合はfirewallを使用していると思うので、httpsを許可していなければ、事前に

$ firewall-cmd --permanent --zone=public --add-service=https
$ firewall-cmd --reload

をお忘れなく。

まとめ

やっぱり素直にnginx等を利用したほうがセットアップは簡単ですが(設定ファイル書き換えで完了)、なにかの参考になれば。

16
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
17