読者です 読者をやめる 読者になる 読者になる

タオルケット体操

サツバツいんたーねっと

Nginxでのドメインやhttpsへのリダイレクトの設定はrewriteよりもreturnを使おう

httpからのアクセスをhttpsへリダイレクトしたいなーと思って調べていたら、「NginxHttpRewriteModuleを使ってrewriteしよう!」みたいな記事が大量ヒットしたんですが、なんとも設定が冗長で微妙な感じがしたので調べたところちゃんと公式に記述がありました。

Converting rewrite rules なお日本語のドキュメントはちょっと古いっぽいので英語版を読んだ方がよさげです。

上記には、rewriteによるリダイレクトは"This is a wrong, cumbersome, and ineffective way." と書かれています。

server {
    listen 80;
    server_name  www.example.org  example.org;
    if ($http_host = example.org) {
        rewrite  (.*)  http://www.example.org$1;
    }
    ...
}

よりも、サーバ節を分離して

server {
    listen 80;
    server_name  example.org;
    return 301 http://www.example.org$request_uri;
}

server {
    listen 80;
    server_name  www.example.org;
    ...
}

とした方が望ましいということですね。
前者がif節を使っていることもそうですが、

  • サーバ節を分離しないことで、全ての処理がifやrewriteを通過する必要がある
  • 正規表現やオプションの指定が出来るrewriteの方が(恐らく)処理が重たいこと
  • 何よりもドメインやプロトコルの単純な置き換え程度であればreturnの方が明示的でクリーンな記述が出来る

というような点からもreturnが推奨されるようです。

Pitfalls - Nginx Community のServer Nameにも記載がありますね。

また、最初のrewriteの例にはpermanentフラグがありません。こういうケースのリダイレクトでは301(Moved Permanently)を返すのが良いはずですね。

なのでhttpsへのリダイレクト処理も

server {
    listen 80;
    server_name hogeracho.com;
    return 301 https://www.hogeracho.com$request_uri;
}

server {
    listen 443 ssl;
    ......
}

と分離して書くことにしました。そんなに負荷がかかるようなアプリを作ったわけではないのですが、スッキリ

なお0.9.1より前のバージョンではrewriteを使うしかないようです。

StackOverflowのサーバ版? にもreturnに対する言及がありました。
How to force or redirect to SSL in nginx? - Server Fault

しかしサーバの設定やらなんやらなインフラはどうしても苦手意識がぬぐえないですね。基本的なことは出来るようになりたいですが。
例によって突っ込み歓迎的日記。

以上!