Configuring HTTPS on Plug.Https

Hello !! :smiley:

I’m trying to configure https in my project but I had some issues.

The first one is with mix, I’ve tried to set up my https config by env and for that I had uncommented that import from config/config.exs

import_config "#{Mix.env}.exs"

And I added this config to my config/dev.exs:

config :momsfood,
   port: 443,
   password: "pass",
   otp_app: :momsfood,
   keyfile: "priv/ssl/key.pem",
   certfile: "priv/ssl/cert.pem"

but when I run iex -S mix it throws this error:

** (Mix.Config.LoadError) could not load config config/dev.exs
    ** (CompileError) config/dev.exs:1: undefined function config/2
    (elixir) lib/code.ex:168: Code.eval_string/3
    (mix) lib/mix/config.ex:161: Mix.Config.read!/1
    (mix) lib/mix/config.ex:195: anonymous fn/2 in Mix.Config.read_wildcard!/1
    (elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6

Adding use Mix.Config to the top of my config/dev.exs file makes this error to go away, but I don’t know if doing this is the properly way.

Then I created a file called https_worker.exs inside my lib folder:

defmodule Momsfood.HttpsWorker do
  def start_link do
    Plug.Adapters.Cowboy.https Momsfood.Router, [],
     port: Application.get_env(:momsfood, :port),
     password: Application.get_env(:momsfood, :password),
     otp_app: Application.get_env(:momsfood, :otp_app),
     keyfile: Application.get_env(:momsfood, :keyfile),
     certfile: Application.get_env(:momsfood, :certfile)
  end
end

In this file I’m setting up the config to be used with Plug and then I’m calling it from start method:

   def start(_type, _args) do
   import Supervisor.Spec, warn: false

   children = [
        # Define workers and child supervisors to be supervised
        # worker(Momsfood.Worker, [arg1, arg2, arg3]),
       worker(Momsfood.HttpsWorker, []),
       worker(Momsfood.Repo, [])
   ]

But it’s throwing this error:

** (Mix) Could not start application momsfood: Momsfood.start(:normal, []) returned an error: shutdown: failed to start child: Momsfood.HttpsWorker
    ** (EXIT) {{:shutdown, {:failed_to_start_child, :ranch_acceptors_sup, {:listen_error, Momsfood.Router.HTTPS, :eacces}}}, {:child, :undefined, {:ranch_listener_sup, Momsfood.Router.HTTPS}, {:ranch_listener_sup, :start_link, [Momsfood.Router.HTTPS, 100, :ranch_ssl, [password: 'pass', certfile: '/Users/nantoaqui/code/momsfood/_build/dev/lib/momsfood/priv/ssl/cert.pem', keyfile: '/Users/nantoaqui/code/momsfood/_build/dev/lib/momsfood/priv/ssl/key.pem', max_connections: 16384, port: 443], :cowboy_protocol, [env: [dispatch: [{:_, [], [{:_, [], Plug.Adapters.Cowboy.Handler, {Momsfood.Router, []}}]}]]]]}, :permanent, :infinity, :supervisor, [:ranch_listener_sup]}}

Am I missing something here?

Thanks!!!

You are trying to bind to a privileged port (443), but you are not root. Try changing the port number to 8443 for now, for testing.

In deployment, when you actually want to serve HTTPS on port 443, you could consider defining an iptables forwarding rule to map port 443 to 8443. There are other options, just please don’t run your app as root :slight_smile:

BTW, use Mix.Config in your dev.exs file is exactly right.

3 Likes

Voltone thank you so much for your explanation, it’s working!!