Load balancer redirect 80 to 443

I am wondering if it is possible to configure the load balancer to send a redirect from port 80 to port 443.

A solution I would use is to use a simple service that has the only role to redirect everything arrives to 80 port. I map the 80 port f the load balancer to that service, and it should be done.

However, the optimal solution would be adding the configuration to HAProxy, something like:

redirect scheme https if !{ ssl_fc }

What do you suggest?

A container that does redirects seems like a good idea for now. Doing it in haproxy would likely be another use case for #1871 unless we think this is a common enough feature to make it a specific API config option.

Thanks Vincent. I will update the issue you linked with my use case.

I think the main problem is, how do we access the cluster from the Internet? Do we place a Proxy in front of it, or we use Rancher’s load balancer? As for the current state I see problems for both scenarios.

If we expose Rancher’s load balancers externally I see these problems:

  • cannot configure redirects (such as 80 to 443)
  • cannot configure ssl certificates with the CLI (I could not set them through rancher-compose, only through UI, ticking the ssl box)

If I add a proxy in front of the cluster to handle the redirects and forward of requests, pointing to the load balancer I see the following problems:

  • I cannot automatically detect the host the Racnher’s load balancers is, and trigger config updates on host changes. I could add something like consul to fix this, but it looks overkill due to the fact I would just use Rancher to orchestrate my infrastructure.

Therefore my questions are?

  1. do you guys plan to make Rancher’s load balancer suitable to work as an external proxy?
  2. do you plan to include a distributed configuration (such as consul or etcd) so that changes in the cluster can be detected and actions can be triggered?

Managing SSL certificates on balancer so through compose is in the next release.

I’m not sure why you’re talking about proxying, if you just want all http requests to be 302ed to https you just need an almost 1-liner nginx or Apache image that serves redirects. Then point port 80 in the balancer to a service running that image, and 443 to your actual app service. Here’s an (old) example: https://github.com/jamessharp/docker-nginx-https-redirect

It is possible to get info about where the containers of a service are running from metadata though.

Just tried this and ran into an issue.

Before I spun up an instance of geldim/https-redirect:latest outside of my load balancer and told it to run on every host. This worked, though it was a bit hacky and opens 80 unnecessarily in some places.

Today I tried adding it into a load balancer with both 80 and 443 open (443 was only open previously.) I have a rule with no hostname set, port 80 open, redirecting to geldim/https-redirect:latest port 80. Every other rule has a hostname and port 443 set as the source.

If I hit, say, http://ci.thewordnerd.info, sometimes it shows the HTTP redirect, sometimes I get a 503. They’re hosted behind Cloudflare but I see this even when hitting the VM directly and setting the Host: header manually. All hosts seem to work if I hit them via https.

How can I provide additional information to help resolve this? Would you like my rancher-compose definition just as a reference, even though compose can’t spin up load balancers yet? Or should I get the haproxy.cfg from the balancer instance? Let me know.

Could you provide your docker-compose.yml file for your stack as well as the HA proxy config?

Docker-compose.yml can be found in the stack view and clicking on the paper icon.

HA proxy config for your load balancer can be found by following the steps in our troubleshooting documentation. http://docs.rancher.com/rancher/faqs/troubleshooting/

I’ve pasted the content here to make it easier:
If you want to see the configuration of the load balancer, you will need to exec into the specific LB Agent container and look for the configuration file. You can use the UI and select Execute Shell on the container.

$ cat /etc/haproxy/haproxy.cfg

This file will provide all the configuration details of the load balancer.

Now that this github issue has been resolved and custom parameters are possible, how do you do this?

I tried putting

redirect scheme https if !{ ssl_fc }

in both global and default sections, and it breaks the load balancer

redirect is not something that can go in global/defaults… https://cbonte.github.io/haproxy-dconv/configuration-1.6.html#4-redirect

Doing this in haproxy will require rancher/rancher#2179.

You can still make a container that returns redirects and then point the balancer port 80 to that contaienr.

I used https://github.com/jamessharp/docker-nginx-https-redirect as a workaround.

nginx-https-redirect listens on port 80 only and the load balancer listening on 443 only. The redirect container will catch all http traffic and redirect to https traffic which will be picked up by load balancer.

1 Like

Hi Yunspace,

Can you please suggest using this GitHub - jamessharp/docker-nginx-https-redirect: A simple nginx container that redirects all http requests to https. Please find the attached configuration and suggest.

Iam able to access the sites using both http and https at the moment, but i need to redirect urls from http to https. Please suggest.

Your LB should only listen to port 443. And you create another service using the docker-nginx-https-redirect that listens to port 80. The docker compose would look something like this:

https-redirect:
  ports:
  - 80:80/tcp
  labels:
    io.rancher.scheduler.global: 'true'
    io.rancher.container.pull_image: always
    io.rancher.service.hash:
  tty: true
  image: jamessharp/docker-nginx-https-redirect:latest
  stdin_open: true
ssl-load-balancer: ( this is your LB )
  ports:
  - 443:443
  external_links:
  labels: blah blah blah
  tty: true
  image: rancher/load-balancer-service
  stdin_open: true
1 Like

Thanks for the update yunspace. Iam able to redirect now with other container. all set now.

Hey Mahesh_K could you please mention what you ended up doing?

@gavargas there is a docker-compose snippet above dated Mar 2016, which indicates exactly what needs to be done.

Also something I just realised from https://github.com/rancher/rancher/issues/3505 is that since Rancher 1.2 you can simply add the following global config to your HAProxy:

frontend http-frontend
    bind *:80
    mode http
    redirect scheme https code 301 if !{ ssl_fc }

This is also mentioned here Trouble setting up http-to-https redirection

I’ve tested this out and it works. I didn’t need to do any special selector rules.

Thanks for your help @yunspace I got it working!

My full setup

docker-compose:

haproxy:
  ports:
  - 8080:8080
  - 8443:8443
  external_links:
  labels:
  tty: true
  image: rancher/load-balancer-service
  stdin_open: true

rancher-compose:

haproxy:
  load_balancer_config:
    haproxy_config:
      defaults: |-
        frontend http-frontend
                bind *:8080
                mode http
                redirect scheme https code 301 if !{ ssl_fc }

        timeout connect 5000
                timeout client 60000
                timeout server 60000
      global: ''

And my AWS ELB has two listeners

  • 80 --> 8080
  • 443 --> 8443
2 Likes

Reading the same question here, one of the responses states that:

https://github.com/rancher/rancher/issues/3505

the LB-frontend is named ‘frontend 80’ not ‘frontend http-frontend’ in the latest Rancher-LB release

Just a heads up, I can verify that it works after trying it out myself.

This is the line that should be added:

# Custom haproxy.cfg
frontend 80
redirect scheme https code 301 if !{ ssl_fc }
2 Likes

adding

timeout client 4m
timeout server 4m

frontend http-frontend
   bind *:80
   mode http
   redirect scheme https code 301 if !{ ssl_fc } . 

to my custom HAproxy.cfg i either get a 503 if i have a other http:80 service rule active (pseudo) or connection denied if i have no other http/80 service role ( only https/443)

Any hints?

This works if you want to redirect all traffic to HTTPS:

# Custom haproxy.cfg
frontend 80
redirect scheme https code 301 if !{ ssl_fc }

If you have multiple sites, some with ssl and other with regular http this has worked for me:

frontend 80
#redirect scheme https code 301 if !{ ssl_fc } (I kept this just for reference purposes)
redirect scheme https if { hdr(Host) -i [your.domain.com] } !{ ssl_fc }

That line redirects only the domains that have ssl enabled. Make sure that the load balancer has the correct 443 port set up to listen for requests and points to the correct container port.

Let me know if this works for you, otherwise I am sure we can solve the problem.

1 Like

Using an AWS ELB’s X-Forwarded-Proto header:

frontend 80
    acl http req.hdr(X-Forwarded-Proto) http
    redirect scheme https if http

(all my gratitude to this gist’s author)

1 Like