サブディレクトリオプションについて

はてなブログは、ご自身が管理されているコーポレートサイトなどと同じドメイン(サブディレクトリ)にはてなブログを設置できます。プランの申込後、すぐにサブディレクトリの設定を開始することができます。

サブディレクトリに設置すると、企業サイト全体の信頼性の向上、SEO観点でのメリット、解析でのメリットなどが見込めます。

サブディレクトリの設定は、「はてなブログBusiness サブディレクトリオプション」「はてなブログ for DevBlog サブディレクトリオプション」のいずれかの有料プランに加入しているブログで利用できます。

サブディレクトリオプションの仕組み

サブディレクトリオプションは、ご自身のサーバーにリバースプロキシを構築いただき、そこにはてなブログを組み入れていただく構成で実現しています。そのため、ご自身のサーバーにリバースプロキシを構築できることが必須の条件となります。

https://cdn.blog.st-hatena.com/files/13574176438099786264/4207112889903868922

リバースプロキシの構築については、以下の環境にて動作を確認しております。

  • nginx
  • Apache HTTP Server
  • Amazon CloudFront
  • Fastly
  • Cloud Functions for Firebase*1
  • AWS Amplify

ただし、ご利用の環境によっては、正常に動作しない可能性も考えられますので、予めシステム管理者にご相談の上、お申し込みください。

「サブディレクトリオプションを申し込んだもののリバースプロキシの設定が不可だった」という場合を考慮し、サブディレクトリオプションは、申込後1ヶ月間は無料での解約、返金を承っています。安心してお申し込みください。

サブディレクトリオプションの導入について

サブディレクトリ設定アシスタントを提供していますので、実際に導入する際にこちらから設定をお願いいたします。
本項では、導入の可否や工数の検討などにご利用いただくため、サブディレクトリオプション利用者が管理するサーバーにて設定が必要な「リバースプロキシ設定」及び「robots.txt」の設定について紹介いたします。

リバースプロキシの設定

冒頭に記載したとおり、サブディレクトリオプションは、ご自身のサーバーにリバースプロキシを構築いただき、そこにはてなブログを組み入れていただく構成で実現しています。
ここでは、はてなブログを https://example.com/blog/に設定する際の例を紹介いたします。

設定すべき項目
  • 特定のパスへのリクエストをはてなブログへ向ける設定
  • Origin Domain(はてなブログのDomain)の設定
    • リバースプロキシからリクエストを受け入れるはてなブログのURLの指定を指定します
    • サブディレクトリ設定をすすめると、ブログを作成した際に指定したURL( 例: https://example.hatenablog.com )でブログを閲覧することができなくなり、URLが https://0123456789.hatenablog-oem.com といったようなURLに変化します。このURLが、リバースプロキシからリクエストを受け入れるはてなブログのURLとなります。また、変化後のURLは、リバースプロキシ経由でのみ閲覧可能な状態になります。
    • 指定すべきURLは、サブディレクトリ設定アシスタントにて確認することができます
  • リクエストヘッダへの X-Forwarded-Host の付与
    • アクセス先ブログの識別に利用するため、 X-Forwarded-Host を付与する必要があります
  • リクエストヘッダへの X-Forwarded-For の付与
    • 一部の機能でユーザのIPアドレスを利用するため、X-Forwarded-For ヘッダを設定する必要があります
  • リクエストヘッダへの X-Hatena-Blog-Subdirectory-Token の付与
    • 権限のないユーザーによる不正な設定を防止するため、X-Hatena-Blog-Subdirectory-Token ヘッダを設定する必要があります。トークンの値は、サブディレクトリ設定アシスタントにて確認することができます
設定時に注意すべき事項
  • ページのキャッシュは行わないでください。記事内容を更新しても反映されない問題が発生する可能性があります
  • 基本的に閲覧者のリクエストの内容は、そのままはてなブログに渡すようにしてください。プロキシで変更を加えるとサービスが正常に動作しなくなる可能性があります
    • ただし、サブディレクトリオプション利用者が提供しているサービスのセッションcookieなど、はてなブログで利用していないことが明らかなデータについては、プロキシでフィルタしていただいても構いません
具体的な設定例

この項では、上記で紹介した設定項目を、代表的なWebサーバにて行う際の設定例を紹介します。

nginx
location /blog/ {
    proxy_set_header X-Forwarded-Host example.com;
    proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header X-Hatena-Blog-Subdirectory-Token 1234567890abcdef;

    # ホスト名の名前解決を適時行うため、ホスト名を変数に代入してから利用します。
    # これを行わない場合、はてなブログのサーバーのIPアドレスが変更になった際に、
    # それに追従できず、ブログへのアクセスができなくなります。
    set $backend 0123456789.hatenablog-oem.com;

    proxy_pass https://$backend;
}
Apache HTTP Server
<VirtualHost *:443>
  ServerName "example.com"
  SSLProxyEngine on
  RequestHeader set X-Hatena-Blog-Subdirectory-Token "1234567890abcdef"

  # ProxyPassMatch ディレクティブを利用すると、VirtualHost ディレクティブの
  # ServerName で指定したホストが X-Forwarded-Host の値として設定されます。
  # この例では X-Forwarded-Host ヘッダの値は example.com になります。
  # また、 X-Forwarded-For ヘッダも自動的に設定されます。
  # このため、利用者のIPアドレスをはてなブログMediaに伝えるための特別な設定は必要ありません。
  <LocationMatch ^/(blog/.*)>
    ProxyPassMatch https://0123456789.hatenablog-oem.com/$1
  </LocationMatch>
</VirtualHost>
Amazon CloudFront Origin Settings
項目
Origin Domain 0123456789.hatenablog-oem.com
Protocol HTTPS only
Minimum origin SSL protocol TLSv1.2
Origin Path (空)
Add Custom Headers (下記表の通り)
Add Custom Headers
項目
Header Name X-Forwarded-Host
Value example.com
項目
Header Name X-Hatena-Blog-Subdirectory-Token
Value 1234567890abcdef

X-Forwarded-For ヘッダは自動的に設定されるため、設定する必要はありません

Cache Behavior
項目
Path pattern blog/*
Origin and origin groups 上記で追加した Origin
Viewer Protocol Policy Redirect HTTP to HTTPS
Allowed HTTP Methods GET,HEAD,OPTIONS,PUT,POST,PATCH,DELETE
Cache key and origin requests (下記表の通り)
Cache key and origin requests
項目
Cache policy CachingDisabled
Origin request policy AllViewerExceptHostHeader
Distribution Settings
項目
Alternate Domain Names (CNAME) example.com
Fastly Domains
項目
Domain Name example.com
Comment 任意の値
Condition
項目 備考
Type Request
Name first condition 任意の値
はてなブログ独自ヘッダの付与
Apply if ... req.url.path ~ "^/blog/"
Priority 10 Advanced option内
項目 備考
Type Request
Name second condition 任意の値
X-Forwarded-Forの付与
Apply if ... req.url.path ~ "^/blog/"
Priority 11 Advanced option内

1つのConditionで「はてなブログの独自ヘッダの付与」と「X-Forwarded-Forを付与した上でリクエストをパスする」の設定を行うと、意図通りに動作しないため、2つのConditionを作成し、順に処理する設定にしています。

Origins/Hosts
項目
Condition 上で作成した「first condition」を指定
Name 任意の値
Address 0123456789.hatenablog-oem.com
Enable TLS? Yes, 443
Verify certificate? Yes
Certificate hostname 0123456789.hatenablog-oem.com
SNI hostname 0123456789.hatenablog-oem.com
TLS CA certificate (空)
Shielding (none)
Health check (none)
Auto load balance Yes
Weight 100
Override host 0123456789.hatenablog-oem.com
Request settings
項目
Condition 上で作成した「second condition」を指定
Name 任意の値
Action Pass (do not cache)
X-Forwareded-For Append
Content/Headers
項目
Condition 上で作成した「first condition」を指定
Name 任意の値
Type Request
Action Set
Destination http.X-Forwarded-Host
Source "example.com"
Priority 10
項目
Condition 上で作成した「first condition」を指定
Name 任意の値
Type Request
Action Set
Destination http.X-Hatena-Blog-Subdirectory-Token
Source "1234567890abcdef"
Priority 10
Cloud Functions for Firebase

Cloud Functions for Firebaseを使用した導入事例があり、公開ブログのはてなブログの閲覧に関して問題なく動作していることは確認できています。 しかしながら、Cloud Functionsをプロキシとして利用するため、他のプロキシ設定と比較してパフォーマンスが悪化することや、Firebaseの仕様上、Cookieの使用に制限があることから推奨できません。特に、非公開のブログにおいて閲覧用Cookieが取得できず閲覧できないという問題にご注意ください。そのため、可能な限り別の方法でのプロキシ導入をおすすめいたします。

firebase.json の設定例
  "rewrites": [
  {
  "source": "/blog/**",
  "function": "apiProxy"
  },
  // ... その他のリソースの設定
  ]
Cloud Functions でプロキシするコード例
 const functions = require("firebase-functions");
 const proxy = require("express-http-proxy");
 const app = require("express")();
 const apiHost = "0123456789.hatenablog-oem.com";
 app.use(
     "/",
     proxy(
         apiHost,
         {
             proxyReqOptDecorator: (proxyReqOpts, srcReq) => {
                 proxyReqOpts.headers["X-Forwarded-Host"] = "example.com";
                 proxyReqOpts.headers["X-Hatena-Blog-Subdirectory-Token"] = "1234567890abcdef";
                 return proxyReqOpts;
             },
             proxyReqBodyDecorator: (bodyContent, srcReq) => {
                 return srcReq.rawBody || Buffer.from([]);
             }
         }
     )
 );
 exports.apiProxy = functions.region('asia-northeast1').https.onRequest(app);
利用しているライブラリのバージョンが古い場合、正常に動作しない場合があります。
AWS Amplify AWS Amplify を利用して構築したウェブサイトに、サブディレクトリオプションを利用したはてなブログを組み込む場合、AWS Amplify 単体の機能ではサブディレクトリオプションの設定で必要なヘッダを付加することができないため、以下のような方針で設定を行います。
  1. はてなブログへの接続をプロキシする Amazon CloudFront を作成する
  2. AWS Amplifyのリダイレクト機能の中の「書き換え」機能を利用し、1.で作成したCloudFrontに向ける
それぞれの具体的な設定方法は以下のとおりです。

1. はてなブログへの接続をプロキシする Amazon CloudFrontを作成する

設定の内容は、本ヘルプのAmazon CloudFrontの設定例と同様の内容で作成して下さい。

2. AWS Amplifyのリダイレクト機能の中の「書き換え」機能を利用し、1.で作成したCloudFrontに向ける

AWS Amplify リダイレクト設定のヘルプを参考に書き換え設定を追加して下さい。具体的な設定例は以下のとおりです。
  • 送信元アドレス: /blog/<*>
    • blog の部分は希望するサブディレクトリ名を指定して下さい
  • ターゲットアドレス: https://example.cloudfront.net/blog/<*>
    • example.cloudfront.net の部分は 1. で作成したCloudFrontのドメインを指定して下さい
    • blog の部分は希望するサブディレクトリ名を指定して下さい
  • リダイレクトのタイプ: rewrite

robots.txt の設定

一例として、https://example.com/blog/ にてサブディレクトリオプションをご利用になる場合、https://example.com/robots.txt に以下の内容を追加していただく必要があります。もし、robots.txtを設置していない場合には、新たにファイルを設置していただく必要があります。

User-agent: *
Disallow: /blog/api/
Disallow: /blog/draft/
Disallow: /blog/preview
Sitemap: https://example.com/blog/sitemap_index.xml

User-agent: Mediapartners-Google
Disallow: /blog/draft/
Disallow: /blog/preview

この robots.txt への変更の目的は、

  • はてなブログが生成するサイトマップを検索エンジンに認識させる
  • 下書き共有機能を使って生成された記事URLやはてなブログのAPIなど、クロールが不要なURLにクロールが行われないように指定する

というものです。指定しない場合も、はてなブログは動作いたしますが、上記の目的のために強く推奨いたします。

robots.txt の挙動について詳しくは、下記のURLをご参照ください。

また、誤った指定を行った場合、正常にクロールが実行されなくなる恐れもあります。公開の前にテスターツールでテストを行うことをおすすめいたします。
support.google.com

リバースプロキシ設定のテスト

本番の切り替え前にリバースプロキシの接続テストを行いたい場合、以下の方法でテストを行うことが出来ます。

  1. 接続テスト用のブログを新規に作成する
  2. サブディレクトリオプション設定アシスタントにて、/blog-test/ 等、テストに利用するディレクトリを指定し、サブディレクトリオプションを有効にする
  3. リバースプロキシの設定を調整し、ブログが閲覧できることを確認する
  4. 接続が確認できたら、サブディレクトリオプション設定アシスタントにて設定を解除する
    • 申し込みのコースによってサブディレクトリオプションを有効にできるブログ数に制限があります
設定アシスタントの画面
設定アシスタントの画面

移行手順例

既存のはてなブログをサブディレクトリ配信に移行する場合やWordPressなどのCMSを利用しセルフホストで運用しているブログをはてなブログに置き換える場合、ブログ自体の準備、リバースプロキシ接続のテストなど、考慮しなければならない点が増えます。以下に詳しい手順例を記載しますので、移行の計画にご利用ください。

WordPressなどのCMSからはてなブログへ移行する

詳細 WordPressなどのCMSからはてなブログへ移行する場合、移行が可能かどうかの調査とコンテンツの調整を行う事前準備と、実際と切り替えの作業に分けて行います。
移行の手順例
元と同じURLになるようにディレクトリ設定を変更する

SEOの観点やユーザービリティの観点から、元のURLは維持することを強く推奨します。

元のURLがhttps://example.com/blog/2023/01/01/000000という形式の場合、はてなブログでは以下のような設定を行ってください。

  • 記事を配信するディレクトリを指定設定にて、空白を指定する
    • 上のリンクから設定を変更する際には、サブディレクトリ配信を希望するブログの管理画面が開かれているか、十分ご確認ください
  • サブディレクトリ設定アシスタントの配信URLに https://example.com/blog/ を指定する

サブドメインで運用中のはてなブログをサブディレクトリ配信へ移行する

詳細 サブドメインで運用中のはてなブログをサブディレクトリ配信へ移行する場合、コンテンツやデザインはそのまま利用することができますが、移行後のURLの検討、リバースプロキシの接続テスト、ダウンタイムに関する検討が必要になります。
移行の手順例
リダイレクト設定

これまで利用していた独自ドメインのURLから、サブディレクトリのURLへリダイレクトを行うことを強く推奨します。これは、SEOの観点やユーザービリティの観点から必要なものです。

subdomain.example.com で提供していたブログを、サブディレクトリオプションを利用し、https://example.com/blog/ に移行すると以下のようにURLが変化いたします。

もし、URLからentryを削除し、以下のようなURLで運営したいという場合には、 https://example.com/blog/2023/01/01/000000 記事を配信するディレクトリを指定設定の「記事のディレクトリ」に空白を指定してください。

リダイレクトの際のステータスコードは、301 を推奨します。301リダイレクトとして実装した場合には、新旧URLではてなブックマークを統合できるためです。はてなブックマークの統合について詳しくは、下記のURLをご参照ください。

コメント一覧ページやブックマークを統合する(エントリー正規化機能) - はてなブックマークヘルプ

なお、サブディレクトリオプションの機能としてリダイレクトの機能は提供していませんので、ご自身でリダイレクトを行うサーバを構築頂く必要があります。

現状、 *.hatenablog.com などはてな提供ドメインにてご利用いただいていたブログをサブディレクトリ配信に移行した場合、自動リダイレクトは行われません。そのため、運用中のはてな提供ドメインのブログのサブディレクトリへの移行は推奨いたしません。将来的に対応予定となっておりますので、対応までお待ち下さい。

ダウンタイムを避ける工夫

サブディレクトリ設定アシスタントにてサブディレクトリへの移行を実行すると、指定したサブディレクトリのURLでのみ閲覧可能になり、これまでのURLでは閲覧ができなくなります。そのため、移行の実行と新URLへのリダイレクトの適用はできる限り近いタイミングで実行すべきです。

また、リバースプロキシの設定に誤りがある場合には、すべてのURLで閲覧ができない状態になり、ダウンタイムが発生します。そのため、リバースプロキシの設定が正しいかどうかを確認するために動作確認用のブログを作成し、動作確認を実行することをおすすめいたします。動作確認完了後は、サブディレクトリ設定の削除を忘れないように実行してください。

その他の注意事項

  • はてなスターは移行することができません

プロキシ設定テストツールの検証項目

プロキシ設定テストツールでは、設定されたプロキシにリクエストを送信し、はてなブログが期待しているリクエストを受け取れるか、期待したレスポンスがプロキシサーバーから返却されるかを確認します。なお、すべてのエラーが解消されている場合でも、プロキシサーバーの設定によっては、はてなブログが正しく動作しない可能性もありますので、最終的には、ご自身で動作をご確認ください。
また、必要に応じてはてなの期待と異なる結果を返すプロキシサーバーの設定を行うことも可能ですが、その場合はてなのサポートの対象外となること、またプロキシ設定テストツールで必ずエラーになることをご理解ください。

具体的な検証項目は以下のとおりです。

  • リクエストメソッドが変換されずにはてなブログのサーバーに到達している: {メソッド名}
    • クライアントから送られるリクエストメソッドが変換されている場合にエラーとして表示されます
  • はてなブログのサーバーが返したHTTPステータスコードが変換されずにクライアントに到達している: {ステータスコード}
    • ステータスコードが変換されている場合にエラーとして表示されます
  • はてなブログのサーバーが返したレスポンスボディがキャッシュされていない
    • はてなブログのリクエスト結果がキャッシュされている場合にエラーとして表示されます
    • キャッシュを行うと、記事を更新しても表示内容が変化しないなどの問題を引き起こす可能性があります
  • {リクエストの種類}リクエストで送信したパラメータが正しくはてなブログのサーバーに到達している
    • クエリパラメータの内容が変換されている場合にエラーとして表示されます
    • はてなブログでは、ページャーの指定などでパラメータを利用します。フィルタや変換などを行わないようにしてください
  • カスタムリクエストヘッダが正しくはてなブログのサーバーに到達している
    • クライアントからのカスタムリクエストヘッダの内容が変換されている場合にエラーとして表示されます
  • はてなブログのサーバーが返したカスタムレスポンスヘッダが正しくクライアントに到達している
    • はてなブログからは複数のカスタムレスポンスヘッダを返却しますが、その内容が変換されている場合にエラーとして表示されます
  • はてなブログのサーバーが返したLocationヘッダが正しくクライアントに到達している
    • はてなから返却されたLocationヘッダが変換されている場合にエラーとして表示されます
  • リクエストしたContent-Typeが正しくはてなブログのサーバーに到達している
    • はてなから渡すリクエストの内容のContent-Typeが変更されている場合にエラーとして表示されます
  • はてなブログのサーバーが返したContent-Typeが正しくクライアントに到達している
    • はてなから返却されたリクエストの内容のContent-Typeが変更されている場合にエラーとして表示されます
  • Cookieが正しくはてなブログのサーバーに到達している
    • Cookieの内容にが変換されている場合にエラーとして表示されます。はてなブログサブディレクトリオプションでは、リクエストの内容をそのままはてなブログに渡すことを想定しています
    • CloudFunctions for Firebase をご利用の場合、システムの都合上必ずエラーになります
    • また、その他の理由で一部のCookieをフィルタしている場合も必ずエラーになります
  • はてなブログのサーバーが返したSet-Cookieヘッダが正しくクライアントに到達している
    • はてなブログのサーバーが返したSet-Cookieヘッダが到達しない、変更されている場合にエラーとして表示されます
  • Hostヘッダが正しく設定されている
    • Hostヘッダが正しく設定されていない場合にエラーとして表示されます
    • HostヘッダはユーザーのリクエストのHostヘッダをそのまま、はてなブログのサーバーに渡すようにしてください
    • ブログを公開するURLが https://example.com/blog/ の場合 example.com を指定する必要があります
  • X-Forwarded-Hostヘッダが正しく設定されている
    • アクセス先ブログの識別に利用するため、 リクエストヘッダ X-Forwarded-Host に、ブログを公開するURLのホスト名を付与する必要があります
    • ブログを公開するURLが https://example.com/blog/ の場合 example.com を指定する必要があります
  • リクエストのパスが正しくはてなブログのサーバーに到達している
    • リクエストのパスが変換されている場合にエラーとして表示されます
  • リクエストのschemeが変換されずに正しくはてなブログのサーバーに到達している
    • リクエストのschemeが変換されている場合にエラーとして表示されます。はてなブログは https: のみを受け付けます
  • はてなブログのサーバー用のドメインを使ってプロキシしている
    • サブディレクトリオプションを利用する場合、はてなブログへのリクエスト先は、通常のブログのURLとは異なるURLが払い出されます
    • 設定アシスタントに表示されているプロキシ先のURL {ブログ固有のID}.hatenablog-oem.com が指定されているか確認してください
  • Cache-Controlヘッダがprivateに設定されてレスポンスが返されている
    • Cache-Controlヘッダがprivate以外に変換されている場合にエラーとして表示されます。レスポンスはプライベートキャッシュにのみ保存されるように指定する必要があります

サブディレクトリオプション設定の解除に関する注意事項

設定を解除する際は以下の点にご注意ください。

  • 設定を解除すると、リバースプロキシ経由でのアクセスができなくなります。ご自身のサーバーのプロキシ設定の変更を行わない場合、従来のURLでコンテンツが閲覧できなくなります。
  • ブログのURLがブログ作成時のURLに戻ります。これまで指定していたサブディレクトリのURLからの自動でのリダイレクトは行われません
  • 記事に含まれるサブディレクトリのURLの置換は行われません。ご自身で差し替えて頂く必要があります
  • はてなブックマークやはてなスターは元のURLに移行されません
  • 設定を解除してもサブディレクトリオプションプランの解約は行われません。必要に応じて別途解約を行ってください

トラブルシューティング

サブディレクトリを利用できる上限に達して、設定ができないとのエラーが表示される
サブディレクトリオプションを利用できるブログ数は、加入しているコースにより上限が設定されます。
上限を超えて設定を行うことができませんので、このエラーが表示されている場合、以下の対処をお願いします。

  • 別のブログにて設定されている不要なサブディレクトリオプション設定を削除する
    • 設定を削除すると、復旧することができなくなります。不要な設定なのか十分ご確認の上、対応をお願いします
  • 利用ブログ数を増やしたコースに変更する
  • はてなに問い合わせる
    • 以下のような場合、お問い合わせ窓口よりご連絡ください
      • エラーの原因が不明な場合など、ご不明な点がある場合
      • 現在提供しているコースはブログ3件が上限のため、3件以上利用したい場合

記事のプレビュー画面やデザインプレビューが表示されません
多くの場合、設定されているプロキシにて X-Frame-Options: DENY が付与されていました。
以下のパスについては、iframeにて表示することが想定されているため、同ヘッダを付与しないようにお願いいたします。

  • /preview
  • /realtime_preview
  • /preview/permalink_design
  • /preview/index_design
  • /preview/theme_store

その他のパスについては、付与していただいても構いませんが、サブディレクトリオプションでは、はてなブログの応答をそのまま閲覧者に返却することを想定しているため、サポートの対象外となることご注意ください。

*1:導入に関する注意事項があります。詳しくは設定例の「Cloud Functions for Firebase」をご参照ください