Proper way to enforce https only?

I’m currently in the process of deploying ibgib, and I just finished configuring my DNS :eyes: :checkered_flag:.

Now I’m trying to set up https redirection so that (http://)www.ibgib.com will automatically redirect to https://www.ibgib.com. What is the “proper” way to implement this?

I know of the force_ssl option in the endpoint configuration, which I’ve tried turning on (with hsts: true), however this does not seem to do the redirect. But this could be that I do not have my docker setup properly configured. Is setting this supposed to do the redirect? Or am I supposed to accomplish this another way, perhaps with nginx? And if nginx is the way to go, could I then completely remove the http config setting from my endpoint config? :thinking:

Additional Background

I’m currently using distillery to produce a release and then docker (engine, compose, machine) with a “simple” setup of my release container + a postgres container deployed to aws ec2. My full-ish (foolish? :confused:) ongoing deployment notes can be found in my deploy issue for anyone else looking to go elixir + docker + aws.

3 Likes

FWIW, in my experience Plug.SSL, which is what Phoenix uses behind the scenes for force_ssl: [hsts: true], works fine.

4 Likes

Thanks @josevalim. I think that may be the sanity check that I’m looking for, as reading the docs it seems obvious what it should do…but I’m just not seeing it happening! :see_no_evil:

It is probably a docker configuration issue that I just haven’t been able to pin down yet. :pushpin:

2 Likes

Well, I couldn’t get the force_ssl to work as expected. :slight_frown: I would hazard a guess that it may be because of the rewrite not working with the docker-machine vm and/or aws configuration. :grey_question:

I was however able to get it (mostly) working with a very basic, customized https + www redirect nginx container. I forked this from an https-only redirect container, and customized it for also forcing www as well. :smile: :cookie:

I say “mostly” because both ibgib.com and www.ibgib.com redirect as expected to https://www.ibgib.com. Also if you type in https://www.ibgib.com directly it will work as well (*). However, if you type in https://ibgib.com, explicitly stating the https and giving a naked URL, it doesn’t properly redirect to the www version, but at this point I’m fine with that, as I’ll have to reconfigure this stuff anyway in a later release. :sweat_smile:

I just wanted to post my results for anyone else going the distillery + docker (engine, compose, machine) route.

Thanks again! :smile:

(*) This may seem like a given to devops/deployment gurus, but I found plenty of (mis)configurations where this doesn’t work :wink:.

2 Likes

It’s not working for me either. I’ve tried both what was in the phoenix guides and force_ssl: [hsts: true] and read the docs for Plug.SSL without seeing any clear reason it’s not working.

If I type in https://myapp.com/foo, it loads with https. If I type http://myapp.com/foo, it loads without. What I want is for the https route to load, even if the user doesn’t type https into the location bar of their browser.

I’m not using a proxy. It’s just a normal install of phoenix.

Here’s my prod.exs config:

config :myapp, Myapp.Endpoint,
  server: true,
  url: [scheme: "https", host: "myapp.com", port: 443],
  http: [compress: true, port: 80],
  https: [compress: true, port: 443,
  force_ssl: [hsts: true],
    otp_app: :myapp,
    keyfile: "/etc/letsencrypt/live/myapp.com/privkey.pem",
    certfile: "/etc/letsencrypt/live/myapp.com/cert.pem"],
  cache_static_manifest: "priv/static/manifest.json"
3 Likes

I’m offloading the SSL termination to HAProxy, you can do the redirect easy in haproxy.cfg:

frontend http-in-website
  bind 0.0.0.0:80
  redirect scheme https code 301 if !{ ssl_fc }

frontend https-in-website
  bind 0.0.0.0:443 ssl crt /etc/haproxy/ssl
  default_backend servers-website

backend servers-website
  server w1 127.0.0.1:4200 check maxconn 4000

Your server just listen on 127.0.0.1:4200, no need to care about the force_ssl.

You still need the http config, check http://www.phoenixframework.org/docs/serving-your-application-behind-a-proxy.

3 Likes

Yes, FWIW this is what I ended up doing as well with ibGib using nginx. I ended up terminating the SSL at the proxy, redirect 301, etc.

2 Likes

Did anyone ever find a solution for this, I am still seeing the same problem on docker, AWS, distillery.

I am currently using force_ssl: [rewrite_on: [:x_forwarded_proto]] for my application running on AWS (ECS specifically) and it is working fine.

2 Likes

force_ssl: [hsts: true, host: nil]

Solved it for me.

3 Likes

Thanks @pshoukry! It solved the problem for me (EC2, no proxy, just iptables routing).

1 Like

@Nagasaki45 most welcome! Great to hear it worked

thank you.

2 Likes

@pshoukry - thank you, your solution worked too (after much googling).

1 Like

Great thread! Anybody have a good resource for their iptables config?

I am on heroku with Phoenix app. and this didnt work for me. any solution?

config :edge_commander, EdgeCommanderWeb.Endpoint,
force_ssl: [hsts: true, host: nil]

try

force_ssl: [rewrite_on: [:x_forwarded_proto], hsts: true, host: nil],

1 Like

It didnt work… :slight_smile: results are the same, nothing get force. both app. and https://app. working, any other clues?

“it works for me”

can you check with curl

eg

curl -s -D- http://myapp.herokuapp.com
should output a 301 to the https

and

curl -s -D- https://myapp.herokuapp.com | grep -i Strict

should output
Strict-Transport-Security: max-age=31536000

1 Like

Thanks it worked. :slight_smile:

1 Like