How to use NGINX as SSL Proxy with OpenNMS Horizon

Working with HTTP and SSL becomes easy and affordable to anyone thanks to Let’s Encrypt. This page describes how to use NGINX as a reverse SSL proxy in front of OpenNMS entangled with Let’s Encrypt.

Before you begin:

We have an OpenNMS Horizon web application which listens on 8980. The NGINX proxy is installed on a separate machine with a public facing IP and an assigned public domain name.

:information_source: This example is made with an NGINX installed on Ubuntu LTS. Configuration files are created in the folder /etc/nginx/sites-available. Any file linked into /etc/nginx/sites-enabled is loaded automatically on NGINX startup. This can be different and depends on your distribution.

Let’s Encrypt is installed on your NGINX proxy and the certificate setup and renewal can be achieved by running the certbot command.

Creating a reverse proxy site

Step 1: Add a site configuration in /etc/nginx/sites-available/horizon-proxy.conf

upstream onms_server {
    server 172.23.42.11:8980;
}

server {
    listen 80;
    server_name mynms.acme.com;

    # maintain the .well-known directory alias for lets encrypt renewals
    location /.well-known {
        alias /var/www/mynms.acme.com/.well-known;
    }

    location / {
        proxy_set_header    Host $host;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto $scheme;

        # Enable Web Socket for Browser notification in Horizon 24+
        proxy_set_header    Upgrade $http_upgrade;
        proxy_set_header    Connection "Upgrade";

        proxy_pass          http://onms_server;
        proxy_read_timeout  90;
    }
}

Step 2: Create a .well-known directory to allow certificate updates

Create a directory /var/www/mynms.acme.com/.well-known which allows dealing with the Let’s Encrypt handshake for obtaining and renewing your certificates.

Step 3: Link the configuration file and restart NGINX

cd /etc/nginx
ln -s sites-available/horizon-proxy.conf sites-enabled/horizon-proxy.conf
systemctl restart nginx

Step 4: Verify proxy connection and log in to your web app on mynms.acme.com/opennms.

Step 5: Install Let’s encrypt certificate

certbot --nginx -d mynms.acme.com

You will be asked if you want to force redirects to HTTPS.
Certbot will change your nginx configuration file to the following:

upstream onms_server {
    server 172.23.42.11:8980;
}

server {
    server_name mynms.acme.com;

    # maintain the .well-known directory alias for lets encrypt renewals
    location /.well-known {
        alias /var/www/mynms.acme.com/.well-known;
    }

    location / {
        add_header          Front-End-Https on;
        proxy_set_header    Host $host;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto $scheme;

        # Enable Web Socket for Browser notification in Horizon 24+
        proxy_set_header    Upgrade $http_upgrade;
        proxy_set_header    Connection "Upgrade";

        proxy_pass          http://onms_server;
        proxy_read_timeout  90;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/mynms.acme.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mynms.acme.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = mynms.acme.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name mynms.acme.com;
    return 404; # managed by Certbot
}

Step 6: Configure OpenNMS web app to serve https instead of http

Create a custom properties file opennms.properties.d/jetty-https.properties with the following content:

opennms.web.base-url = https://%x%c/

Step 7: Restart OpenNMS and restart nginx.

Test your setup, you should now be redirected to https://mynms.acme.com/opennms/login.jsp when you connect to http://mynms.acme.com


:woman_facepalming: You can fix me, I’m a wiki post.

1 Like

Hello, I have applied this configuration. Everything works except login.jsp and logout.jsp. It goes to page not found. If I enter index.jsp the console pops ups. Am I missing mod_proxy for apache ?

This howto set’s it up with NGINX, what gives you the impression the mod_proxy for apache is missing? Have you build a equivalent setup with apache instead of NGINX?

I thought I might be missing something as I have this exact setup and it works with the exception of login.jsp and logout.jsp redirect to http instead of https so I get page not found. Yet if I pop in index.jsp after going thru login.jsp and it timing out the session has started and console is available.

Hello , I configured ‘nginx’ in centos and it successfully redirects my request from ’ [https://nginx:8990]’ to ’ …/opennms/login.jsp’. But after login to opennms portal, actual opennms urls are getting exposed instead of nginx url.
Here is my proxy configuration from nginx – /etc/nginx/conf.d/proxy.conf

server {
  listen  8990 ssl;
  server_name  opennms;
  ssl on;
  ssl_certificate     /etc/nginx/ssl/rpwildcard.crt;
  ssl_certificate_key /etc/nginx/ssl/rpwildcard.key;
  location / {
       proxy_pass http://opennms:8980;
  }
}

Am I missing any configuration which could hide my opennms url to the user/browse ?

Thanks
Senthil

1 Like

Hi, in general this seems to work fine for 24.1.3 with the exception of Event Notification Configuration, the reverse proxy breaks the add notification wizard and also switching notifications on and off. I end up with a redirection to unknownexception.jsp. Is anyone else seeing this?

If you happen to use not-443 as the port, you’ll need to configure a couple extra things.

In the nginx config after the other proxy_set_header entries, add this:

     proxy_set_header X-Forwarded-Port 1443;

replacing 1443 with the port you’d like to use.

Then you’ll need to grab the example jetty.xml from $ONMS_HOME/etc/examples/jetty.xml and put it in $ONMS_HOME/etc. In the New element with id=httpConfig, add the following block after the last Set child element:

     <Call name="addCustomizer">
        <Arg>
           <New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/>
        </Arg>
     </Call>

The default config of ForwardedRequestCustomizer looks for the header we added to the nginx config to determine what port the URLs for redirects and links and such should have.

This works as of Horizon 25.2.0 but should be generally applicable to any release that uses jetty 9.x.

2 Likes

Ok, so I didn’t follow until the end indigo’s guide and after I did step 6 and step 7 everything is fine. So my question below describes a situation where steps 6 and 7 are not done yet. My bad and thanks to indigo for the guide!


Hello, I followed indigo’s guide and several other guides using Let’s Encrypt in NGINX reverse proxy. In OpenNMS Horizon (version 27.0.0, java 11.0.13, jetty 9.4.30.v20200611) I get “session expired” both in Firefox and Chrome after this: login (ok) → Networking interfaces (ok) → and when I click some “Node” on the list, node’s detailed subpage flashes but then goes back to the login page. From browser, I can go clicking back button eg to “home” or “networking interfaces” and continue browsing and everything is ok, I can also logout normally. Commenting out security headers does not affect on this behaviour.

This is my nginx proxy config.

server {
server_name my.horizon.com;

access_log /var/log/nginx/proxy_opennms.access.log;
error_log /var/log/nginx/proxy_opennms.error.log;

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/my.horizon.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/my.horizon.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

location / {
	proxy_set_header X-Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host:$server_port;

# Enable Web Socket for Browser notification in Horizon 24+
    proxy_set_header    Upgrade $http_upgrade;
    proxy_set_header    Connection "Upgrade";

#
# Security headers
#
add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; #HSTS
add_header X-Frame-Options DENY; #Prevents clickjacking
add_header X-Content-Type-Options nosniff; #Prevents mime sniffing
add_header X-XSS-Protection "1; mode=block"; #Prevents cross-site scripting attacks
add_header Referrer-Policy "origin"; 

#
# Here we point to Jetty
#
proxy_pass http://172.22.54.44:8980;
proxy_read_timeout  90;
proxy_redirect http://172.22.54.44:8980 https://my.horizon.com;
}
}
server {
    if ($host = my.horizon.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name my.horizon.com;
    return 404; # managed by Certbot
}

Would you have any ideas? OpenNMS UI is working fine when accessing directly 172.22.54.44:8980