Serving Graphhopper over HTTPS? Modifications to config.yml file?

So I have an ERR_SSL_PROTOCOL_ERROR which I’m trying to track down as I attempt to serve Graphhopper over https rather than http

So I have my custom graphhopper instance up and running (over http on port 8989) on an Ubuntu 20.04 server at vultr.com. I have a webmap which uses the Mapbox Javascript API in combination with the Graphhopper Javascript API to make the requests. The single-page website is secure and served over https, but the graphhopper data-requests are served over http. So the website is only operational if I allow insecure content in my web-browser.

I’ve been trying to self-teach my way through securing it on https but I am struggling (If anyone is comfortable with best practices of web-hosting and familiar with serving Graphhopper securely, I’ll pay like $70/hour to zoom/skype with me and help me figure this out - payment conditional on us solving the issue).

What I think I need to do - but I’m not sure are these four steps:

  1. Generate a Keystore File and Keystore Password for https connections (as discussed here)
  2. Copy the generated keystore file into my graphhopper folder on my vultr.com server; and modify the Dropwizard of the config.yml file to include https
  3. Buy a Domain name and point it to my server. I’m doing this because currently the Graphhopper Javascript API directly references the server IP address in my main.js file. https websites aren’t allowed to do that. They must reference domain names.
  4. Generate an SSL Certificate for that domain name (as discussed here)

So my config.yml file looks like this:

# ... other code ...

# Dropwizard server configuration
server:
  application_connectors:
  - type: http
    port: 8989
  - type: https
    port: 8988
    key_store_path: keystore-location
    key_store_password: <MYPASSWORDHERE>
    validate_certs: false
    # for security reasons bind to localhost
    # bind_host: localhost
  request_log:
      appenders: []
  admin_connectors:
  - type: http
    port: 8990
  - type: https
    port: 8991
    key_store_path: keystore-location
    key_store_password: <MYPASSWORDHERE>
    validate_certs: false
    #bind_host: localhost
# See https://www.dropwizard.io/1.3.8/docs/manual/configuration.html#logging
logging:
  appenders:
  - type: file
    time_zone: UTC
    current_log_filename: logs/graphhopper.log
    log_format: "%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
    archive: true
    archived_log_filename_pattern: ./logs/graphhopper-%d.log.gz
    archived_file_count: 30
    never_block: true
  - type: console
    time_zone: UTC
    log_format: "%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"

My netstat connections (when the graphhopper server is running)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      25145/nginx: master
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      3920/systemd-resolv
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      627/sshd: /usr/sbin
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      54985/mysqld
tcp6       0      0 :::80                   :::*                    LISTEN      25145/nginx: master
tcp6       0      0 :::22                   :::*                    LISTEN      627/sshd: /usr/sbin
tcp6       0      0 :::8988                 :::*                    LISTEN      55999/java
tcp6       0      0 :::8989                 :::*                    LISTEN      55999/java
tcp6       0      0 :::8990                 :::*                    LISTEN      55999/java
tcp6       0      0 :::8991                 :::*                    LISTEN      55999/java
tcp6       0      0 :::33060                :::*                    LISTEN      54985/mysqld

I wish I had specific questions to ask, but I’m very novice at web-hosting (and programming in general - entirely self taught). I am anywhere close? Is there documentation I should see? I can’t any specific help in prior forum posts.

Thanks for your time,
Dylan

Hey Dylan,

Long time no speak, hope you’re well!

My suggestion would be this: Leave GraphHopper running over vanilla HTTP and instead use nginx (which I see you already have on that server) to handle SSL for you and to “reverse proxy” requests to GrapHopper. This is a very common deployment model for modern web applications. Java is a pain in the backside to configure for SSL frankly, and there’s hundreds of guides and automation for it in nginx. GraphHopper’s own website uses nginx!

To do this, you would:

  1. Pick a domain name - e.g. api.tusconpathways.org - and point it at your server via DNS
  2. Request an SSL certificate for api.tusconpathways.org and configure it in nginx. You can get an SSL certificate for free these days via LetsEncrypt, and there’s loads of guides on how to set this up with nginx. Here’s one for Ubuntu: https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-18-04 or https://certbot.eff.org/lets-encrypt/ubuntufocal-nginx
  3. At this point you should be able to hit https://api.tusconpathways.org and see an nginx welcome message
  4. To complete the setup, you now just need to tell nginx to reverse proxy requests for https://api.tusconpathways.org/route to http://localhost:8989/route on your server. This would look something like this in your nginx config file:

In /etc/nginx/sites-available/api.tusconpathways.org:

server {
    listen       *:443 ssl http2;
    server_name  api.tusconpathways.org;

    ...

    # This is the start of the bit you should add
    location /route {
        proxy_pass http://localhost:8989/route;
    }
    # This is the end of the bit you should add
}

Once done, restart nginx, and you should be able to use https://api.tusconpathways.org/route as your routing endpoint.

Hope this helps!

1 Like

Sam!

Hey! I was planning on ceremoniously sharing my website with you once it was totally up and running, but looks like you’re coming to help one last time before then. I’m doing well all things considered, and hope life is smooth with you and family/friends on your end!

I spent the day following your steps. I still haven’t gotten it to work due to a ERR_SSL_PROTOCOL_ERROR but I think I’m very close. Let me know if anything sticks out to you? Does it have something to do with the fact that # bind_host: localhost is commented out in my config.yml? (That was a change I made weeks ago to get graphhopper to work over http on the Vultr Ubuntu Server)

A sample GET request from tucsonpathways.org to my neighborhoodpathways.org server:
(works perfectly fine when over http)

VM499:1 GET https://www.neighborhoodpathways.org:8989/route?point=32.237089%2C-110.898606&point=32.226522%2C-110.93947&debug=false&locale=en&points_encoded=true&instructions=true&elevation=false&optimize=false&profile=pathways1&details=road_class&details=distance net::ERR_SSL_PROTOCOL_ERROR

My etc/nginx/sites-available/neighborhoodpathways file on my server

server {
    server_name neighborhoodpathways.org www.neighborhoodpathways.org;
    root /var/www/neighborhoodpathways;

    index index.html index.htm index.php;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
     }

    location ~ /\.ht {
        deny all;
    }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/neighborhoodpathways.org/fullcha>
    ssl_certificate_key /etc/letsencrypt/live/neighborhoodpathways.org/pri>
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    location /route {
        proxy_pass http://localhost:8989/route;
    }
}
server {
    if ($host = www.neighborhoodpathways.org) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = neighborhoodpathways.org) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name neighborhoodpathways.org www.neighborhoodpathways.org;
    return 404; # managed by Certbot




}

netstat -plnt connections are:

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      617/nginx: master p
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      535/systemd-resolve
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      601/sshd: /usr/sbin
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      617/nginx: master p
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      1439/mysqld
tcp6       0      0 :::80                   :::*                    LISTEN      617/nginx: master p
tcp6       0      0 :::22                   :::*                    LISTEN      601/sshd: /usr/sbin
tcp6       0      0 :::8989                 :::*                    LISTEN      1320/java
tcp6       0      0 :::8990                 :::*                    LISTEN      1320/java
tcp6       0      0 :::33060                :::*                    LISTEN      1439/mysqld

And the Dropwizard portion of my config.yml file is:

...
# Dropwizard server configuration
server:
  application_connectors:
  - type: http
    port: 8989
#    bind_host: localhost
  request_log:
      appenders: []
  admin_connectors:
  - type: http
    port: 8990
#    bind_host: localhost
...

And my ufw firewall is currently disabled.

Let me know what you think? Thanks as always =]

Good news - you’ve already got it working: https://www.neighborhoodpathways.org/route?point=32.237089%2C-110.898606&point=32.226522%2C-110.93947&debug=false&locale=en&points_encoded=true&instructions=true&elevation=false&optimize=false&profile=pathways1&details=road_class&details=distance

The above link works for me without any errors or SSL certificate warnings.

Your issue was that you were trying to access the HTTP port (port 8989) over HTTPS - this resulting in the protocol error you saw.

Accessing the link above (https://www.neighborhoodpathways.org/route…) uses HTTPS and port 443 (this is the default HTTPS port if you don’t specify one). This is hitting nginx (you can see in your netstat command that nginx is listening on port 443), which then hits the “location /route” rule in nginx’s config and proxies the request back to http://localhost:8989 (which is your local GraphHopper instance).

I’d love to see a write-up of how you got everything working when you’re all done!

That was it! It worked! This is incredible! I can’t believe it! Oh wow! I just used the web-app on phone, and cycled across town to my favorite park - it made a perfect route through several neighborhoods I’ve never been through. It was a lovely and quiet bike commute just as programmed!

I’ll send you an email later today or tomorrow outlining how I put this together. In the meantime I’m going to probably go drink some beers out in the grass and take a long nap afterward haha. Sam, thank you so very much!

2 Likes
Powered by Discourse