Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I make nginx-proxy redirect to www. and enforce https/ssl? #958

Open
haemse opened this issue Oct 28, 2017 · 20 comments
Open

How do I make nginx-proxy redirect to www. and enforce https/ssl? #958

haemse opened this issue Oct 28, 2017 · 20 comments

Comments

@haemse
Copy link

haemse commented Oct 28, 2017

No description provided.

@haemse
Copy link
Author

haemse commented Oct 30, 2017

Not a single hint?

@kamermans
Copy link
Contributor

I think you are more likely to get a response if you include something in the body :)

There is a section on enforcing HTTPS/SSL in the README - nginx-proxy does this by default by forwarding the user to HTTPS and sending them an HSTS response that prevents the browser from even trying HTTP again for a year.

I'll assume you are running another nginx container with VIRTUAL_HOST=www.foo.com and you want to redirect the foo.com requests to it. In this scenario, you should use VIRTUAL_HOST=www.foo.com,foo.com on that container, then add something like this to your foo.com site's nginx container:

server {
    listen 80;
    server_name foo.com;
    return 308 https://www.foo.com$request_uri;
}

Now requests for foo.com will go through nginx-proxy to the foo.com nginx container, which will send them back and HTTP 308 Permanent Redirect with Location: https://www.foo.com/<original_path>; then the browser will make a second request to the correct location.

@haemse
Copy link
Author

haemse commented Nov 7, 2017

Thanks, actually thats what I did eventually, but on the nginx-proxy, by including a vhost file. However 1. I think this should be done upfront at the proxy, so that the request is redirected right there and does not hast to go all the way through ...
2. I since using www. is good partice, I think this should be a simple option of the nginx-proxy.

Thanks though

@kamermans
Copy link
Contributor

Redirecting to www is definitely a common thing - I do it as well. Maybe there is a graceful way for us to do it in nginx-proxy, I'll need to think about it.

@xczheng
Copy link

xczheng commented Mar 6, 2018

For the https redirect from example.com to www.example.com, here I how I got it done:

  1. in my service container docker-compose.yml:
    environment:
    VIRTUAL_HOST: www.example.com
    LETSENCRYPT_HOST: example.com,www.example.com
    Note, I intentionally removed example.com from the VIRTUAL_HOST because I don't want to have the server example.com block to be generated from the template. We still need the example.com TLS certificate though in the LETSENCRYPT_HOST.

  2. Put an extra.conf in /etc/nginx/conf.d on the nginx container so it can redirect:
    server {
    listen 80;
    server_name example.com;
    return 308 https://www.example.com$request_uri;
    }

server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/certs/example.com.crt;
ssl_certificate_key /etc/nginx/certs/example.com.key;
ssl_dhparam /etc/nginx/certs/example.com.dhparam.pem;
return 308 https://www.example.com$request_uri;
}

  1. map this extra.conf to the container in the docker-compose.yml:
    volumes:
    • ./nginx/docker/extra.conf:/etc/nginx/conf.d/extra.conf

It is working, however, this is still a workaround as I have domain hardcoding in the extra.conf.
With this workaround, all the 3 below requests ended up on https://www.example.com:
http://www.example.com
http://example.com
https://example.com

@Redsandro
Copy link

@xczheng is this config still working for you? Or you found something better?

With the current versions of nginx-proxy and docker-letsencrypt-nginx-proxy-companion, I'm doing something similar but the le-companion clashes with the custom configuration: nginx-proxy/acme-companion#521

I've been messing a long time with this. User @witten suggests to use a separate redirect container. Seems like overkill, but at least it works. https://hub.docker.com/r/morbz/docker-web-redirect/

@coreyjewett
Copy link

I am running nginx-proxy for internal services. I wanted to redirect all short names to their corresponding fully qualified names. e.g. http://git/ -> https://git.internal.example.com/

I borrowed from @xczheng's idea, but instead of adding a new config file I modified the server_name '_'; section of the nginx.tmpl file:

--- a/nginx.tmpl
    b/nginx.tmpl
@@ -96,7  96,9 @@ server {
        listen [::]:80;
        {{ end }}
        access_log /var/log/nginx/access.log vhost;
-       return 503;
 
         # short name redirection.
         return 308 https://$host.internal.example.com$request_uri;

Then I removed all the short names from the docker-compose.yml VIRTUAL_HOST.

@SiGmAX666
Copy link

Thanks @xczheng your instructions worked perfect for my nonwww to www redirect, and the rest of my subdomains route as expected too.

@dm17
Copy link

dm17 commented Sep 30, 2019

I'm very confused about how this works across containers:

location /old/URL {
rewrite ^.* https://newURL.need.to/visit permanent;
return 307;
}

The wrong container is answering. When /old/URL is visited, it is via the domain need.to/old/URL, so the nginx-proxy talks to need.to's container, but the newURL.need.to needs to be the container nginx-proxy talks to... This nginx config was placed in the correct vhost.d/VIRTUAL_HOST filename. Do I need to use internal URLs or some docker-magic?

Thanks a lot... Stuck!
Edit: another confounding variable is the http -> https being done. The need.to/old/URL is on http://

@dm17
Copy link

dm17 commented Sep 30, 2019

OK, I figured it out using the following:
location /old/URL {
proxy_pass http://newURL.need.to/visit;
proxy_set_header host http://newURL.need.to/visit;
}

However... I also needed to use "HTTPS_METHOD=noredirect" in the container's env... And this has ended up causing other issues... Is there no way in this configuration to have no SSL redirect for a single regex / specific URL? This one proxy_pass has caused the website to required the noredirect setting for its entire domain!
Thanks again for your help!

@dm17
Copy link

dm17 commented Oct 1, 2019

This seems like the solution:
https://docs.nginx.com/nginx/admin-guide/security-controls/securing-http-traffic-upstream/

Anyone know which .pems to specify, though? And which files in nginx-proxy's certs mount to use as the .key file (as specify in the above nginx doc)?

EDIT: Figured it out: it is the per-VHOST fullchain.pem (for the cert) and key.pem (for the cert's key).

@dm17
Copy link

dm17 commented Oct 5, 2019

I've consolidated & clarified my question here: #1340
EDIT: @xczheng @coreyjewett @kamermans - any thoughts on this? I still haven't been able to figure it out, and I wonder if it is possible with nginx (considering switching for this one issue).

@dannycarrera
Copy link

@propheth were you able to get it working? I've been attempting to solve this issue without success

@dannycarrera
Copy link

@propheth great to hear that it works. I'm using https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion which seems to be adding some more complexity. I will try again tomorrow from scratch. Thanks!

@dannycarrera
Copy link

@propheth I think your solution only works when redirecting from an http site. According to nginx docs, when no listen directive is provided within a server block, it defaults to listen on 80. I would ensure it's working for you with browser caching disabled.

Also, I submitted #1369 to address this issue. If you want to take a look and use it before it gets merged, all you need is the updated nginx.tmpl. See #1369 for usage details.

Cheers, hope it helps!

@propheth
Copy link

propheth commented Dec 15, 2019

@dannycarrera the solution should work for both.

The standard jrcs/letsencrypt-nginx-proxy-companion handles the redirection to https 443 and by default communicates upstream via http 80 unless you set some other env vars.

Before applying the solution, your setup should already be redirecting from http://example.com -> https://example.com and http://www.example.com -> https://www.example.com.

The upstream nginx will check for a non-www and do a redirect to the www version whatever the schema/protocol be and vice-versa.

@dannycarrera
Copy link

@propheth so it seems you are you using 2 nginx containers? I think that's the part I missed from your solution.

With your approach you'll still run into the double redirect issue (#1204).

@d4n1b
Copy link

d4n1b commented Jan 22, 2020

Hi @dannycarrera,

Could you finally achieve the redirect?

@dannycarrera
Copy link

@d4n1b Yes, I made a PR #1369 for the changes to make it work seamlessly. They haven't been merged in yet, but I created a fork you can use if you don't want to wait. https://hub.docker.com/r/dannycarrera/nginx-proxy

@d4n1b
Copy link

d4n1b commented Jan 22, 2020

Thanks @dannycarrera! - I'll use that one in the meantime, as it looks like it's going to take a while to be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants