Phoenix Endpoint url force ssl behind proxy

When not using ssl directly in the phoenix app, but behind a Nginx proxy, how to configure

config :app, AppWeb.Endpoint, url: [host: deployment_domain, port: 443]

correctly, so that the generated urls include https? With the above config it generates http://domain:443

Thank you

Quote from docs:

  • :url - configuration for generating URLs throughout the app. Accepts the :host , :scheme , :path and :port options.

So you need to use:

config :app, AppWeb.Endpoint, url: [scheme: :https, host: deployment_domain]

Instead (you do not need to set port, as it is default value for HTTPS requests).

3 Likes

Not sure if this has changed since then, but I recall once when [scheme: :https] did not work for me, and instead required [scheme: "https"]

EDIT: docs say

The :scheme option accepts “http” and “https” values.

2 Likes

And you want to specify port: 443 as well. It does not change the default (80) port with the scheme: "https". I got burnt once.

2 Likes

So to summarise it is

config :app, AppWeb.Endpoint, url: [scheme: “https”, host: deployment_domain, port: 443]

Thanks @hauleth @APB9785 @derek-zhou

1 Like

Don’t forget to also add Plug.RewriteOn, :x_forwarded_proto to your Endpoint, so Plug.Session knows the request arrived over HTTPS. Otherwise your session cookies will not be marked as ‘secure’ and they might leak over plain HTTP. That also requires that Nginx sends the X-Forwarded-Proto header, of course.

Could you show here an example, where/how to configure this in prod.exs?

This is not configuration, you need to add it to your endpoint.ex, typically somewhere in the middle near plug Plug.RequestId but definitely before plug Plug.Session

1 Like

You can also do it in config - see Using SSL — Phoenix v1.5.9. Recently introduced perhaps?

Relatedly you can also enable HSTS there.

1 Like

Actually, the force_ssl Endpoint configuration is older. It dynamically injects Plug.SSL into the endpoint depending on configuration, in particular to allow it to be present/absent depending on the environment. Plug.RewriteOn was extracted from Plug.SSL recently (which now defers to it when the rewrite_on option is present).

I started advocating the use of Plug.RewriteOn when terminating TLS externally, since it seems more intuitive. I’m sure many people skip over the force_ssl config docs because they think they don’t need it when TLS is not handled by Phoenix. Which is unfortunate: I’m sure there are quite a few installations out there that have insecure session cookies as a result…

IIRC it is actually enabled by default when you use force_ssl, though it can be disabled.

1 Like

Thanks for the clarification @voltone , that’s good to know.

I came across the config option in the docs when figuring out how to deploy my first (toy) Phoenix app to fly.io. For a Phoenix beginner focussing mainly on getting code working, how the docs presents this kind of thing looms pretty large!

1 Like

Just to confirm: :hsts - a boolean on enabling HSTS or not, defaults to true (from Plug.SSL — Plug v1.11.1)

1 Like