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

Option to force the scheme forwarded by Nginx #46

Open
giohappy opened this issue Oct 9, 2024 · 6 comments
Open

Option to force the scheme forwarded by Nginx #46

giohappy opened this issue Oct 9, 2024 · 6 comments
Assignees

Comments

@giohappy
Copy link
Contributor

giohappy commented Oct 9, 2024

Overview

There are cases where the Nginx deployed with GeoNode sits itself behind an HTTP proxy, and this proxy often performs the SSL termination itself.
In this cases Nginx is served over port 80 and the HTTP_HOST variable is used to set the server name, instead of HTTPS_HOST.
The scheme forwarded by Nginx is obtained from the HTTP(S)_HOST variable, so if Nginx is served over 80, it will forward the http scheme to Django, even if GeoNode is served over https by the external HTTP server. This breaks the GeoNode APIs, because they get advertized (URLS and links inside the API responses) as being served over http, instead of https.

We introduce a new optional HTTP_FORWARDED_SCHEME .env variable that can be set to force the scheme forwarded by Nginx.
In case it is empty the current heuristic based on the host is maintained.

Solution

  • Add HTTP_FORWARDED_SCHEME to the .env.sample file in GeoNode and GeoNode Project.
  • Add the following to Nginx docker-entrypoint.sh:
--- 
+++ 
@@ -35,11 +35,16 @@
 if [ -z "${HTTPS_HOST}" ]; then
         HTTP_SCHEME="http"
 else
         HTTP_SCHEME="https"
 fi
 
+if [ -n "${HTTP_FORWARDED_SCHEME}" ]; then
+        echo "Force fowarded scheme ${HTTP_FORWARDED_SCHEME}"
+        HTTP_SCHEME=${HTTP_FORWARDED_SCHEME}
+fi
 export HTTP_SCHEME=${HTTP_SCHEME:-http}
 export GEONODE_LB_HOST_IP=${GEONODE_LB_HOST_IP:-django}
 export GEONODE_LB_PORT=${GEONODE_LB_PORT:-8000}
 export GEOSERVER_LB_HOST_IP=${GEOSERVER_LB_HOST_IP:-geoserver}
 export GEOSERVER_LB_PORT=${GEOSERVER_LB_PORT:-8080}
@giohappy giohappy self-assigned this Oct 9, 2024
@ridoo
Copy link

ridoo commented Oct 10, 2024

I configured external proxies (doing the TLS stuff) without that extra property. There is actually no need to disable https.

The proxy nginx includes this geonode.conf:

location / {
    proxy_pass http://geonode;  # proxy runs in the same network
    proxy_request_buffering off;
    client_max_body_size 0;

    proxy_set_header  Host $http_host;
    proxy_set_header  Origin $scheme://$http_host;
    proxy_set_header  X-Forwarded-Host $http_host;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto https;
}

However, we are using $http_host which keeps the scheme in the host. See here:

  proxy_redirect              off;
  proxy_set_header            Host $http_host;
  proxy_set_header            Origin $HTTP_SCHEME://$http_host;
  proxy_set_header            X-Real-IP $remote_addr;
  proxy_set_header            X-Forwarded-Host $http_host;
  proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header            X-Forwarded-Proto $HTTP_SCHEME;
  proxy_hide_header           X-Frame-Options;
  proxy_request_buffering     off;

BTW: $http_host was mentioned already as solution in

@giohappy
Copy link
Contributor Author

@ridoo the point is that without disabling https you might end up having a partially configured SSL termination in the Nginx proxy (either because Letsencrypt won't reach it, you don't have custom SSL certs for it, or you don't want to use self-signed certs).

I don't think $http_host; is relevant here. It was mainly proposed to forward the port (I haven't had the chance yet to test the proposal from Ricardo). The scheme is already forwarded by X-Forwarded-Proto $HTTP_SCHEME;

@ridoo
Copy link

ridoo commented Oct 14, 2024

the point is that without disabling https you might end up having a partially configured SSL termination in the Nginx proxy (either because Letsencrypt won't reach it, you don't have custom SSL certs for it, or you don't want to use self-signed certs).

I overlay the actual cert config like so:

  volumes:
    - statics:/mnt/volumes/statics
    # Link to a custom certificate here
    - /etc/letsencrypt/live/<your_domain>/fullchain.pem:/geonode-certificates/autoissued/fullchain.pem
    - /etc/letsencrypt/live/<your_domain>/privkey.pem:/geonode-certificates/autoissued/privkey.pem

@giohappy
Copy link
Contributor Author

ok so @ridoo you're using a self-signed cert for the internal Nginx.

@ridoo
Copy link

ridoo commented Oct 14, 2024

ok so @ridoo you're using a self-signed cert for the internal Nginx.

actually, what is created and updated by letsencrypt. This is not a self-signed certificate. Actually, what the GeoNode's letsencrypt service is doing, but managed by the server setup.

@giohappy
Copy link
Contributor Author

giohappy commented Oct 18, 2024

In my case the certificates are managed outside GeoNode and SSL termination is performed by the frontend server.
The internal GeoNode's Nginx is not exposed to the internet. This is the reason we don't need (and don't want in this specific case) to set it up over SSL.

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

2 participants