MQTT through nginx and owntracks

I managed to compile.

Can I use the certificate (I use letsencrypt) that are on the other pi3?

p.s.
I have one pi3 with HASS 192.168.1.238 with letencrypt certificate
other pi3 has now this mginx modified version at 192.168.1.239

Ops I have this error

make -f objs/Makefile install
make[1]: Entering directory ‘/tmp/nginx/nginx’
test -d ‘/usr/local/nginx’ || mkdir -p ‘/usr/local/nginx’
mkdir: cannot create directory ‘/usr/local/nginx’: Permission denied
objs/Makefile:1381: recipe for target ‘install’ failed
make[1]: *** [install] Error 1
make[1]: Leaving directory ‘/tmp/nginx/nginx’
Makefile:11: recipe for target ‘install’ failed
make: *** [install] Error 2
pi@raspberrypi:/tmp/nginx/nginx $ sudo make && make install
make -f objs/Makefile
make[1]: Entering directory ‘/tmp/nginx/nginx’
make[1]: Nothing to be done for ‘build’.
make[1]: Leaving directory ‘/tmp/nginx/nginx’
make -f objs/Makefile install
make[1]: Entering directory ‘/tmp/nginx/nginx’
test -d ‘/usr/local/nginx’ || mkdir -p ‘/usr/local/nginx’
mkdir: cannot create directory ‘/usr/local/nginx’: Permission denied
objs/Makefile:1381: recipe for target ‘install’ failed
make[1]: *** [install] Error 1
make[1]: Leaving directory ‘/tmp/nginx/nginx’
Makefile:11: recipe for target ‘install’ failed
make: *** [install] Error 2
pi@raspberrypi:/tmp/nginx/nginx $

sudo make install or it can’t create the directory

The certificate is based on the hostname so you will get errors if they don’t match. If you don’t mind that the connection is still encrypted.

sites-available was not there, I create a new directory?

EDIT, lots of additional problem

Never mind. Project cancelled

So, I ran into a few issues and it took me a bit to work it out, but I got it. I’m also using nginx for the main Home Assistant page so I can do Alexa integration (which is awesome, can’t believe I put it off so long). At first I was trying to stick mosquitto in the sites-available like you did, but that directory by default is for HTTP connections, like websites. So it works for the Home Assistant site, but not for throwing the stream thing in there for MQTT, get errors about stream object in a bad spot. Ended up poking around your linked guide and just adding the stream config after the http config in the main nginx.conf file.

My other problem was I kept getting errors about “the shared memory zone ‘SSL’ is already declared for a different use in /etc/nginx/nginx.conf.” So, I removed all the SSL config stuff from the stream config. This produced a new error “no ‘ssl_certificate’ is defined in server listening on SSL port while SSL handshaking”. So, I went back and added in the ssl_certificate, ssl_certificate_key, and dhparam parameters to the stream config. They point to the same files I used for my main site access.

This is what I ended up with:

stream {
        upstream mosquitto {
                server servername:1883; # My MQTT server isn't on the same server
        }

        server {
                listen 8883 ssl;
                proxy_pass mosquitto;

                ssl_certificate /etc/nginx/ssl/cert.crt;
                ssl_certificate_key /etc/nginx/ssl/cert.key;
                ssl_dhparam /etc/nginx/ssl/dhparams.pem;
        }
}

Just wanted to share in case anyone else runs into those issues.

Note, I’m using a Ubuntu VM for Home Assistant and Nginx (same server) and CentOS VM for Mosquitto. So, I didn’t have to do anything special to use the stream directive. I’m also using Zanzito with the OwnTracks emulation with no issues. And I previously bought a wildcard SSL cert through ssl2buy.com (fairly cheap if you want to go that option vs letsencrypt or something similar).

1 Like

has anyone got nginx/mqtt/owntracks working with the hass.io addons?
I am using hass.io with the virtual host and cert bots from
https://github.com/bestlibre/hassio-addons

My nginx reverse proxy to 8123 with not problems.

UPDATE:
I did get it to work. For me the keys was learning where the hass.io add-on certbot stores the cert files. Also the mqtt config defaulted to the /ssl directory, so I had change my file path accordingly.
Here is my config …

{
  "plain": true,
  "ssl": true,
  "anonymous": false,
  "logins": [
    {
      "username": "user1",
      "password": "pass1"
    },
    {
      "username": "test_user",
      "password": "test_pass"
    }
  ],
  "customize": {
    "active": false,
    "folder": "mosquitto"
  },
  "certfile": "letsencrypt/live/mqtt/fullchain.pem",
  "keyfile": "letsencrypt/live/mqtt/privkey.pem"
}

I had the test_user for when I had 1883 port forward testing owntracks without having to fight TLS. I removed it after I got TLS (8883) working.
Also the cert that needs to be loaded on the owntracks client is in the same directory.
I copied the cert.perm to a different directory, then renamed it to mqtt_cert.perm.

I may play with and see if HA can connect TLS, then I can turn off 1883.

Just in-case anyone else is wondering about hassio:

To setup MQTT with websockets, you need to specify an additional config to MQTT with the following (and don’t turn on secure MQTT)

listener 8883
protocol websockets

Then in your nginx config from https://github.com/bestlibre/hassio-addons:

{
      "vhost": "mqttws.hostname",
      "remote": "172.17.0.1",
      "certname": "certname",
      "port": "1884"
},

I use this with owntracks without issues with TLS/Websockets enabled with the certbot.

I assume you could probably swap the secure/unsecure ports in your MQTT/Nginx config if you wanted only secure sockets and WS MQTT

1 Like

@lizaoreo
I followed your instructions and added the stream to .conf.
Seems to be working (dont know how to really test it but nginx is starting at least) but I`m having problem to connect with Zanzito.
Did you import the cert on your phone or how could you connect secure from Zanzito?
Also, how is the proxy_pass used?

To test:

sudo nginx -t

Are you using a purchased SSL cert for your domain? I actually purchased a wildcard cert for the domain I own, so it might be a little different than if you use something like one of the common solutions people use here.

If I understand how NGINX works (I honestly don’t really), the proxy_pass line points to the upstream line, which points to your server for MQTT. In my example above, my MQTT server would be named servername (change to localhost if on same server as NGINX) and it would be listening on port 1883 for MQTT traffic. NGINX is listening on port 8883 for MQTT traffic, so when you hit the NGINX server, you want your traffic to be on port 8883.

In Zanzito, my MQTT connection settings are basically this:

Host: NGINX Server Name (ie, mqtt.homedomain.com)
Port: 8883
Security:
  Username: MQTT Username (this is whatever you set up for mosquito, not NGINX/HomeAssistant)
  Password: MQTT Password
  SSL/TLS Connection: Checked
  Don't worry about import CA I'm pretty sure (I didn't need to).

Everything else is variable based on preference (I have instant updates set, heartbeat enabled, and intervals at 90seconds). I don’t use Home host settings as I set up the same domain name environment at home and forward the outside name to the server, so basically same address hits server inside and outside.

Let me know if that helps. If you need help with the mosquito server, let me know and I drop my config in and explain it.

Thank you for a good explanation!

Got it to work by pressing “Delete cert” in Zanzito. Apparently I had imported a cert before.

Can you post the relevant section in configuration.yaml?

My yaml:
mqtt:
broker: 127.0.0.1
port: 1883
client_id: home-assistant-1
username: !secret mqtt_username
password: !secret mqtt_password
However, the port specification is done in the mosquito component, not in HASS.
If you are on hassio, you can just open the mosquito component and set plain websockets to true. In the ngynix config, (I use the addon from https://github.com/bestlibre/hassio-addons) I added an entry to point to the 1884 nginx websockets port.

Do you specify the clientid because that’s what HA is using to communicate to the service?

What I’m trying to do is, from the internet, access mqtt.example.com on port 80 and have that proxied over to 192.168.1.25:1883. Hassio and nginx are running on different machines. Once I get that working I’ll muck around with SSL and user authentication.

client id can be anything. Username and pass have to exist in the MQTT side. Also, HASS does NOT use websockets. You have to support BOTH WS and non WS comms in mqtt.
WS requires some additional work in nginx to work properly if you aren’t using the hassio addon.

I’m doing the exact same thing (except on https) for owntracks.

I’m also using the add-on. Thanks to your server block, I’m able to get http://mqtt.example.com working.
Now I want to get https working, but I must be missing something or CertBot failed me. My config block looks like

{
  "plain": true,
  "plain_websockets": true,
  "ssl": false,
  "ssl_websockets": false,
  "anonymous": true,
  "logins": [
    {
      "username": "foo",
      "password": "bar"
    }
  ],
  "customize": {
    "active": false,
    "folder": "mosquitto"
  },
  "certfile": "fullchain.pem",
  "keyfile": "privkey.pem"
}

Since nginx is so new to me, im not 100% sure, but if you are using it for reverse proxy, then you don’t need to install certs on the target, correct? You can just run the service as http and nginx will force the client to use https using the cert installed in nginx and then proxy everything between the client and the target.

Last I checked, certbot didn’t support wildcard certs, so you need to make sure your cert covers mqtt.example.com You are correct about certs, mosquitto doesn’t need to know about them. I would however disable anonymous access. If you are able to access the mqtt service over http, you should be able to hit it over https if your certs are valid for that site.

I don’t think it does wildcards, but individual certs are so easy, why bother? I’m loving nginx and Certbot. Finally I can create as many subdomains I want for any service and have everything go over 80,443 without having to screw around with certs on the service itself. And no more having to remember port numbers! I just have to remember the subdomain and I’m golden. I’ve got about a dozen services I’m using with nginx now. I might even start using it for work for beta and internal sites. Why pay a few hundred bucks for a wildcard cert for ssl on test sites if I can get it for free?

I also want to hide my mqtt behind nginx on my hassbian install for zanzito.
but as soon I add a line with stram it hits me with
ginx: [emerg] "stream" directive is not allowed here in /etc/nginx/sites-enabled/mosquitto.conf:x
It looks so straight forward - but I realy struggle hard

stream directive needs nginx 1.9 - 1.10.3 installed
when I add in the nginx.conf:
load_module /usr/lib/nginx/modules/ngx_stream_module.so;
I ll get [emerg] module "ngx_stream_module" is already loaded in /etc/nginx/modules-enabled/50-mod-stream.conf:1 so the stream module is aparently loaded already.
here I hit rock bottom - out of ideas - So Ideas are most welcome

You just helped me figure it all out in another (very useful) thread, check this out if you’d like here