MQTT through nginx and owntracks

Has anyone tried to get owntracks and mqtt running behind an nginx proxy?

I used the all in one installer to get mosquitto installed, so I’m not quite sure what I need to do to get it all working behind nginx. I’ve tested locally/using simple port forwarding to connect to my server on port 9001 and owntracks/mqtt are all happy, but I can’t figure out how to do SSL+proxying through nginx to make everything happy.

Also interested in setting this up. I’ve found some docs on proxying secure websockets traffic, but not having any luck in getting it working on my end. On the Home Assistant side, everything is running within my local network, so I’m pointing to internal IPs (no SSL), but I can’t get OwnTracks or any MQTT debugging tools to connect successfully.

OwnTracks reports its connection parameters as:
mqtts://pi@<host.name.com>:<port> c0 k60 as pi/<DeviceID>

Hi nivekmai,
Can you show me how to config for mqtt running behind an nginx proxy (not SSL)?
My email: [email protected]
Thanks!

I don’t know how to, hence the thread.

I’ve simply got my router set up to forward ports 9001 and 1883 to my box running mqtt and that’s just running with the default all in one installer.

Has anyone been able to actually get Owntracks working through NGINX to MQTT?

Got Owntracks to go through WS to Mosquitto, but the websockets close shortly after registering. Likely a bug in either Owntracks or Mosquitto. Get the same behavior with or without nginx.

If anyone knows how to get websockets MQTT working properly with owntracks I’m all ears.

Alrighty, so I have it working, but mosquitto and owntracks complain and the socket dies after every connection. Owntracks still updates with position info, so I guess it “works”.

Here’s my nginx config entry:

server {
server_name mqtt.example.com;
listen 80;

location / {
    proxy_pass http://localhost:1884/; # The server you want to redirect to
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
}

My mosquitto config items to note:

port 1883
protocol mqtt
...
listener 1884
protocol websockets

Not sure about Home Assistant’s built-in MQTT server.

1 Like

Through a fair bit of experiementation, I managed to this going with letsencrypt SSL and basic auth on nginx so just sharing it here:

My nginx config looks like this.

server {
    listen 8889 ssl;
    server_name YOURSERVER; # Your site

    ssl_certificate     /etc/letsencrypt/live/YOURSERVER/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/YOURSERVER/privkey.pem;
    ssl_dhparam         /etc/nginx/ssl/dhparams.pem;


    location / {
       proxy_pass http://localhost:1884/; # Mosquitto websockets port

       proxy_redirect default;
       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 https;

       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "upgrade";
       auth_basic "Restricted Content";
       auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

On iOS app, at least (don’t know about Android):

Mode: Private (not HTTP)
Host: username:password@YOURSERVER
Port: 8889
WebSockets: Enabled
TLS: Enabled:
Authentication: Disabled
2 Likes

I have this set up but it just constantly tries to connect until after a long period of time it times out. Any idea what I’m doing wrong?

Hi - have you setup the same way as I did and using the iOS client? (post more details if you can)

What happens when you use your webbrowser to try and reach https://YOURSERVER:8889/ ? (login/password box should pop up)

Was basic auth required to get yours to work? I have MQTT auth on, with no basic auth… the client will connect but gets disconnected immediately after an update with an error like:

MQTT connection to broker was lost
Connection lost (32109) - java.io.EOFException

I’m fairly sure got it working without basic auth before turning it on - however the difference is that I don’t have MQTT auth on. For me, the reason for https + basic auth was because I didn’t want to switch authentication “on” at the MQTT end = too many devices already configured and harder to test :slight_smile:

Quick update on this. The solution is documented here: http://frankfurtlovesyou.com/posts/mqtt-bridge-with-mosquitto-and-nginx.html.

The stream directive needs nginx 1.9 and above. If you’re using Raspbian this isn’t available in jessie so I had to compile nginx from source - this is pretty straightforward even on a Pi Zero.

  1. Download the current STABLE source from Nginx.org: http://nginx.org/download/nginx-1.12.0.tar.gz
  2. Unzip in a user directory with gunzip -zxvf
  3. cd to the directory
  4. Install prequisites - this is what I needed from configure complaining as I kept trying:
    sudo apt install perl-pcre libpcre3-dev libssl-dev
  5. Configure with this string:
    ./configure --sbin-path=/usr/sbin --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-stream --with-stream_ssl_module
    This is a very basic configuration. The important bit is --with-stream --with-stream_ssl_module.
  6. Compile with
    make && make install

Nginx will be installed in /etc/nginx. Configuration is as the documentation above which I created in /etc/nginx/sites-available/mosquitto:

stream {

    upstream mosquitto {
    server localhost:1883;
}

server {
    listen 8883 ssl;
    proxy_pass mosquitto;

    ssl_certificate /etc/dehydrated/certs/example.com/fullchain.pem;
    ssl_certificate_key /etc/dehydrated/certs/example.com/privkey.pem;

    # from https://cipherli.st/
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_ecdh_curve secp384r1;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
}
}

The SSL configuration is optional but desirable especially if you are exposing the port to the outside world. It may be advisable to generate your dhparam key on another machine, as it takes a while on a Pi. 15 hours or so.

Enable by linking in sites-enabled:
cd /etc/nginx/sites-enabled
ln -s …/sites-available/mosquitto .

To create your SSL certificates I use dehydrated (https://dehydrated.de/), which is a bash LetsEncrypt client which has built in support for DNS validation through assorted modules which is handy for machines that you don’t want to expose to the Internet too much. Follow the instructions on the git site to make them work for you.

Test nginx with nginx -t

What you won’t have at this point is a service file for nginx as in a package so here it is:

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Copy this to /lib/systemd/system/nginx.service and run:

systemctl enable nginx
systemctl unmask nginx
systemctl start nginx

And you should now have a proxy listening on 8883.

For reference this is my mosquitto.conf, nothing special in it:

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

connection_messages true
log_dest file /var/log/mosquitto/mosquitto.log

password_file /etc/mosquitto/passwd

include_dir /etc/mosquitto/conf.d

This connects to Owntracks and updates although some more logging might be handy in the debug stage.

1 Like

can you tell me where I have to put this?

Copy this to /lib/systemd/system/nginx.service and run:

systemctl enable nginx
systemctl unmask nginx
systemctl start nginx

thanks now I have installed NGINX on HASSBIAN, so I think is version 1.8 (I use it for HASS and works perfectly, wanted to make it work also for mqtt)

Do I need to uninstall and then use your procedure, or?

And then to make it work on HASS with 1.12, any particu;ar procedure?

Yes, the issue is that streaming is only supported in nginx 1.9+ which isn’t available in Debian Jessie, so you have to uninstall the repo version and build from source. However my workaround was to use a Pi Zero as a proxy which I use to terminate SSL, so you don’t have to interfere with the Hasbian install if you don’t want to.

I see, but I don’t get it totally.

Following your instructions you create a file mosquito. Do you have to create also a file HASS (in nginx 1.8 following instructions on this forum I had to create a file HASS)??

I do have 2 pi3 in my network maybe I can use the other pi3 for nginx?

My doubts are which nginx configuration for using hass, mosquito, and other services