Installation on v-server as a subfolder with other services in subfolders using apache

Ok, after stoping apache2 the installation worked fine and nginx was running, but it blocked apache2. Stoping nginx and restarting apache2 worked, but restarting nginx fails as long as apache2 is running.

Good! Now that both are installed, you can configure them as you want.

The basic plan of attack (if you want to follow my recommendation) is this:

  1. Teach Apache to listen on another port, leaving port 80 (and maybe 443 for SSL) free. If Apache has been doing SSL for you so far, dismiss Apache of this duty.
  2. Get nginx to listen on port 80 (and maybe 443). nginx will also handle SSL if needed.
  3. Teach nginx to sort incoming requests, and forward them to Discourse and Apache as needed.

The nginx <-> Discourse part is handled through a socket and discussed in the howto above.

For the nginx <-> Apache part, you’re a bit on your own – if you need help, we need more details (i.e. where is Discourse running, where is the remainder of your website?).

1 Like

Thanks a lot, I definitly appreciate your advice!
I wish I could continue right now, but other duties demand to postpond this project to the weekend…
I hope to get back to this tomorrow evening and hopefully my next post will be about success :wink:

1 Like

Now I spent some more time on this. I thought it makes sense first to get discourse running on nginx and then worry about integration.

I got it working halfway, but there are more difficulties: creating my first user account (for the admin) leeds to an activation link that doesn’t work. It starts with “http://http://domain…” and if i copy the link cutting the first "“http://” it gets me to a discourse site “The page you requested doesn’t exist or is private”. The login doesn’t work telling me I need to activate the account first…

Also the starting page is not working as I expected. I don’t use subdomains (as, but instead (no idea how to call this). Is this a problem?

For the further part, after the basic setup is working I need to enable ssl and then I consider serving my other webservices (owncloud, dokuwiki and a very simple html website) also via nginx, as I figure it will probably be easier than negotiating between apache and nginx. Does that make sense?

1 Like

Uh, now it seems I can not get apache back online. This is a problem… :fearful:

Could rebuiding the discourse app cause this somehow? I did not touch any apache settings and while playing with this before rebuilding I could always stop ngingx and restart apache.

EDIT: I could solve this. nginx seems not to have terminated completely with “service nginx stop”, so apache could not start correctly, but after killing the nginx process it was all good. :relieved:

Yikes :open_mouth:, this is not good and looks like your nginx configuration is broken. Did you set up everything as shown in the tutorial, including the proxy_set_header directives?

This is fine if and only if you follow this howto:

Discourse needs to know it is running in a subfolder or all links will be broken; the tutorial above configures this.

If you follow the combination of this and the original howto, you should have a working Discourse as long as you stop Apache and start nginx for a moment. If this is not the case, can you post your nginx configuration files?

I’m not sure all of this works under nginx (as ownCloud needs PHP, which is not my forte). Setting up nginx to route requests to Apache should be relatively easy, I have a working setup using this apprach.

I made some progress today, now apache and nginx are both working at the same time :grinning:
For now, all my old services are available via ssl and nginx / discourse may have the http all for itself, as long as I am testing this is fine, I just need to get encryption working before inviting real people to register…
But I am stuck again rebuilding the app after configuring the subfolder support, rebuilding fails with:
(<unknown>): did not find expected key while parsing a block mapping at line 16 column 1 -e LANG=en_US.UTF-8 YAML syntax error. Please check your /var/discourse/containers/*.yml config files.
The block starting line 16 contains

  • “templates/postgres.template.yml”
  • “templates/redis.template.yml”
  • “templates/web.template.yml”
  • “templates/sshd.template.yml”
  • “templates/web.ratelimited.template.yml”
  • “templates/web.socketed.template.yml”where I needed to delete the line- “templates/web.ssl.template.yml”and add the line- “templates/web.socketed.template.yml”`

I pasted the code block into and it was accepted, also the content of the web.socketed.template.yml was accepted, I assume cecing the other files makes no sense, since they worked before and I didn’t change them…

Can you try linting the whole file? YML is really sensitive to minor errors like indentation errors, and can break in unexpected ways if the syntax is invalid.

Sure, I pasted it here:

For privacy reasons I changed following info to default

and deleted the mailsever infos (but that part worked during my first attempt without the right subfolder configuration)

Thanks for looking into it!

There seems to be missing a whitespace in the pasted code at the beginning of line 17.
I just thought that’s it, but it seems correct (two whitespace) in my local file…

That’s highly suspicious. Are you 100% certain that these are two spaces, not a single tab?

As sure as I can get, which would never be 100% though…

To confirm again, I edited the file with notepad++on my local machine, deleting the two whitespaces and the linebreak, hitting enter and adding two whitespaces manually. another copy to pastebin has the same result:

At last, I edited the file on the server the same way, using nano, copy from there to pastebin: same strange result:

Definitly highly suspicius, but I am out of ideas…

The last two lines of your file are not indented correctly, compared to the other parts of the run: section.


That was it! It works. Thank you so much!

The activation link still starts with “http://http://…”, could this be caused by discourse.conf in the nginx/conf.d? I copied it from the howto on Running other websites on the same machine as Discourse, only altering the server_name.

Or could this be caused by my nginx “sites-enabled”? The “location ~ .php$”-part ended up beeing a mix out of “How To Configure Nginx as a Reverse Proxy for Apache” (How To Configure Nginx as a Reverse Proxy for Apache | DigitalOcean) and “Running other websites on the same machine as Discourse” (Running other websites on the same machine as Discourse):

location ~ \.php$ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $host; 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; }

1 Like

Ah, I didn’t catch that before:


That’s wrong, you shoud only include the hostname itself, i.e.


That was easy. Thanks again :smiley:

It seems it is working great now, the last part is to enable ssl. As I see it, I need to

  1. change /etc/nginx/conf.d/discourse.conf as described in the howto on Running other websites on the same machine as Discourse.

  2. Put my ssl certificate files into /var/discourse/shared/standalone/ssl/ and change the file names according to the howto

  3. ? Is that it, or do I also need to make changes to nginx.conf and/or nginx/conf.d/discourse.conf?

My recommendation would be:

  1. Change your current server block to be the block for SSL.
  2. Make a new server block that redirects all HTTP requests to HTTPs.

For reference, here is such a redirect block:

server {
        listen 80;
        return 301 https://$host$request_uri;

Here’s how the SSL configuration could look like:

server {
        listen 443 ssl;

        ssl_certificate /etc/ssl/certs/cert.crt;
        ssl_trusted_certificate /etc/ssl/certs/cert.crt;
        ssl_certificate_key /etc/ssl/private/cert.key;

        ssl_ciphers "AES256+EECDH";
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;

        add_header Strict-Transport-Security "max-age=63072000;";
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        ssl_stapling on;
        ssl_stapling_verify on;

        client_max_body_size 20m;

        location / {
                proxy_pass http://unix:/var/discourse/shared/vorkurs/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_redirect;

Watch out: My example enables HSTS. If your site goes live with this configuration, visitors that have seen it will refuse to use http for up to 2 years.

1 Like

Ok, your last warning made me rather try the SSL config from the howto on running other websites on the same machine as Discourse.

I have a partial success: when I enter the old http domain, it routes me to the https site and shows the correct certificate. But there is no discourse, only a bad gateway (502).

Also, I had to stop apache2 for enabling the new nginx config, probably because apache2 was still listening on port 443. So now I assume I have to change the port in the in the apache config that listens to SSL to another port, to which nginx needs to forward requests to subfolders it cannot find. How do I configure nginx to do this?

EDIT: Reading through the SSL tutorial again reminded me I needed to add the “templates/web.ssl.template.yml” which I deleted before. Rebuilding took for ever, because “Generating DH parameters” - but in the end, still the same result (bad gateway). I bet I missed to enable SSL in some config file…

You don’t actually needed that, as you want the outer nginx to handle SSL, not Discourse’s internal nginx instance.

If my HSTS remark scared you off, you can just comment out the line that sets Strict-Transport-Security or decrease the number there to a low number of seconds.

Ah, I see. I will try with your config and “add_header Strict-Transport-Security “max-age=60;”;” then. Restarting nginx gave me complaints about the cert now, so I am rebuilding the app again without the web.ssl.template.yml. Another 6 long minutes…

Is it correct for the same reason I do not need to expose port 443 within the app.yml, because all the port handeling happens outside of the container, or could there be an error? I deleted the lines "expose: - “80:80"” "expose: - “443:443"” and and added “templates/web.socketed.template.yml” instead (as explained in the howto on running other websites on the same machine as Discourse).