11

I'm trying to access the RabbitMQ interface over HTTPS/SSL with nginx, and I can't figure out what I'm missing.

Here's my rabbitmq.conf file:

[
  {ssl, [{versions, ['tlsv1.2', 'tlsv1.1']}]},
  {rabbit, [
      {reverse_dns_lookups, true},
      {hipe_compile, true},
      {tcp_listeners, [5672]},
      {ssl_listeners, [5671]},
      {ssl_options, [
        {cacertfile, "/etc/ssl/certs/CA.pem"},
        {certfile,   "/etc/nginx/ssl/my_domain.crt"},
        {keyfile,    "/etc/nginx/ssl/my_domain.key"},
        {versions, ['tlsv1.2', 'tlsv1.1']}
      ]}
    ]
  },
  {rabbitmq_management, [
    {listener, [
      {port, 15671},
      {ssl,  true},
      {ssl_opts, [
        {cacertfile, "/etc/ssl/certs/CA.pem"},
        {certfile,   "/etc/nginx/ssl/my_domain.crt"},
        {keyfile,    "/etc/nginx/ssl/my_domain.key"},
        {versions, ['tlsv1.2', 'tlsv1.1']}
      ]}
    ]}
  ]}
].

All works ok when I restart rabbitmq-server

My nginx file looks like this:

location /rabbitmq/ {
        if ($request_uri ~* "/rabbitmq/(.*)") {
                proxy_pass https://example.com:15671/$1;
        }
}

Now, I'm guessing there's something with the ngnix config not being able to resolve the HTTPS URL, as I'm getting 504 timeout errors when trying to browse:

https://example.com/rabbitmq/

Obviously, this is not the correct FQDN, but the SSL cert works fine without the /rabbitmq/

Has anyone been able to use the RabbitMQ Management web interface on an external connection over a FQDN and HTTPS?

Do I need to create a new "server" block in nginx config dedicated to the 15671 port?

Any help would be much appreciated!

Dario Zadro
  • 1,143
  • 2
  • 13
  • 23

5 Answers5

30

I ended up reverting back to the default rabbitmq.config file, then modified my nginx config block to the below, based on another stackoverflow answer that I can't find right now.

    location ~* /rabbitmq/api/(.*?)/(.*) {
        proxy_pass http://127.0.0.1:15672/api/$1/%2F/$2?$query_string;
        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;
    }

    location ~* /rabbitmq/(.*) {
        rewrite ^/rabbitmq/(.*)$ /$1 break;
        proxy_pass http://127.0.0.1:15672;
        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;
    }

Also, I had browser caching for JS files, which was causing issues and have disabled that.

I will try to re-enable SSL piece-by-piece but do have the example URL working for now:

https://example.com/rabbitmq/
Dario Zadro
  • 1,143
  • 2
  • 13
  • 23
  • This got me most of the way, but I'm getting a bunch of ``Cannot read property 'length' of undefined`` errors from js files, and I've tried both disabling and clearing my cache... did you ever find the core issue with the JS files and how to fix it? – scnerd Dec 21 '18 at 16:41
  • 1
    I removed the .js extension from nginx caching. – Dario Zadro Dec 24 '18 at 00:21
  • 2
    You saved me tons of time here. I only modified the target to another server behind a firewall and it worked perfectly. Just remember to add the "/" at the end of the URL in your browser. – David Welborn Aug 06 '19 at 15:48
  • Awesome David, glad it helped! – Dario Zadro Aug 11 '19 at 21:37
  • 1
    Thank you Dario. It works for some of the APIs like `queue` or `exchange`. But not with `user` API which doesn't need `%2F` as a vhost – leoleozhu Aug 21 '19 at 04:55
  • I got also the users API part working by removing the first location configuration. It only matched the users API management like `rabbitmq/api/users/my-username` and broke it. All other API calls were already going through the second location configuration. Tested with https://github.com/nginxinc/NGINX-Demos/tree/master/nginx-regex-tester . – Marko Lahma Sep 01 '20 at 06:25
  • Thanks, this rule `proxy_pass http://127.0.0.1:15672/api/$1/%2F/$2?$query_string;` worked for me, but seems like a hack. Should be easier. – jkulak Oct 01 '22 at 14:14
22

I tried the following nginx.conf

    location /rabbitmq/ {
        proxy_pass http://rabbitmq/;
        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;
    }

However I couldn't get the details for a queue or exchange. I got 404 errors for api calls. And there was a %2F in the url, it's url encoded /.

We need to keep the %2F in the API url and pass it to rabbitmq.

The following link describes how to keep the encoded url part and rewrite it. Nginx pass_proxy subdirectory without url decoding

So my solution is:

    location /rabbitmq/api/ {
        rewrite ^ $request_uri;
        rewrite ^/rabbitmq/api/(.*) /api/$1 break;
        return 400;
        proxy_pass http://rabbitmq$uri;
        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;
    }

    location /rabbitmq/ {
        proxy_pass http://rabbitmq/;
        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;
    }
leoleozhu
  • 630
  • 6
  • 21
8

This did the trick for me

location /rabbitmq {
  proxy_pass http://localhost:15672/;
  rewrite ^/rabbitmq/(.*)$ /$1 break;
}

I didn't have to use any other directives.

user3142747
  • 173
  • 3
  • 10
  • 1
    This answer again proves that copying lots of configuration is dangerous sometimes. This answer ended my 2 days debugging and searching for answer. Thanks. – Rafik Farhad Sep 02 '20 at 18:42
2

In case someone is looking for the solution for the Apache (2.4):

<VirtualHost *:443>
        ServerName              rabbitmq.your-domain.com
        AllowEncodedSlashes     NoDecode 
        ... // rest of the settings

        <Location "/">
          Require all granted
          
          ProxyPass         http://localhost:15672/
          ProxyPassReverse  http://localhost:15672/
        </Location>
        <Location "/api">
          Require all granted

          ProxyPass         http://localhost:15672/api nocanon
        </Location>
</VirtualHost>

In fact, 2 elements are very important:

  1. The 'AllowEncodedSlashes NoDecode' on VirtualHost level
  2. The 'nocanon' parameter for ProxyPass on "/api" location
Ziemowit Stolarczyk
  • 1,014
  • 2
  • 11
  • 26
2

This worked for me and I did not need any other header settings. This is a variation on the answer by @user3142747:

location /rabbitmq/ {
    # Strip off the "/rabbitmq" prefix
    rewrite  ^/rabbitmq/(.*) /$1 break;

    # Do NOT suffix proxy_pass path with a trailing "/". This allows NGINX to pass the client request completely unchanged.
    #    - see http://mailman.nginx.org/pipermail/nginx/2009-November/016577.html
    proxy_pass $scheme://localhost:15672;
}
WantStuff
  • 71
  • 1
  • 4