Search code examples
elixirphoenix-frameworkplug

how to redirect traffic from Http to Https in Phoenix Elixir for SSL on Load Balancer?


I need to forward the traffic from Http to Https, SSL is on the load balancer so all I need to do is forward the header by using the plug_ssl so in my prod.exs I added:

config :web, Web.Endpoint,
  force_ssl: [rewrite_on: [:x_forwarded_proto]]

in my prod.exs and remove everything else on config :web, Web.Endpoint

It doesn't work.

What am I doing wrong?

Do I need to put the force_ssl in my router?

Thank you in advance.


Solution

  • You will probably need to enable the force_ssl plug only for your endpoints that are not used for health check or something related to that.

    I had a similar problem with the k8s Ingress on GKE and the solution was to put the force_ssl on router only for my application routes, and let /healthz (which was configured as my health check route) using HTTP.

    An example of config/prod.exs:

    # Tells if we need to enforce SSL for our endpoints.
    # Only production/staging should enforce
    config :my_app, force_ssl: true
    
    config :my_app, MyAppWeb.Endpoint,
      load_from_system_env: true,
      url: [host: "${APP_HOST}", port: 80],
      server: true,
      http: [port:  "${PORT}"],
      url: [scheme: "https", host: "${APP_HOST}", port: 443],
      secret_key_base: "${SECRET_KEY_BASE}"
    

    And here is an example of lib/my_app_web/router.ex:

    defmodule MyAppWeb.Router do
      use MyAppWeb, :router
    
      # This route will NOT enforce SSL
      get("/healthz", MyAppWeb.HealthCheckController, :show)
    
      pipeline :api do
        plug(:accepts, ["json"])
    
        if Application.get_env(:my_app, :force_ssl) do
          plug(Plug.SSL, rewrite_on: [:x_forwarded_proto], host: nil)
        end
      end
    
      scope "/", MyAppWeb do
        pipe_through(:api)
    
        # My routes will go here, and will be enforced if the
        # application flag `force_ssl` is enabled.
      end
    end
    

    This is a little bit tricky to debug. If you are using kubernetes, try to use the kubectl describe ingress YOUR-INGRESS-HERE, and always check the headers for your requests and responses while doing the tests.