👋

さよなら http://localhost、よろしく https://localhost

に公開

現在、株式会社TAIANで婚礼業界向けSaaSの開発に携わっています。プッシュ通知と名刺スキャン機能の検証にあたり、localhost でも HTTPS が必要になりました。

本記事では、その背景と、ローカル・CI 環境で HTTPS を構築する方法を整理します。

なぜ Localhost HTTPS が必要なのか?

1. モダン Web API の要求

現代の Web 開発では、ローカル開発環境で HTTPS を使うことが当たり前になりつつあります。
多くの最新 Web API やブラウザの機能は Secure Context(安全なコンテキスト) を必要とします。

  • Service Worker:PWA 機能のコア
  • Web Push API:プッシュ通知
  • Geolocation API:位置情報
  • Camera / Microphone API:カメラとマイク
  • Web Authentication API:WebAuthn などの認証 API

これらは HTTPS でなければ動作しません。

2. サードパーティサービス統合

多くの外部サービスが HTTPS のコールバック URL を要求します:

  • OAuth 2.0 のリダイレクト URL は HTTPS が必須
  • Stripe、PayPal などの webhook が HTTPS を要求
  • Google Maps、Mapbox など一部の機能で HTTPS が必要

ローカルでも HTTPS があると実際の運用と同じ挙動を検証できます。

3. 本番環境との一貫性

ローカルで HTTPS を使うことで:

  • 混合コンテンツ(Mixed Content)の警告を事前に検出
  • Cookie の Secure 属性や HSTS のテスト
  • SSL 設定の検証

など、本番で起こりうる HTTPS 関連の問題を早期発見できるようになります。

4. ブラウザのセキュリティポリシー

最新のブラウザは HTTP に対して制限を強めています:

  • HTTP ページでは一部の API が制限される
  • HTTPS ページ中の HTTP リソースはブロックされる
  • 自動入力やその他機能が制限されることもある

そのため、HTTPS が前提の環境での開発が望まれます。

Localhost HTTPS の設定方法

利用可能な方法

ローカルで HTTPS を有効にするための一般的な手法:

  1. mkcert + nginx(推奨):ローカル CA で証明書を生成し、nginx をリバースプロキシとして利用
  2. 自署名証明書:簡単だが手動で信頼設定が必要
  3. Cloudflare Tunnel:外部アクセスが必要なケースに有用

ここでは mkcert + nginx の方法をメインで解説します。

手順

1. mkcert をインストールする

macOS

brew install mkcert

Linux(Ubuntu / Debian)

sudo apt install libnss3-tools
wget https://github.com/FiloSottile/mkcert/releases/latest/download/mkcert-v1.4.4-linux-amd64
chmod +x mkcert-v1.4.4-linux-amd64
sudo mv mkcert-v1.4.4-linux-amd64 /usr/local/bin/mkcert

これで mkcert を使えるようになります。

2. SSL 証明書を生成する

自動スクリプトを使う:

bash script/local_setup_https.sh

スクリプトは以下を実行します:

  1. mkcert のインストール確認
  2. ローカル CA をシステムに信頼済みとして登録
  3. 通配符証明書(*.lvh.me など)を生成
  4. 証明書を ~/.ssl/ に保存

手動で生成する場合:

mkcert -install
cd ~/.ssl
mkcert -key-file _wildcard.lvh.me+3-key.pem \
       -cert-file _wildcard.lvh.me+3.pem \
       "*.lvh.me" "lvh.me" localhost 127.0.0.1 ::1

これでローカル HTTPS を扱うための証明書が用意できます。

3. nginx リバースプロキシを設定する

containers/nginx/nginx.conf を以下のように追加します:

upstream rails_app {
  server unix:/app/tmp/sockets/puma.sock;
}

server {
  listen 3001 ssl;
  ssl_certificate /etc/ssl/certs/_wildcard.lvh.me+3.pem;
  ssl_certificate_key /etc/ssl/private/_wildcard.lvh.me+3-key.pem;
  server_name admin.lvh.me;

  location / {
    proxy_pass http://rails_app;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

基本的に nginx が HTTPS ターミネーションを行い、バックエンド(Rails など)と通信します。

4. Docker Compose に nginx を追加する

docker-compose.yml:

services:
  proxy:
    build: containers/nginx
    ports:
      - 3001:3001
    volumes:
      - app-tmp:/app/tmp
      - ~/.ssl:/etc/ssl/certs:ro
      - ~/.ssl:/etc/ssl/private:ro
    depends_on:
      - app

  app:
    volumes:
      - app-tmp:/app/tmp

nginx コンテナを立ち上げることで HTTPS を経由したアクセスが可能になります。

5. アプリサーバ設定(例: Puma)

Rails アプリの場合:

# config/puma.rb
if Rails.env.development? || Rails.env.test?
  bind "unix://#{Rails.root}/tmp/sockets/puma.sock"
else
  bind "tcp://0.0.0.0:#{ENV.fetch('PORT', 3000)}"
end

Puma を UNIX ソケットで起動し nginx からプロキシする形にします。

6. hosts ファイルを設定する

以下を /etc/hosts に追加:

127.0.0.1 lvh.me
127.0.0.1 admin.lvh.me
127.0.0.1 tenantA.lvh.me

実際の HTTPS ドメイン名として lvh.me 系を利用できます。

7. サービスを起動する

docker compose build proxy
docker compose up

ブラウザで以下の URL を HTTPS で開けます:

  • https://admin.lvh.me:3001/admin
  • https://tenantA.lvh.me:3001/crm

CI 環境での HTTPS

CI で HTTPS を使う方法も複数あります:

方法 1:自署名証明書を使う(E2E テスト向け)

GitHub Actions などでは自署名証明書を生成:

mkdir -p ~/.ssl
openssl req -x509 -newkey rsa:4096 \
  -keyout ~/.ssl/key.pem \
  -out ~/.ssl/cert.pem \
  -days 365 -nodes \
  -subj "/CN=*.lvh.me"

ブラウザのテストコードで証明書を信頼させる設定が必要になります。

方法 2:CI 上で mkcert を使う(推奨)

CI 上でも mkcert をインストールして証明書を生成できます:

wget https://github.com/FiloSottile/mkcert/releases/latest/download/mkcert-v1.4.4-linux-amd64
chmod +x mkcert-v1.4.4-linux-amd64
sudo mv mkcert-v1.4.4-linux-amd64 /usr/local/bin/mkcert
mkcert -install

mkdir -p ~/.ssl
cd ~/.ssl
mkcert -key-file _wildcard.lvh.me+3-key.pem \
       -cert-file _wildcard.lvh.me+3.pem \
       "*.lvh.me" "lvh.me" localhost

CI でもローカル HTTPS が動作できます。

方法 3:リアルなドメイン + 証明書(PR Preview 用)

PR Preview や外部アクセスが必要な場合、Let’s Encrypt の証明書や fly.io などを使って外部 HTTPS を構築します。

よくある問題と対処

1. 証明書が信頼されない

  • mkcert -install を実行したか確認
  • 証明書ファイルのパスが正しいか確認
  • ブラウザを再起動して信頼状態を更新

2. nginx が証明書を読み込めない

  • ~/.ssl/ に正しい証明書ファイルがあるか確認
  • docker-compose.yml のボリュームマウント設定をチェック
  • nginx が読み取り可能な権限か確認

3. WebSocket 接続がうまく行かない

Nginx の WebSocket 設定が必要:

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

などを追加します。

4. ポート衝突

3001 ポートが別プロセスで使われている場合:

  • ポート番号を変更する
  • 他のサービスを停止する

などで解決します。

まとめ

ローカルで HTTPS を使うことは、最新 Web API、外部サービス統合、本番環境との一致性、ブラウザのセキュリティ要件などの理由から推奨されます。mkcert + nginx の方法は簡単かつ実用的であり、開発効率と品質向上に役立ちます。

TAIAN Tech Blog

Discussion