Running other websites on the same machine as Discourse


(Graeme Stuart) #115

I removed the web.ssl.template.yml from my configuration as the OP states it is ‘handled by outer nginx’. This makes sense and I am reflecting the content of the template in my outer nginx discourse.conf file.

Another thing I notice is that my discourse instance is creating nginx.http.sock rather than nginx.https.sock. However, changing my discourse.conf file to reflect that still doesn’t work.

What might cause a 502 bad gateway? I’m assuming nginx is fine but is either missing the discourse or is redirecting to a broken discourse. What are the ways I can debug this?


(Juan M. Gonzalez) #116

It seems you are right:

Please note that this release removes support for SPDY. In the NGINX 1.9.x branch, we have completely removed the SPDY module from the codebase and replaced it with the HTTP/2 module. After moving to 1.9.5, you can no longer configure NGINX to use SPDY.
(…)
To enable HTTP/2 support, simply add the http2 parameter to all listen directives. Also include the ssl parameter, required because browsers do not support HTTP/2 without encryption.

(HTTP/2 Supported in Open Source NGINX 1.9.5 | NGINX, Sep 22, 2015)


(Vinoth Kannan) #117

I think you can still use nginx.http.sock for your ssl enabled outer nginx config.

And if you include web.ssl.template then you will get https sock instead


(Graeme Stuart) #118

Thanks, this is what I am doing. But I’m still getting a Bad Gateway 502.

My app.yml file has this, it exposes no ports, just the socket.

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.socketed.template.yml"
## Uncomment these two lines if you wish to add Lets Encrypt (https)
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

## which TCP/IP ports should this container expose?
## If you want Discourse to share a port with another webserver like Apache or nginx,
## see https://meta.discourse.org/t/17247 for details
expose:
  #- "80:80"   # http
  #- "443:443" # https

The outer nginx looks like this, it is redirecting http to https and then passing to the socket.

server {
        listen 80;
        listen [::]:80;
        server_name discourse.edi-net.eu;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name discourse.edi-net.eu;

        ssl on;
        ssl_certificate         /var/discourse/shared/standalone/ssl/ssl.crt;
        ssl_certificate_key     /var/discourse/shared/standalone/ssl/ssl.key;
        ssl_dhparam             /var/discourse/shared/standalone/ssl/dhparams.pem;
        ssl_session_tickets off;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS$
        ssl_prefer_server_ciphers on;

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

Is proxy_http_version 1.1 perhaps a problem?


(Vinoth Kannan) #119

You should not use https protocal in proxy_pass for http sock. Try by using http


(Graeme Stuart) #120

Good point. I changed it and I still got Bad Gateway after an nginx reload. So I turned to my discourse and it was somehow corrupted. ‘Marked for removal’ so I needed to destroy it and rebuild it.

Now I’m up and running. Thanks!


(probus) #121

It looks like the example nginx config for https is missing the line proxy_set_header X-Forwarded-Proto https.


(David Sánchez) #125

I have a droplet in Digital Ocean with Ubuntu 16.4 and the LAMP stack in order to run SMF 2.0. My plan is to migrate to Discourse in the near future. Given this, am I correct to install the following in the same droplet, in this order?

  1. Nginx
  2. Docker
  3. Discourse
  4. Setup Nginx so that my current SMF site continues showing mysite.com and perhaps a subdomain forum.mysite.com for Discourse?

(Jay Pfaffman) #126

You can move discourse to another port and have nginx reverse proxy to the discourse running under docker.


(Wang Yu) #127

The reason for the error bellow

connect() to unix:/var/discourse/shared/standalone/nginx.https.sock failed (2: No such file or directory)

is because you start nginx inside docker container which is not able to access the path of /var/discourse/shared/standalone/nginx.https.sock, so instead of using nginx inside docker, please start nginx from your vps, or configure this file for docker running nginx to accessable


(Christoph) #128

Does this mean that if you want to run Discourse and WordPress on the same machine, you should install Discourse first and then add WP rather than the other way around? Another post seems to suggest to do it the other way around… I am sure that experienced admins can do it either way, so what I’m asking here is: what is the more fool-proof path: first WP then discourse or the other way around?


(Jay Pfaffman) #129

I don’t think one is necessarily easier than the other. You install Discourse on a non standard port,so you can check that, thenyou configure something to reverse proxy to it. Then, if you’re clever you firewall off Discourse.


(Mitchell Krog) #130

I found this guide extremely useful and it works perfectly, took me a mere 20 minutes to setup and still have Nginx serving sites on port 80.


(Christoph) #131

I wish I’d understand enough of what you’re saying… Not blaming you or anyone, but I am struggling to because there seem to be so many ways of doing this and then when I look for advice and find what looks like a solution, I rarely know whether it actually applies to my situation. So for example, when you say “install Discourse on a non standard port” I am not sure whether I already did that by following the instructions in the OP or whether I still need to do this. Or whether the OP actually suggests a different path, namely to keep discourse on the default port and change the port for other applications insteads (it looks like that to me because it only tells me to delete the - "80:80" from /var/discourse/containers/app.yml but does not tell me to replace it with something else (e.g. - "8080:80" as other sources do).

Or the post that mitchellk is referring to:

It locates discourse.conf in either /etc/nginx/sites-enabled/ or /etc/nginx/sites-available/ whereas the OP says to put it into /etc/nginx/conf.d/. Furthermore, it suggests to make some changes to the configuration of the “inner nginx”, i.e. the nginx instance that discourse uses inside its container. I am very hesitant to make such changes to the container, as I assume that the discourse people have configured that container just as it’s supposed to be…

Anyway, my current problem is not that I can’t see discourse through nginx but that nginx sends everything to discourse. So, for example, when I try to access WP at <my-IP>/wp-admin/install.php or so, I get

And if I try the same using my domain (mydomain.net/wp-admin/install.php) nginx throws me a 502 Bad Gateway error.

I don’t understand two things:

  1. Why is discourse reacting to anything at all that does not start with the domain specified with DISCOURSE_HOSTNAME in app.yml (let’s say it’s forum.mydomain.net in my case)?

  2. How do I tell nginx to not route anything to discourse except for requests starting with forum.mydomain.net? I thought I did that by setting server_name forum.mydomain.net; in /etc/nginx/conf.d/discourse.conf as well as with

    upstream forum {
    server 127.0.0.1:8080 fail_timeout=0;
    }

and [I realized the following was nonsense, so I took it out]

server {
listen 80;
server_name forum.mydomain.net;


root /usr/share/nginx/html;
index index.html index.htm;

client_max_body_size 10G;

location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://forum;
}
}

in /etc/nginx/sites-available/default, but quite obviously that is either wrong or insufficient.

I can add that both my discourse and my WP installation seem to be running fine because if I disable the default site (by commenting out the entire /etc/nginx/sites-available/default), I can actually see WP (but not discourse any more).

Any advice would be appreciated.

As for the much appreciated instructions in the OP, I also would like to point out that this is where they could be improved for newbies like myself: [quote=“riking, post:1, topic:17247”]
Make sure that the default site is either disabled or has the correct server_name set.
[/quote]
How do you disable the default site? What would be the correct server_name? And how do I know whether to set the server name or disable it altogether?


(Christoph) #132

Okay, it looks like I finally got this to work, i.e. I have my dicourse forum at forum.mydomain.net and everything else goes to my WP istallation, including calls without a host name, using only the IP address.

Before I forget how I managed, I want to share some insights with anyone running into similar issues. For advanced users, all of this will be trivial, but I hope it will help others (and everyone else is welcome to correct inaccuracies or add explanations).

Insight 1 (and the answer to my questions 1 and 2 above): apparently nginx works in such a way that when it works as a webserver (i.e. serving my wordpress pages), it needs explicit instructions (server blocks) for every possible domain/sub-domain combination but not when it acts as a reverse proxy (i.e. when serving discourse pages). Since I only had a server block with server_name mydomain.net wordpress was only reachable under mydomain.net but not www.mydomain.net or . All other requests went to the reverse proxy even though the upstream directive was only for forum (as shown in my previous post). At least that is how I made sense of it.

So the solution was to make sure that my server_name includes all possible URLs (or all that should lead to the WP root directory): server_name mydomain.net *.mydomain.net almost accomplished that but requests to still went to discourse. So, you guessed it, I also included the IP: server_name mydomain.net *.mydomain.net <my-IP-adress>. No, I am not happy with this, since the IP may change, but I couldn’t be bothered searching for a more elegant solution.

Insight 2 You need to carefully watch your wordpress folder. Depending on which instructions you follow, you may have wordpress in /var/www/html, /var/www/html/wordpress or even /usr/share/nginx/html or /usr/share/nginx/html/wordpress (or you name it). So if you are blindly copying server blocks (or virtual hosts on apache) when you are configuring your webserver, chances are that you will have it pointing to the wrong directory.

To be more specific, I am talking about the root setting in the relevant server block in /etc/nginx/sites-available/default

Insight 3 There really is only one configuration file for your Nginx webserver and that is /etc/nginx/nginx.conf All the other files into which you write various settings (namely /etc/nginx/sites-available/default and /etc/nginx/conf.d/discourse.conf) become part of nginx.conf via include commands in that file. And, in case you havn-t already noticed, /etc/nginx/sites-available/default and /etc/nginx/sites-enabled/default are the same files (because the latter is just a symlink to the former. See here for a very good quick introduction into the basics of Nginx).

I am pasting my /etc/nginx/sites-available/default below because even though it currently works, I am not sure if the configuration is good because I have been trying so many settings from various sources, that I may have lost some important things or introduce some nonsense along the way. Please comment if you think there is something to be improved.

upstream forum {
server 127.0.0.1:8080 fail_timeout=0;
}

upstream php {
    server unix:/tmp/php-cgi.socket;
    server 127.0.0.1:9000;
}

server {
    server_name mydomain.net *.mydomain.net 46.101.xxx.xxx;
    root /var/www/html;
    ## This should be in your http block and if it is, it's not needed here. <-- it's not there, so I'm leaving it here
    index index.php index.html index.htm;

    location / {
            #try_files $uri $uri/ /index.php?$args;
             try_files $uri $uri/ /index.php?q=$uri&$args; 
    }

    error_page 404 /404.html;

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
            root /usr/share/nginx/html;
    }

    location ~ \.php$ {
            #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini <-- I did that
            include fastcgi.conf; # <-- this is crucial
            fastcgi_intercept_errors on;
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
            #fastcgi_pass php;
            fastcgi_index index.php;
            include fastcgi_params;
    }

    # This is for saving resources by caching static content longer
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
            expires max;
            log_not_found off;
    }

    location = /favicon.ico {
            log_not_found off;
            access_log off;
    }
	
   location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
    }
}

(Mitchell Krog) #133

Glad you got it working although if you followed the link to the guide I posted it’s current and it absolutely works 100% without any problems, a lot of solutions floating around there are not up to date unfortunately and can lead you in circles.

A couple of things to note with that guide and a few things I changed during my own setup.

Instead of doing mkdir /var/discourse I did mkdir /var/www/myforum.whatever.com

Then I cloned into that folder as it follows my nginx structure for all web sites being located in /var/www

Then I copied samples/standalone.yml containers/app.yml as per the instructions and edited that file which is now obviously located in /var/www/myforum.whatever.com/containers/app.yml and here’s how my app.yml file looks (all commenting removed). I obviously have high settings on memory and unicorn workers as I have a lot of available resources.

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
 
expose:
   - "25654:80"
#  - "80:80"   # http
#  - "443:443" # https

params:
  db_default_text_search_config: "pg_catalog.english"
  db_shared_buffers: "4GB"
  db_work_mem: "40MB"
env:
  LANG: en_US.UTF-8
  DISCOURSE_DEFAULT_LOCALE: en
  UNICORN_WORKERS: 6
  DISCOURSE_HOSTNAME: 'myforum.whatever.com'
  DISCOURSE_DEVELOPER_EMAILS: 'myemail@myforum.whatever.com'
  DISCOURSE_SMTP_ADDRESS: mx.whatever.com         # required
  DISCOURSE_SMTP_PORT: 587                        # (optional, default 587)
  DISCOURSE_SMTP_USER_NAME: myemail@myforum.whatever.com      # required
  DISCOURSE_SMTP_PASSWORD: mypassword               # required, WARNING the char '#' in pw can cause problems!
  DISCOURSE_SMTP_ENABLE_START_TLS: true           # (optional, default true)
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log
## Plugins go here
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
run:
  - exec: echo "Beginning of custom commands"
  - exec: rails r "SiteSetting.notification_email='myemail@myforum.whatever.com'"
  - exec: echo "End of custom commands"

then following that guide I ran

sudo ./launcher bootstrap app and sudo ./launcher start app which takes some time but note that during this process it creates the /var/discourse folder and puts everything it needs into their for you.

then there is NO discourse.conf file created in /etc/nginx/sites-available/ you create that yourself and here is how my working myforum.whatever.com.conf file for nginx looks with Let’s Encrypt SSL working 100%.

server {
	listen 443 ssl http2;
	root /var/www/myforum.whatever.com;
	server_name myforum.whatever.com www.myforum.whatever.com;
	charset UTF-8;
	access_log /var/log/nginx/myforum.whatever.com-access.log;
	error_log /var/log/nginx/myforum.whatever.com-error.log;
	ssl_certificate /etc/letsencrypt/live/myforum.whatever.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/myforum.whatever.com/privkey.pem;
	ssl_trusted_certificate /etc/letsencrypt/live/myforum.whatever.com/chain.pem;
	ssl_dhparam /etc/nginx/ssl/dhparam.pem;
	ssl_session_timeout 1d;
	ssl_session_cache shared:SSL:128m;
	ssl_session_tickets off;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
	ssl_prefer_server_ciphers on;
	add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
	ssl_stapling on;
	ssl_stapling_verify on;

	# Pass to discourse through a proxy
    location / {
        proxy_pass http://myforum.whatever.com:25654/;
        proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect http://myforum.whatever.com:25654/ https://myforum.whatever.com;
    }
# END OF SSL HOST CONFIG - CLOSING BRACE BELOW THIS LINE
}
server {
	listen 80;
  	server_name myforum.whatever.com www.myforum.whatever.com;
        return 301 https://myforum.whatever.com$request_uri;
# END OF HTTP PORT 80 HOST CONFIG - CLOSING BRACE BELOW THIS LINE
}

then a simple

sudo nginx -t
sudo service nginx reload

browse to the site and get the setup page … done. It really took 20 minutes I kid you not.

You could also change this section of the app.yml file to keep everything in one folder, then running multiple forums is easier as one change to /var/discourse won’t affect them all.

volumes:
  - volume:
      host: /var/www/myforum.whatever.com/shared/standalone
      guest: /shared
  - volume:
      host: /var/www/myforum.whatever.com/shared/standalone/log/var-log
      guest: /var/log

(Prakarsh Upmanyu) #134

I followed the given steps.
I plan to run Discourse through a subdirectory. Hence, I modified the nginx conf file with this line:

location /forum/ {

but when I try to run it I get the following error:

*21 connect() to unix:/var/discourse/shared/standalone/nginx.http.sock failed (2: No such file or directory) while connecting to upstream

/var/discourse/shared/standalone/nginx.http.sock does not exist!!

How can I fix this problem?


(Lutz Biermann) #136

As far as I know, a subfolder setup for Discourse is not officially supported. Do this only if you have experience as a Linux admin and if you can solve problems yourself. You really want to do two things at once. I would go step by step. You want to run Discourse with an additional nginx proxy next to other webpages on the same IP. And you want Discourse in a subfolder.

Please make sure that Discourse is running. Check if you have actually activated templates/web.socketed.template.yml in app.yml. If not, then uncomment it and rebuild Discourse. Then type in the console: locate nginx.http.sock and use the path found for your outer nginx.conf. If that still does not work, post your full app.yml (no mail passwords!) and your outer nginx.conf.


(Jeff Atwood) #137

This is not true. We do not recommend it because it is a complex setup that involves unavoidable proxying.


(Lutz Biermann) #138

Okay thank you, good to know!