Edited at
herokuDay 23

Herokuでマルチ(バーチャル)ホストを実現してかしゆかをお祝いする

おめでとうございます。本日はかしゆかの誕生日、良い休日ですね。元気に過ごされていますか、しょっさんです。

Heroku Advent Calendar 2018 23日目、一人で4本目になります、ホント申し訳ない。

かしゆかをどのようにHerokuでお祝いするかと一所懸命考えていたときに、ふと昔作ったテストのサイトを思い出したので、そちらを紹介します。ふくすうの「これはできるの?」に回答できる内容です。


  • Private Space で ACMは使えるの?

  • Heroku でマルチ(バーチャル)ホストは使えるの?

答えはともに「YES」です。具体的な実装方法です。


Automated Certificate Management in Private Space

2018/5/24に紹介されていますが、ACM機能は Private Spaceでも利用可能になりました。ACMとは、Let's Encrypt証明書を自動的に発行・更新し、SSLのサイトを適用するものです。具体的な利用方法については拙作「Herokuの運用とセキュリティ~HerokuでSSL証明書の自動化とPrivate Spacesでセキュリティを強化しよう」をごらんください。

Private Space利用時にも、自動的にSSL証明書を発行し、更新してくれるのお便利ですね。


Heroku でマルチホストはどうするの?

同じくドメイン周りの設定になりますが、具体的な手順を説明します。

Herokuアプリケーションのダッシュボードから、「Settings」タブへ移動します。

中程に「Domains and certificates」があります。見てわかるように、すでに2つ登録されていますね。なんとなく想像がついたと思いますが、「Add domain」ボタンをクリックします。

Screen Shot 2018-12-22 at 13.37.13.png

「New domain」画面が現れますので、登録したいホスト名(FQDN)をここに入力します。すでに割り当て済みのホスト名の場合(多分、名前解決やってみてA/CNAMEなどが割り当てられていると)は、エラーが出て登録できません。

Screen Shot 2018-12-22 at 13.37.54.png

先程の画面に戻ってきますと、登録したホスト名が追加されています。これで3つになりましたね。

Screen Shot 2018-12-22 at 13.38.26.png

DNS Targetという欄があります。ここがCNAMEとして登録すべきホスト名が入っています。おもむろに、ご自分で管理されているDNSサーバにて、該当のFQDNにたいしてCNAMEとして、このDNS Targetのホスト名を入れます。たいていは45〜60分でACM含め登録が完了します。正常に登録されると、上2つのようにACM Statusが「OK」となります。


プログラム側ではどのように対処するの?

HTTP/1.1以上でアクセスしてくるの絶対のはずなので、HTTPヘッダのhostにアクセスしてきたホスト名が入っているはずです。各言語で取得方法は変わるでしょうが、例えば Node.js + Express では次のようになります。


index.js

var express = require('express');

var router = express.Router();

/* GET home page. */
router.get('/', function (req, res, next) {
const hostname = req.headers.host;
console.log('hostname = ' + hostname);

if (hostname.match(/^localhost/))
res.render('local', { title: 'access to localhost' });
if (hostname.match(/^multi.kashiyuka.info/))
res.render('kashiyuka', { title: 'access to kashiyuka' });
if (hostname.match(/^multi.prfm.jp/))
res.render('index', { title: 'Heroku Meetup #23' });

console.log('no hostname');
let err = new Error('host not found');
err.status = 400;
next(err);
});


localhostmulti.kashiyuka.infomulti.prfm.jp それぞれで異なるページをレンダリングしていることがわかります。これだけです。

2つのサイト、適当にアクセスしてみてくださいね。今日のお土産はそちらです。