Difference between socket- and port-based connection to outer NGINX?

If I understand things correctly there are two ways of configuring your discourse instance behind an NGINX server:

  1. with a socket connection (as described here)
  2. by exposing some port of the container and telling the outer NGINX to forward traffic for discourse to that port (as suggested here and here).

Since the how-to here on meta uses the socket method, I suppose that is the preferred method. But what exactly are the benefits compared to the port-method?

I can’t seem to get the the socket version to work even though I followed the instructions here. I just get ERR_CONNECTION_REFUSED when trying to access the discourse subdomain. Other webpages served by the same NGINX are working fine.

3 Likes

UNIX sockets (as opposed to TCP sockets) are faster and more efficient, and less prone to accidental disclosure to places you don’t want connections coming from. A misconfiguration can potentially cause a listening TCP socket to be exposed to the Internet, whereas there’s absolutely no way you can make a mistake such that a UNIX socket is exposed directly to the Internet.

8 Likes

OK, so I’ll continue trying the UNIX socket. What would be some steps for trouble shooting why a UNIX socket is not working? (I already have the default_server listening on port 81 for the time being, just to have it out of the way)

I think there is a typo in the tutorial. At the end of the first line is a colon too much. Don’t forget to rebuild!

For https installations It should be:

        proxy_pass              http://unix:/var/discourse/shared/standalone/nginx.http.sock;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        Host $host;
        proxy_http_version      1.1;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto "https";

Remove the last line if you do not use https. If this does not work, please type the following at the console and show us the result:

ls -al /var/discourse/shared/standalone/nginx.http.sock
updatedb && locate nginx.http.sock

If “locate” ist not found, you can install it:

apt-get install locate
5 Likes

I already tried both with and without the extra colon. But good to know that it should definitely be without the colon. Regarding rebuild: this is the config for the outer NGINX, so I don’t see why a rebuilt would be necessary. Or did I miss something? Or do you mean restart the NGINX?

I am on http for the moment, just to avoid any additional sources of error. This is my discourse.conf:

server {
    listen 80; listen [::]:80;
    server_name test.mydomain.com;
}

location / {
    proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
    proxy_set_header Host $http_host;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    }
}

ls -al /var/discourse/shared/standalone/nginx.http.sock gives me
srw-rw-rw- 1 root root 0 Mar 29 02:53 /var/discourse/shared/standalone/nginx.http.sock

sudo updatedb && locate nginx.http.sockgives me (after quite a bit of delay)
/var/discourse/shared/standalone/nginx.http.sock

You need to put the whole location block inside the server block.

4 Likes

Opps, how embarassing. :dizzy_face: But also interesting that sudo nginx -t did not complain about the extra }.

Unfortunately, however, that was apparently not the only problem as I still get ERR_CONNECTION_REFUSED :frowning:

Where did you get this ERR_CONNECTION_REFUSED error? On a client machine? If so then your nginx is just not listening on port 80.

Yes, the error is on a client machine. Okay, then I suspect the problem is with my /etc/nginx/sites-available/default. For the time being I set it to listen to port 81:

server {
        listen 81 default_server;
        listen [::]:81 default_server;
        server_name 88.99.**.** mydomain.net www.mydomain.net;

In my mind, this should imply that /etc/nginx/sites-available/default will not interfere with the settings in discourse.conf and indeed: if I change the defauklt server to port 80, I get the BGINX welcome page instead of ERR_CONNECTION_REFUSED.

So maybe my discourse.conf is simply not being included in the nginx.conf? That would also explain why NGINX din’t complain about the extra }… And indeed, I had my discourse.conf in the wrong path (sites-available instead of sites-enabled).

But when I fixed that, I saw the NGINX welcome page even when calling test.mydomain.net. So, for lack of other ideas, I tried starting the conainer but uit said it was already started. So I stopped and re-started it and now I’m getting 502 bad gateway.

So I did a cleanup based on this suggestion (plus a stop and restart of the container) and tada it is finally working. :tada:

So, to draw some lessons from this that might be useful for others: what puzzles me is how exactly the container interacts with the outer NGINX. As I indicated earlier, I was assuming that they are two separate entities that are merely linked in that they are sending packets back and forth between them. In other words: changes in the NGINX-configuration will not affect the container at all, as long as those packets are still sent back and forth. But now it looks like the container “fixed itself” after I fixed the outer NGINX?!?

Or maybe this is just a combination of several independent issues? In other words: if I had done a container cleanup earlier, and then fixed the outer NGINX, the result would have been the same?

2 Likes

@tophee @Lutz pls give me some advice thx
I have 3 multisite running each of them disable https and run a nginx over the host, nginx.conf is like this.url is 522 error.

events {
    worker_connections 1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    lua_shared_dict ssl_certs_cache 1m;

    init_by_lua_block {
        -- Define a funcction to determine which SNI domains to automatically
        -- handle and register new certificates for. Defaults to not allowing
        -- any domain, so this must be configured.
        function allow_domain(domain)
            if domain:find("antivte.com$") then
                return true
            end
            return false
        end

        -- Initialize backend certificate server instance.
        cert_server = (require "resty.ssl-cert-server").new({
            backend = '127.0.0.1:8999',
            allow_domain = allow_domain
        })
    }

    # HTTPS Server
    server {
        listen 443 ssl;

        # Works also with non-default HTTPS port.
        listen 8443 ssl;

        server_name bbs.antivte.com;  # <-- change this

        # Dynamic handler for issuing or returning certs for SNI domains.
        ssl_certificate_by_lua_block {
            cert_server:ssl_certificate()
        }

        # Fallback certificate required by nginx, self-signed is ok.
        # openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
        #   -subj '/CN=sni-support-required-for-valid-ssl' \
        #   -keyout /etc/nginx/certs/fallback-self-signed.key \
        #   -out /etc/nginx/certs/fallback-self-signed.crt
        ssl_certificate /etc/nginx/certs/fallback-self-signed.crt;
        ssl_certificate_key /etc/nginx/certs/fallback-self-signed.key;


        location / {
                proxy_pass http://unix:/var/discourse/shared/bbs/nginx.http.sock:;
                proxy_set_header Host $http_host;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Real-IP $remote_addr;
        }
    }

    # HTTP Server
    server {
        listen 80;
        server_name bbs.antivte.com;  # <-- change this
        return 301 https://$host$request_uri;

        # Endpoint used for performing domain verification with Let's Encrypt.
        location /.well-known/acme-challenge/ {
            content_by_lua_block {
                cert_server:challenge_server()
            }
        }
    }


    # HTTPS Server
    server {
        listen 443 ssl;

        # Works also with non-default HTTPS port.
        listen 8443 ssl;

        server_name ytb.antivte.com;  # <-- change this

        # Dynamic handler for issuing or returning certs for SNI domains.
        ssl_certificate_by_lua_block {
            cert_server:ssl_certificate()
        }

        # Fallback certificate required by nginx, self-signed is ok.
        # openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
        #   -subj '/CN=sni-support-required-for-valid-ssl' \
        #   -keyout /etc/nginx/certs/fallback-self-signed.key \
        #   -out /etc/nginx/certs/fallback-self-signed.crt
        ssl_certificate /etc/nginx/certs/fallback-self-signed.crt;
        ssl_certificate_key /etc/nginx/certs/fallback-self-signed.key;

        location / {
                proxy_pass http://unix:/var/discourse/shared/ytb/nginx.http.sock:;
                proxy_set_header Host $http_host;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Real-IP $remote_addr;
        }        
    }

    # HTTP Server
    server {
        listen 80;
        server_name ytb.antivte.com;  # <-- change this
        return 301 https://$host$request_uri;

        # Endpoint used for performing domain verification with Let's Encrypt.
        location /.well-known/acme-challenge/ {
            content_by_lua_block {
                cert_server:challenge_server()
            }
        }
    }
 
    # HTTPS Server
    server {
        listen 443 ssl;

        # Works also with non-default HTTPS port.
        listen 8443 ssl;

        server_name cp.antivte.com;  # <-- change this

        # Dynamic handler for issuing or returning certs for SNI domains.
        ssl_certificate_by_lua_block {
            cert_server:ssl_certificate()
        }

        # Fallback certificate required by nginx, self-signed is ok.
        # openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
        #   -subj '/CN=sni-support-required-for-valid-ssl' \
        #   -keyout /etc/nginx/certs/fallback-self-signed.key \
        #   -out /etc/nginx/certs/fallback-self-signed.crt
        ssl_certificate /etc/nginx/certs/fallback-self-signed.crt;
        ssl_certificate_key /etc/nginx/certs/fallback-self-signed.key;

        location / {
                proxy_pass http://unix:/var/discourse/shared/cp/nginx.http.sock:;
                proxy_set_header Host $http_host;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Real-IP $remote_addr;
        }
    }

    # HTTP Server
    server {
        listen 80;
        server_name cp.antivte.com;  # <-- change this
        return 301 https://$host$request_uri;

        # Endpoint used for performing domain verification with Let's Encrypt.
        location /.well-known/acme-challenge/ {
            content_by_lua_block {
                cert_server:challenge_server()
            }
        }
    }   
}
   

and this one is ok

root@docker-s-1vcpu-2gb-sgp1-01:/var/discourse# curl --unix-socket /var/discourse/shared/bbs/nginx.http.sock http:/images/json<!DOCTYPE html>
<html lang="en-US">
<head>
  <meta charset="utf-8">
  <title>Discourse</title>
  <meta name="description" content="">
  <meta name="generator" content="Discourse 2.4.0.beta9 - https://github.com/discourse/discourse version 86fb08d04a841b1967e2bb5ec879a07dc6210eee">
<link rel="icon" type="image/png" href="http://bbs.antivte.com/uploads/default/optimized/1X/_129430568242d1b7f853bb13ebea28b3f6af4e7_2_32x32.png">
<link rel="apple-touch-icon" type="image/png" href="http://bbs.antivte.com/uploads/default/optimized/1X/_129430568242d1b7f853bb13ebea28b3f6af4e7_2_180x180.png">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=yes, viewport-fit=cover">

<script type="application/ld+json">{"@context":"http://schema.org","@type":"WebSite","url":"http://bbs.antivte.com","potentialAction":{"@type":"SearchAction","target":"http://bbs.antivte.com/search?q={search_term_string}","query-input":"required name=search_term_string"}}</script>
<link rel="search" type="application/opensearchdescription+xml" href="http://bbs.antivte.com/opensearch.xml" title="Discourse Search">

    <link href="/stylesheets/desktop_cf66a5b18273cc17f4c0a96847c93ecda0519dc8.css?__ws=bbs.antivte.com" media="all" rel="stylesheet" data-target="desktop" data-theme-id="2"/>


  <link href="/stylesheets/desktop_theme_2_1dbc8b6a9b9bc0ce8633dbac246d040d6b9e3f6d.css?__ws=bbs.antivte.com" media="all" rel="stylesheet" data-target="desktop_theme" data-theme-id="2"/>

  <link href="/stylesheets/discourse-details_cf66a5b18273cc17f4c0a96847c93ecda0519dc8.css?__ws=bbs.antivte.com" media="all" rel="stylesheet" data-target="discourse-details" data-theme-id="2"/>
  
  <link href="/stylesheets/discourse-local-dates_cf66a5b18273cc17f4c0a96847c93ecda0519dc8.css?__ws=bbs.antivte.com" media="all" rel="stylesheet" data-target="discourse-local-dates" data-theme-id="2"/>
  <link href="/stylesheets/discourse-presence_cf66a5b18273cc17f4c0a96847c93ecda0519dc8.css?__ws=bbs.antivte.com" media="all" rel="stylesheet" data-target="discourse-presence" data-theme-id="2"/>
  <link href="/stylesheets/lazy-yt_cf66a5b18273cc17f4c0a96847c93ecda0519dc8.css?__ws=bbs.antivte.com" media="all" rel="stylesheet" data-target="lazy-yt" data-theme-id="2"/>
  <link href="/stylesheets/poll_cf66a5b18273cc17f4c0a96847c93ecda0519dc8.css?__ws=bbs.antivte.com" media="all" rel="stylesheet" data-target="poll" data-theme-id="2"/>
  <link href="/stylesheets/poll_desktop_cf66a5b18273cc17f4c0a96847c93ecda0519dc8.css?__ws=bbs.antivte.com" media="all" rel="stylesheet" data-target="poll_desktop" data-theme-id="2"/>

  

  
  
  
</head>
<body >
  
  
  <section id='main'>
    
  <header class="d-header">
    <div class="wrap">
      <div class="contents">
        <div class="header-row">
          <div class="logo-wrapper">
            <a href="/">
                <img src="http://bbs.antivte.com/images/discourse-logo-sketch.png" alt="Discourse" id="site-logo">
            </a>
          </div>
            <div class='auth-buttons'>
                <a href="/signup" class='btn btn-primary btn-small signup-button'>Sign Up</a>
              <a href="/login" class='btn btn-primary btn-small login-button btn-icon-text'><svg class="fa d-icon svg-icon svg-node" aria-hidden="true"><svg id="user" viewBox="0 0 448 512">
    <path d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"/>
  </svg></svg>
Log In</a>
            </div>
        </div>
      </div>
    </div>
  </header>

    <div id="main-outlet" class="wrap not-found-container">
      <div class="page-not-found">
  <h1 class="title">Oops! That page doesn’t exist or is private.</h1>

</div>



<div class="row page-not-found-topics">
  <div class="popular-topics">
    <h2 class="popular-topics-title">Popular</h2>
    <a href="/top" class="btn btn-default">More&hellip;</a>
  </div>
  <div class="recent-topics">
    <h2 class="recent-topics-title">Recent</h2>
      <div class='not-found-topic'>
        <a href="/t/welcome-to-discourse/7">Welcome to Discourse</a>
      </div>
    <a href="/latest" class="btn btn-default">More&hellip;</a>
  </div>
</div>


  <div class="row">
    <div class="page-not-found-search">
      <h2>Search this site</h2>
      <p>
        <form action='/search' id='discourse-search'>
          <input type="text" name="q" value="">
          <button class="btn btn-primary">Search</button>
        </form>
      </p>
    </div>
  </div>

  <link rel="preload" href="/assets/onpopstate-handler-09bc9d995084d732c7f6dfaadcd21404e817fc736165b7b893bc2dd040749aae.js" as="script">
<script src="/assets/onpopstate-handler-09bc9d995084d732c7f6dfaadcd21404e817fc736165b7b893bc2dd040749aae.js"></script>


    </div>
  </section>
  
  
  
  
</body>
</html>
root@docker-s-1vcpu-2gb-sgp1-01:/var/discourse# 

Sorry, I can’t help you with this. The first and (almost) last time I looked at the details of NGINX was three years ago, when I set up my forum… And I have no experience with multi-site at all.