Prevent Nginx from changing host

746 views Asked by At

I am building an application which is right now working on localhost. I have my entire dockerized application up and running at https://localhost/. HTTP request is being redirected to HTTPS

My nginx configuration in docker-compose.yml is handling all the requests as it should.

I want my application accessible from anywhere hence i tried using Ngrok to route the request to my localhost. Actually i have a mobile app in development so need a local server for apis.

Now, when i enter ngrok's url like abc123.ngrok.io in the browser, the nginx converts it to https://localhost/. That works for my host system's browser, as my web app is working there only, but when i open the same in my mobile emulator. It doesn't work.

I am newbie to nginx. Any suggestions will be welcomed. Here's my nginx configuration.

nginx.conf

upstream web {
    ip_hash;
    server web:443;
}

# Redirect all HTTP requests to HTTPS
server {
    listen 80;
    server_name localhost;
    return 301 https://$server_name$request_uri;
}

# for https requests
server {

    # Pass request to the web container
    location / {
        proxy_pass https://web/;
    }

    location /static/ {
        root /var/www/mysite/;
    }
    
    listen 443 ssl;
    server_name localhost;

    # SSL properties
    # (http://nginx.org/en/docs/http/configuring_https_servers.html)    
    ssl_certificate /etc/nginx/conf.d/certs/localhost.crt;
    ssl_certificate_key /etc/nginx/conf.d/certs/localhost.key;
    root /usr/share/nginx/html;    
    add_header Strict-Transport-Security "max-age=31536000" always;
}

This configuration i got from a tutorial.

1

There are 1 answers

5
Ivan Shatsky On BEST ANSWER

First of all, you set redirection from every HTTP request to HTTPS:

# Redirect all HTTP requests to HTTPS
server {
    listen 80;
    server_name localhost;
    return 301 https://$server_name$request_uri;
}

You are using $server_name variable here, so every /some/path?request_string HTTP request to your app would be redirected to https://localhost/some/path?request_string. At least change the return directive to

return 301 https://$host$request_uri;

Check this question for information about difference between $host and $server_name variables.

If these are your only server blocks in your nginx config, you can safely remove the server_name localhost; directive at all, those blocks still remains the default blocks for all incoming requests on 80 and 443 TCP ports.

The second one, if you are using self-signed certificate for localhost be ready for browser complains about mismatched certificate (issued for localhost, appeared at abc123.ngrok.io). If it doesn't break your mobile app, its ok, but if it is, you can get the certificate for your abc123.ngrok.io domain from Lets Encrypt for free after you start your ngrok connection, check this page for available ACME clients and options. Or you can disable HTTPS at all if it isn't strictly requred for your debug process, just use this single server block:

server {
    listen 80;

    # Pass request to the web container
    location / {
        proxy_pass https://web/;
    }

    location /static/ {
        root /var/www/mysite/;
    }
}

Of course this should not be used in production, only for debugging.

And the last one. I don't see any sense encrypting traffic between nginx and web containers inside docker itself, especially if you already setup HTTP-to-HTTPS redirection with nginx. It gives you nothing in the terms of security but only some extra overhead. Use plain HTTP protocol on port 80 for communications between nginx and web container:

upstream web {
    ip_hash;
    server web:80;
}

server {
    ...
    location / {
        proxy_pass http://web;
    }
}