Phoenix LiveView constantly refreshes with custom domain

I’ve added a custom domain to my app (https://www.rafo.com.au) by following the guide SSL for Custom Domains.

However it appears that if you visit my site via the custom domain the site constantly refreshes every couple of seconds. If you visit via the fly.io provided domain (https://rafo.fly.dev) it does not do this.

Any ideas what I could’ve done wrong?

This is an excerpt from the logs in my fly dashboard. Including them here in case it helps someone else find the solution in future :slight_smile:

[error] Could not check origin for Phoenix.Socket transport.
[info] Origin of the request: https://www.rafo.com.au
[info] This happens when you are attempting a socket connection to
[info] a different host than the one configured in your config/
[info] files. For example, in development the host is configured
[info] to "localhost" but you may be trying to access it from
[info] "127.0.0.1". To fix this issue, you may either:
[info] 1. update [url: [host: ...]] to your actual host in the
[info] config file for your current environment (recommended)
[info] 2. pass the :check_origin option when configuring your
[info] endpoint or when configuring the transport in your
[info] UserSocket module, explicitly outlining which origins
[info] are allowed:
[info] check_origin: ["https://example.com",
[info] "//another.com:888", "//other.com"]

This was an easy fix in the end (thankfully).

I had forgotten to update my Elixir apps config when I swapped to my custom domain. I.e. runtime.exs needed to be updated to reflect my custom domain as the host.

If you follow Build, Deploy and Run an Elixir Application you’ll have something like below in your config/runtime.exs

  config :rafo, RafoWeb.Endpoint,
    url: [host: "#{app_name}.fly.dev", port: 80],
    http: [
      ip: {0, 0, 0, 0, 0, 0, 0, 0},
      port: String.to_integer(System.get_env("PORT") || "4000")
    ],
    secret_key_base: secret_key_base

This needed updates to become:

  config :rafo, RafoWeb.Endpoint,
    url: [host: "rafo.com.au", port: 443], # host + port change
    http: [
      ip: {0, 0, 0, 0, 0, 0, 0, 0},
      port: String.to_integer(System.get_env("PORT") || "4000")
    ],
    secret_key_base: secret_key_base

To expand on this, Phoenix enforces same origin for websockets by default, (check_origin: true endpoint config). By default, we will enforce the same origin as configured in your :url, but you can also provide a list of hosts if you have other needs. For example:

config :my_app, MyAppWeb.Endpoint,
  check_origin: ["//example.com", "//another.com"]

For applications generated with phx.new >= 1.6.3, the config/runtime.exs will use a PHX_HOST environment export if available to set the endpoint url host, and fly.toml which is set to myapp.fly.dev when you run fly launch, and can be customized as you add your custom domains. Glad you got things sorted and hope that helps!

1 Like

Thanks Chris! I’m currently trying to get the www. subdomain working + a preview environment. Would below be a valid config/runtime.exs?

  app_name =
    System.get_env("FLY_APP_NAME") ||
      raise "FLY_APP_NAME not available"

  app_url = "https://#{app_name}.fly.dev:443"

  config :rafo, RafoWeb.Endpoint,
    check_origin: [
      "https://rafo.com.au:443",
      "https://www.rafo.com.au:443",
      app_url
    ],
    http: [
      ip: {0, 0, 0, 0, 0, 0, 0, 0},
      port: String.to_integer(System.get_env("PORT") || "4000")
    ],
    secret_key_base: secret_key_base

EDIT: Above works :slight_smile:

1 Like

Phoenix 1.6.6 will have a setting that should make this easier. It’s in master now, if you are feeling frisky: check_origin: :conn.

This allows any origin matching the current request’s host, port, and scheme. So you can point arbitrary hostnames at your app and it does what you’d expect.

Is there a drawback to check_origin: :conn?

There isn’t! Hopefully it’ll be the default in Phoenix down the road. You will need to configure your app to use the proxy headers we set:

plug Plug.SSL, rewrite_on: [:x_forwarded_host, :x_forwarded_port, :x_forwarded_proto]

Phoenix 1.6.6 is out now!

1 Like

Thanks! I assume that goes in AppWeb.Endpoint, does it need to be somewhere specific in the ordering of plugs?

We plug Plug.SSL for you if you are using force_ssl configuration for your endpoint, so you could do this in your prod endpoint config:

config MyAppWeb.Endpoint,
  ...,
  force_ssl: [rewrite_on: [:x_forwarded_host, :x_forwarded_port, :x_forwarded_proto]],
3 Likes

Awesome :smiley:

The code below is working in Phoenix 1.6.6, thanks Chris and Kurt!

FYI to anyone that finds this later - the force_ssl option is a compile time config item, so can’t go in our runtime config.

config/prod.exs

config :rafo, RafoWeb.Endpoint,
  ...
  force_ssl: [rewrite_on: [:x_forwarded_host, :x_forwarded_port, :x_forwarded_proto]]

config/runtime.exs

  config :rafo, RafoWeb.Endpoint,
    check_origin: :conn,
    ...
10 Likes

@stibbs can you mark your last message as a solution so people next time will see it at the top highlighted?