Installing Discourse Behind Reverse Proxy using recommended (supported) installation

In this post, I will show you exactly how to run discourse behind a nginx reverse proxy. While still using the supported installation methods.

Requirements:

  1. Valid domain name.
  2. Valid ssl certificate.
  3. Valid DNS entries pointing to the domain name.
  4. Valid working email server or smtp provider.
  5. Working Nginx Reverse Proxy and ability to reach the instance and create the SSL cert for later use.
  6. VM or LxC container that can run docker.

For this guide I will be using my own instance as an example, with all features working, backups, upgrading etc. Tested for around 2 weeks.

My Discourse VM Specs:

  • CPU: 4 Cores
  • Ram: 6GB
  • Swap: 8GB (SSD swapfile)
  • Storage: 50GB (SSD)
  • OS: Ubuntu 22.04.3

You can use the minimum but when testing. Discourse basically abuses 2GB easily. Inactive usage is about 1.48GB of 6GB.

NOTE: This install uses the reverse proxy to create the ssl certificates. certbot can be used if preferred.

STEP 1:

Download the latest ubuntu server from https://ubuntu.com/download/server

STEP. 2:

  1. Install Ubuntu sever on the VM/LxC template
    1.1 Make sure ubuntu is up-to-date with all server packages.
  2. Use the following commands to install all required packages:
apt update -y && apt upgrade -y && apt wget curl zip git docker.io nginx -y && reboot

STEP 3:
Installing Discourse. Following the Beginner Guide discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub

ssh into your server and simply enter the following:

sudo -s
git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
chmod 700 containers

After completing the above. You can then run the ./discourse-setup

Follow all the steps and enter them correctly, As this would be vital for a successful install.
The steps would ask the following; example from the setup guide:

Let the install run it may take a while depending on your internet connection and sever specs. It took around 5-8 minutes to fully complete the install using my VM setup.

STEP 4:

Once the installation has completed you will then see the start command that the docker container is using and the generated container ID (hash).

NOTE: Since you are behind a proxy via the WAN it would show you a 502 error and since the container is using dockers network. It will be unreachable by the WAN or LAN, unless you connect to the 172.17.0.1/16 network, which we will not be needing.

Double check that the installation has completed and the docker container is running using:

docker ps

You should get the following output.

CONTAINER ID   IMAGE                 COMMAND        CREATED      STATUS       PORTS     NAMES
XXXXXX   local_discourse/app   "/sbin/boot"   6 days ago   Up 7 hours             app

STEP 5:
Updating the app.yml file to fit the reverse proxy configuration.

Using your preferred text editor open /var/discourse/container/app.yml
Replace/Comment out the following lines: (this will be handled by the local Nginx)

  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

Immediately after the #- "templates/web.letsencrypt.ssl.template.yml" add the following:

- "templates/web.socketed.template.yml"

Then comment out the expose section as discourse will now be using a websocket, finally nginx would be able to start as it would free up the required 80 & 443 ports locally.

#expose:
# - "80:80" # http
# - "443:443" # https

Now to force Discourse to only supply links with HTTPS add the following in the env section:

# FORCE SSL 
DISCOURSE_FORCE_HTTPS: true

Now to finally get things going you will need to rebuild the app. Using the following:

cd /var/discourse
./launcher rebuild app

Let that run and complete. To check if it was successful make sure the docker run command is showing or simply run docker ps and you will see the container running.

STEP 6:

Enabling Nginx and configuring the default site to point to the docker container. Allowing the Reverse proxy to the access the container using the local nginx.

Run the following:

systemctl enable nginx && systemctl start nginx

To check if it is running. Try to access the default landing page for nginx using your browser and local ip.
EG:

http://10.10.0.4

You should get a congratulations page from Nginx.

STEP 7:
Updating the default config to the following:
First empty out the config file:

echo "" > /etc/nginx/sites-available/default

Using your text editor open the config file and add the following:
NOTE: Update server_name with your domain and ssl_certificate, ssl_certificate_key with your SSL certificate and keyfile location.
Certbot can be used but i simply rsync my cert and key from my reverse proxy.

server {
    listen 80; listen [::]:80;
    server_name add.yourdomain.com;
    server_tokens off;
    return 301 https://$host$request_uri;
}
# Default server configuration
#
server {
	# SSL configuration
	#
	server_tokens off;
	listen 443 ssl default_server;
	listen [::]:443 ssl default_server;

    server_name add.yourdomain.com;
	ssl_certificate /etc/ssl/certs/your_ssl_cert.bundle;
	ssl_certificate_key /etc/ssl/private/your_ssl_cert.key;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	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-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
	ssl_prefer_server_ciphers on;
	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;
		proxy_set_header X-Real-IP $remote_addr;
	}
}

Save the new default file and run systemctl restart nginx.

STEP 8:

Open up your browser and goto your forum domain https://somedomain.com and you will be greeted with the following page.

That’s it, all done. You can then follow the steps to register and get you forum/community going :).

ADDITIONAL STEP:

Post-Install Maintenance
We strongly suggest you turn on automatic security updates for your OS. In Ubuntu use the dpkg-reconfigure -plow unattended-upgrades

For support you can simply use this community, for the local Nginx you can feel free to ask for assistance on this post.

8 Likes

This is great. Thank you.

One thing I would like to see as an improvement to this guide is being able to serve static assets via nginx.

Currently, all the static requests are going to the worker in the above configuration. I am still trying to figure out how to work-around this, will post an update if i figure it out.

Can you expand on what static files ?

Are you perhaps talking about the 404, 302,500 static pages from nginx or static pages from Discourse?

I looked into it for a bit and found that the redirect for the 404 pages work. The only page i cannot seem to set it the 500 error page.

Can you be a little bit more specific so that i know exactly what i am looking into. :slight_smile: