Generate the proper uls when Phoenix is behind reverse proxy and https is handled by nginx

My application in production is behind a reverse proxy, nginx, and https is handled by nginx too. Meaning, a Phoenix applications runs as http and on a non-standard port.

For the emails, for instance, I need the full urls. At the moment calling Routes.something_url(...) will result in the urls such as http://blahblahblahblah.com:8080/abc

I’ve checked out Phoenix.Endpoint — Phoenix v1.7.7, but haven’t been able to find what precisely I’d fix in my application.

How to get rid of the port number and replace the scheme with https, and properly so?

From the endpoint config:

:url - configuration for generating URLs throughout the app.

You will need to configure this with the appropriate values. An example from an application of mine:

port = get_env("PORT", 5000, :int)
host = get_env("HOST", "localhost")
host_port = get_env("HOST_PORT", 5000, :int)
url_scheme = if host_port == 443, do: "https", else: "http"

# Configures the endpoint
config :code_stats, CodeStatsWeb.Endpoint,
  http: [port: port],
  url: [
    host: host,
    port: host_port,
    scheme: url_scheme
  ],

(get_env here is my own function, but you get the idea.)

3 Likes
  1. url_scheme will always be http because host_port will never be 443.

  2. I already have config :my_app, MyApp.Endpoint, set up like in your response.

Where did you get that from? Have you tried it youself?

This is from my production code, so yes, I’d say that I have tried it.

The host_port value is the port visible to the outside world (the one that your reverse proxy serves). I set it to 443 when I run the app (in my Systemd file where I control the environment). The port value should be the internal port that Phoenix binds to. You can see that you need to tell Phoenix both of these values.

Then why do you pass host_port via an env. variable? In the prod. It’ll always have to be 443

This same config is also used in development, where it can be different.