Using NGINX Reverse Proxy (Authentication and HTTPS)

Forget NGINX! Use Apache2 instead, if you want to change the path to e.g. https://myserver/openhab/basicui/app – after quite a few hours, I got it working with the following config file:

<Location "/openhab">
        Options SymLinksIfOwnerMatch

        AuthType Basic
        AuthName "openHAB"

        ## BEGIN LDAP
        AuthLDAPURL "ldap://localhost:389/ou=person,dc=codewizards,dc=co?cn?sub?(objectClass=person)"
        AuthLDAPBindDN "cn=CENSORED,ou=CENSORED,ou=person,dc=codewizards,dc=co"
        AuthLDAPBindPassword "CENSORED"
        #AuthzLDAPAuthoritative on
        AuthBasicProvider ldap
        Require valid-user
        ## END LDAP

        RewriteEngine On
        RewriteRule "/openhab/openhab/(.*)" "/openhab/$1" [R,L]
        RewriteRule "/openhab/?(.*)" "http://localhost:10080/$1" [P,L]
#               LogLevel alert rewrite:trace8

## We cannot use ProxyPass, because this implicitly adds its own rewrite-rules *before* ours!
## Hence, we cannot redirect the browser from .../openhab/openhab/... to .../openhab/...!
#               ProxyPass http://localhost:10080
        ProxyPassReverse http://localhost:10080

        ProxyHTMLEnable On

## The ProxyHTMLExtended can be used to work on *embedded* JavaScript. It does not work
## on separate .js-files. Thus, I now use SUBSTITUTE instead -- which works on both separate
## and embedded. Thus, this ProxyHTML* is not needed, anymore.
#               ProxyHTMLExtended On
#               ProxyHTMLURLMap / /openhab/ [e]
#               ProxyHTMLURLMap /basicui /openhab/basicui
#               ProxyHTMLURLMap /openhab/basicui /openhab/basicui

## Seems the suppression of gzip is not needed. Found this hint in the web,
## before, but the problem was actually another one. Thus, commented the following line
## again.
## UPDATE: IT IS NEEDED! My smarthome.js was obviously cached, before.
        RequestHeader unset Accept-Encoding

        AddOutputFilterByType SUBSTITUTE text/html
        AddOutputFilterByType SUBSTITUTE text/css
        AddOutputFilterByType SUBSTITUTE application/javascript
        AddOutputFilterByType SUBSTITUTE application/json
        Substitute "s|/basicui/|/openhab/basicui/|n"
        Substitute "s|/rest/|/openhab/rest/|n"
        Substitute "s|'/rest'|'/openhab/rest'|n"
        Substitute "s|/paperui/|/openhab/paperui/|n"
        Substitute "s|/inbox/|/openhab/inbox/|n"
        Substitute "s|/icon/|/openhab/icon/|n"
        Substitute "s|http://|https://|n"

This file is included in my default-ssl.conf:

<VirtualHost ... CENSORED ...>

... lots of other stuff ...

    Include /etc/apache2/openhab/openhab-ssl.conf

Both basicui and paperui work fine this way. But no guarantee: Maybe there are still more Substitute rules needed. I didn’t test everything, yet.

I hope this helps everyone who wants to use openHAB behind a reverse-proxy (and with LDAP-authentication)!

Best regards, Marco :slight_smile:

P.S.: It seriously sucks that openHAB doesn’t allow to configure a path-prefix! I have written quite a few programs in my life, already, and always when there were URLs involved, things like a prefix (or even more) were configurable. How can you even get the idea that this is an unnecessary feature?! And most importantly: If you really don’t want to configure it, why don’t you hard-code such a prefix (e.g. “openhab/”) – it would be far easier to remap an existing prefix than to deal with all these individual paths (like “basicui”, “paperui”, “rest” etc.).

1 Like

ARG!!! The Android app did not work, yet :frowning:

The following two lines need to be added:

AddOutputFilterByType SUBSTITUTE application/json

Substitute "s|http://|https://|n"

I’ll try to edit my previous post and add this.

Again an update:

RequestHeader unset Accept-Encoding

is needed! I thus removed the comment-# in my post above. It seems the smarthome.js was still in my browser-cache, after I disabled and tested it.

Well, it’s a pity that we can’t use gzip, but it doesn’t really matter. We’re usually in the LAN, anyway :wink:

Hey @nlmarco,
your contribution here is very much appreciated! Why don’t you move these steps to their own tutorial? The topic sure deserves one and a thread is easier found than reply number 38 here :wink:

Hi Thom, you’re absolutely right!

I was trying to get things running, read this thread, saw that things don’t work the way I need with NGINX, tried it with Apache (which was running already, anyway) and directly wrote it here :wink:

Now it’s really late and I’m going to postpone any further stuff to tomorrow. But certainly, I should write it in a cleaner way somewhere else.

Cheers, Marco :slight_smile:


As promised:


Hi, I run into this thread while banging my head to wall with nginx proxy. To simplify https certs, I have all my stuff behind one domain, separated by suffixes. OH2 basic UI looses all graphics and CSS files if it’s proxied like that. Any configuration option like grafana has: which I could set?

To clarify: not like, but, where nginx location is /openhab/ for the proxy.

I see there is post about “forget nginx” above, but I have it all in nginx, and I just can’t get it out of my mind :slight_smile:

Any new input for this topic?

My location:

  location /openhab/ {
    proxy_pass ;
    proxy_buffering                         off;
    proxy_set_header Host                   $http_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;
    auth_basic           "authme";
    auth_basic_user_file htpasswd;

To short answer is no.

Some have managed to figure out most of the urls that need to be replaced in the nginx config but I’ve not seen a complete working solution.

I think people using Apache have had better luck.

An issue has been filed and has remained open for quite some time but no progress has been made that I know of.

I see the right way to do it would be to have conf options for domain an suffix for UI components. All web server confs are temporary tricks around the problem, and any app change could break the web server confs again.

Is any app developer interested of this change? The conf should ask for domain and suffix used in proxy, and app should use those as variables for any internal links. In short :slight_smile:

EDIT: the issue seems to be reported here:

Did u accomplished to set it up ? My problem is that i cant proxy_pass directly to choosen skin and passing to http don’t work either. My config:

Public machine static IP (ipsec and nginx). VPN setup with openhab running on a dynamic IP.

when i setup ginx to proxy_pass from https://public_machine to http://local_vpn_machine it’does not work correctly. Config which is quite good is
listen 443;
proxy_buffering off;
proxy_set_header Host $http_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_redirect http:// $scheme://;

but i can’t setup this proxy_pass to redirect directly to - images are not loading at all. It’s a bit confusing to always choose the basicui skin manually

thx in advance

1 Like

WARNING: :skull_and_crossbones:

You need to limit JAVA/HTTP access to NGINX/Reverse Proxy!

Edit :


and change/set these: = false
org.ops4j.pax.web.listening.addresses =

Now openHAB2 listening only localhost (

tcp6       0      0          :::*                LISTEN      12731/java
tcp6       0      0         :::*                LISTEN      12731/java
tcp6       0      0          :::*                LISTEN      12731/java

Does anyone how how to setup this on a Windows 7 PC?

I am in the process of setting up my openhab installation and the route I wanted to go with the reverse proxy is via subdirectory rather than subdomain. I have got most of the items to work, but I am still working out a few areas. Try this in your nginx configuration and let me know how it works for you.

    ##### OpenHAB #####

    location ~* ^/(?:openhab|start|homebuilder|habpanel|basicui|paperui|rest|icon) {
      rewrite /openhab / break;
      rewrite /((?:start|homebuilder|habpanel|basicui|paperui|rest|icon)/.*) /$1 break;
      proxy_pass http://XXX.XXX.XXX.XXX:8080;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
1 Like

I’d like to test this. However I’ve changed from nginx to HAProxy, and would need to adapt the regexps. Would you mind opening these a bit?

location ~* ^/(?:openhab|start|homebuilder|habpanel|basicui|paperui|rest|icon) {

So any request starting with any of those words, or what does ‘?:’ there do?

rewrite /openhab / break;

This snaps away word openhab. So does ‘?:’ above skip the word, but expect it to be there?

rewrite /((?:start|homebuilder|habpanel|basicui|paperui|rest|icon)/.*) /$1 break;

Is this the same as passing anything after ‘openhab’ forward?

Thanks for sharing this.

The ?: means a non capturing expression, I haven’t tried it without but it might work without. The case for openhab redirects to the root directory on the target and the rest of the cases carry the first subdirectory forward since that is what the requests seem to reference when accessing it locally.

And when the app references to stuff like /icon or somethig, how do you modify the response to add /openhab to the beginning of uri? So that browser would know to request /openhab/icon instead of /icon? As without /openhab there at the beginning it would point them to non existent path in proxy, or some default site’s /icon directory.

To my understanding, all the above can be done in HAProxy by the following rules:

acl acl_5aef6814c09b63.87584580 path_beg -i /oh
# ACTION: to_openhab_bep_oh
use_backend openhab_bep if acl_5ae5eeecbbf009.46818008 acl_5aef6814c09b63.87584580

# Backend: openhab_bep (OpenHab backend)
backend openhab_bep
    # health checking is DISABLED
    mode http
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m  
    stick on src
    # tuning options
    timeout connect 30s
    timeout server 30s
    # ACL: add_auth
    acl acl_5afc4930790c77.74502605 http_auth(foobar)
    # ACTION: require_auth
    http-request auth realm foobar unless acl_5afc4930790c77.74502605
    # ACL:
    acl acl_5ae5eeecbbf009.46818008 hdr(host) -i
    # ACL: path_oh
    acl acl_5aef6814c09b63.87584580 path_beg -i /oh
    # ACTION: remove_oh_from_path
    http-request set-path %[path,regsub(^/oh/,/)] if acl_5ae5eeecbbf009.46818008 acl_5aef6814c09b63.87584580
    server OpenHAB openhab.intranet:8083 

So it basically checks if domain is and uri is /oh/whatever_here, and it just removes /oh. I don’t see the need to check for start|homebuilder|habpanel|basicui|paperui|rest|icon while testing this. perhaps later on it would be nice protection.

It kinda works. It shows the page.

However, now it has the problem I was asking for. So as the backend doesn’t have configuration item (?) for URI prefix, it points browser to e.g. /rest, instead of /oh/rest. To avoid that, all responses from openhab should be read through, and any occurance of such text to be replaced by /oh/ in before it.

It’s likely doable, but it is just so wrong I’m not going to do it. The proper way would be to have such an option in ESH backends configs, so that the app would insert the given $prefix into any URI it sends to browser. This is how many other apps work. Unfortunately it doesn’t have that, I was told, and it would take some effort to find the spots and add it everywhere in code.

So if someone ™ did the following, it would work right:

  1. add uri_prefix option into configs
  2. find all the spots where the applications send internal addresses to browser, like /rest
  3. add $uri_prefix to all those occurances.

After this the forward proxy would not need to do the URI rewrites either. Unfortunately there is no that someone around :smiley:

Hi All,

Just some basic questions. My OH2 server has a local instance of OpenHab Cloud running locally, this means NGINX and LetsEncrypt is already ready running. This was setup specifically for Cloud notifications from OH2 to my Mobile device.

I currently port forward 8080 to allow access to OH2 from the Internet, but restrict the networks on my Cisco Firewall.

I want to be able to password protect OH2 on the Web, I’m assuming most of this is already done given ive got OpenHab Cloud running locally, right on port 3000?

Which sections would I need to do to allow it to be password protected and use port 80? Further, does this give me the ability to expose HTTP elements in HabPanel and OpenHAB app using short names instead of the full URL? I currently have Grafana Graphs and fetch web cam images but for it to work I also need to open the devices to the Internet. Ideally, id like to stop all that and just have them referenced using http://local-servername/image.jpg for example

Thank you!

Hello All ,

I have a simple question , what i need to add in to the nginx configuration file in order to allow the acces to the port 9001 (openHAB log viewer)

as a example

when i access the DNS addres (example) : i insert my user and pass
then i access the log viewer from OH2 but i have a error

This address work :
This address it does not work :

The port forwarding is working , on the port 9001 because i can access using HTTP.

I know i have to add some extra information in to the ginx configuration

Here are my setting from the nginx
If is necessary i will add also the log file from nginx