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 can proxy_pass work with nginx_proxy without 301s on HTTP addresses? #1340

Open
dm17 opened this issue Oct 5, 2019 · 7 comments
Open

Comments

@dm17
Copy link

dm17 commented Oct 5, 2019

location /specific/old/http/URL {
	proxy_pass http://service.new.tld/new;
	proxy_set_header host http://service.new.tld;
	proxy_ssl_certificate     /etc/nginx/certs/new.tld/fullchain.pem;
	proxy_ssl_certificate_key /etc/nginx/certs/new.tld/key.pem;
}
location /upstream {
    proxy_pass                http://service.new.tld;
    proxy_ssl_certificate     /etc/nginx/certs/service.new.tld/fullchain.pem;
    proxy_ssl_certificate_key /etc/nginx/certs/service.new.tld/key.pem;
}

This, put into vhosts, is working fine if the specific old URL was HTTPS, but it is HTTP! I cannot use HTTPS_METHOD=noredirect disabling auto SSL for the entire VHOST! Is it possible just to disable it for the context of this custom nginx location? I can see in the nginx-proxy logs that it gets a 301 before it even hits this nginx customization. So unfortunately, I've only been able to get this proxy_pass config to work with HTTPS URLs, not HTTP.

Thanks for your help!

@dm17
Copy link
Author

dm17 commented Oct 25, 2019

I still have not figured out how to do this... Maybe not possible with nginx.

@dm17
Copy link
Author

dm17 commented Oct 27, 2019

@jwilder I guess there's a more direct way I can ask: Is there any way to make your nginx proxy not forward HTTP -> HTTPS for a specific URL, only?

@dm17
Copy link
Author

dm17 commented Nov 12, 2019

This seems like confirmation it is not possible in this project:
https://stackoverflow.com/questions/58701863/is-there-any-way-to-make-your-nginx-proxy-not-forward-http-https-for-a-specif
@thomasleveil @kamermans -- any thoughts on this? Thanks!

@kamermans
Copy link
Contributor

There's definitely no feature to do this intentionally, and I can't think of any way to cleanly workaround it.

If I was in this situation, I might put my application behind another plain instance of nginx, so my application and an nginx instance are in the same docker-compose file, and nginx-proxy then forwards the requests to nginx which forwards them to the application. This is actually fairly common in when there is a tight integration between the webserver and the application (php-fpm, fcgi, etc).

@dm17
Copy link
Author

dm17 commented Nov 13, 2019

There's definitely no feature to do this intentionally, and I can't think of any way to cleanly workaround it.

If I was in this situation, I might put my application behind another plain instance of nginx, so my application and an nginx instance are in the same docker-compose file, and nginx-proxy then forwards the requests to nginx which forwards them to the application. This is actually fairly common in when there is a tight integration between the webserver and the application (php-fpm, fcgi, etc).

Thanks for your reply... Just wanted to confirm it sounded difficult before spending a bunch more time on this. Running another instance of nginx on the same system sounds like something a bit beyond my nginx familiarity. Were you recommending to run it on the host system - and continue running nginx-proxy in docker? Just want to understand your recommendation.

@kamermans
Copy link
Contributor

Hi @dm17, here's a working example that you can try:

First, make a new directory and create these files:

index.php - this is our dummy "application" that will just reply Hello World! to each request. In this example, the application will listen inside its container on port 8000.

<?php
echo "Hello World!\n";

default.conf - this is the nginx configuration for the instance of nginx that sits in front of your application and does the custom redirections, etc.

server {
    listen       80 default_server;

    access_log /dev/stdout main;
    error_log  /dev/stderr error;

    location =/specific/old/http/URL {
        proxy_pass http://app:8000;
    }

    location / {
        # Warning: "if" should only be used with rewrite and return statements
        # https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
        if ($http_x_forwarded_ssl != "on") {
            # Redirect the user to the HTTPS version of the site if required
            return 301 https://$host$request_uri;
        }

        proxy_pass http://app:8000;
    }
}

docker-compose.yml - this brings up the application and nginx:

# The application itself, listening on port 8000 in the container
app:
    image: php:7.3-cli-alpine
    volumes:
        - ./:/opt
    command: php -t /opt -S 0.0.0.0:8000

# Nginx sits in front of the application to handle redirections
nginx:
    image: nginx
    links:
        - app:app
    volumes:
        - ./default.conf:/etc/nginx/conf.d/default.conf
    environment:
        VIRTUAL_HOST: dev.foo.com

Note that I've set VIRTUAL_HOST on nginx now, instead of on your application, since I want nginx-proxy to send requests to it.

Now make sure you have an nginx-proxy running on your machine, and then you can run docker-compose up to start the application and nginx (aka the "stack").

You can use curl to make requests with the correct hostname, even though it's not in DNS:

curl -sSi -H 'Host: dev.foo.com' http://localhost/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.15.8
Date: Wed, 13 Nov 2019 17:16:06 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://dev.foo.com/specific/old/http/URLs

<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.17.5</center>
</body>
</html>

As you can see, this request is being answered with a redirection to the HTTPS version of the site.

The old URL you mentioned above, however, is not:

$ curl -sSi -H 'Host: dev.foo.com' http://localhost/specific/old/http/URL
HTTP/1.1 200 OK
Server: nginx/1.15.8
Date: Wed, 13 Nov 2019 17:16:01 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Host: app:8000
X-Powered-By: PHP/7.3.11

Hello World!

Hopefully this gets you to the point of being able to solve your problem!

@nealjack
Copy link

So a few years later, I can confirm the above works for this use case!

The only additional thing I had to do was set the HTTPS_METHOD env variable to disable the nginx-proxy auto-redirect so that the intermediary nginx layer could handle it instead.

Hope it helps for anyone else that stumbles upon this!

  # Nginx sits in front of the application to handle redirections
  nginx:
      image: nginx
      links:
          - hawkbit:app
      volumes:
          - ./default.conf:/etc/nginx/conf.d/default.conf
      environment:
          HTTPS_METHOD: "noredirect"
          VIRTUAL_HOST: "dev.foo.com"

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

3 participants