Discourse delivering blank web pages on Ubuntu 14 on Linode


I’ve installed Discourse and Docker as per the instructions on GitHub.

My setup is Ubuntu 14 LTS at Linode. This machine delivers a bunch of PHP+MySQL websites via Apache on port 80, hence I’ve set up Apache at subdomain.host.com on port 8080 to connect to Discourse running on container port 3000.

See my previous post for the gory details on how I got that running:

I’ve added a proxy directive to Apache to pass all traffic on subdomain.host.com:80 to subdomain.host.com:8080 so that users can simply type subdomain.host.com into the browser without needing the :8080 bit:

<VirtualHost subdomain.host.com:80>
    ServerName subdomain.host.com
    ServerAlias subdomain.host.com

    DocumentRoot /home/host/subdomain.host.com

    <IfModule mod_pagespeed.c>
        ModPagespeed off # Disabling this to make debugging simpler.

    <IfModule mod_proxy.c>
        ProxyPass        /       http://localhost:8080/
        ProxyPassReverse /       http://localhost:8080/
        ProxyPassMatch   ^/(.*)$ http://localhost:8080/$1

    LogLevel Debug
    ErrorLog /home/host/subdomain.host.com/log/error.log
    CustomLog /home/host/subdomain.host.com/log/access.log combined

However now when I point a browser to subdomain.host.com I am faced with a blank screen. Literally nothing in browser. Or so it appears. If I view source, I can see what appears to be a successfully delivered web page. So why is there nothing in the browser?

Looking through the source, I’ve tried to follow all the links in the HTML source to see if my server is delivering them, for example this lot:

<script src="/assets/preload_store-8d9173c7fdb49e0fc758a572fc829b20.js"></script>
<script src="/assets/locales/en-54e7e7ca87a0948886f81429f53da979.js"></script>
<script src="/assets/vendor-68a043ffb30ca8b0ef68bf301d9c2efb.js"></script>
<script src="/assets/application-79a710ee3ddb255d335596d4c815ffcc.js"></script>

Oh dear, they are all 404:

root@www:~# curl -I 'http://subdomain.host.com/assets/preload_store-8d9173c7fdb49e0fc758a572fc829b20.js'
HTTP/1.1 404 Not Found
Date: Wed, 01 Jul 2015 09:13:40 GMT
Server: Apache/2.4.7 (Ubuntu)
Status: 404 Not Found
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Discourse-Route: exceptions/not_found
Content-Type: text/html; charset=utf-8
X-Runtime: 0.043835

That can’t be good. Same goes for CSS, images, everything. This must be why the page is blank.

I suspect this is a problem with the Apache VirtualHost proxy config above, I’ll tinker with it. However the log files are uninformative: no errors, just mod_proxy reporting success (initialising; granting auth; running scheme http handler; acquiring connection; connecting; completing; releasing connection).

I’m hoping this isn’t anything more gnarly than the Apache config. Hunting around, apparently Docker has problems with certain storage drivers:

So here’s my docker info:

root@www:~# docker info
Containers: 1
Images: 27
Storage Driver: overlay
 Backing Filesystem: extfs
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 4.1.0-x86_64-linode59
Operating System: Ubuntu 14.04.2 LTS
CPUs: 2
Total Memory: 1.945 GiB
Name: www
Username: me
Registry: https://index.docker.io/v1/
WARNING: No swap limit support

If anyone has any pointers, I’d appreciate it.

Many thanks.

Discourse doesn't deliver webpages, fresh install on Linode Ubuntu 14.04

For completeness, according to this page at Linode.com, Docker shouldn’t have a problem with the lack of AUFS in Ubuntu. So I’m going to continue looking at the Apache config as the source of the problem. I also don’t get get any warnings about AUFS when starting Discourse:

root@my-linode:/var/discourse# ./launcher restart app
+ /usr/bin/docker stop -t 10 app

starting up existing container
+ /usr/bin/docker start app

Apparently it is possible to use a custom kernel at Linode to provide AUFS:

That’s probably (definitely) beyond me for now.


So it looks like rails isn’t delivering static content at all.

Short version: I’ve configured rails to deliver static content and it is now served up, but I have 502 proxy errors in the browser, which presumably means there’s an outstanding problem with the Apache config. However it seems that Discourse may be “working”, I just can’t get to it :confused:

Long version:

From the HTML source, I picked an image as a test case:

root@my-linode:/var/discourse# ./launcher enter app
root@www-app:/# curl -I http://localhost:3000/images/d-logo-sketch.png
HTTP/1.1 404 Not Found
Date: Wed, 01 Jul 2015 09:45:07 GMT
Status: 404 Not Found
Connection: close
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Discourse-Route: exceptions/not_found
Content-Type: text/html; charset=utf-8
X-Request-Id: ...
X-Runtime: 0.057383

All similarly “missing” files exist in the container in /var/www/discourse/public/assets. Looking at error logs, rails was complaining:

me@my-linode:~$ tail /var/discourse/shared/standalone/log/rails/production.log

Started HEAD "/images/d-logo-sketch.png" for at 2015-07-01 10:09:11 +0000

ActionController::RoutingError (No route matches [HEAD] "/images/d-logo-sketch.png"):
  config/initializers/quiet_logger.rb:10:in `call_with_quiet_assets'
  config/initializers/silence_logger.rb:26:in `call'
  lib/middleware/request_tracker.rb:70:in `call'
  lib/scheduler/defer.rb:85:in `process_client'
  lib/middleware/unicorn_oobgc.rb:95:in `process_client'

Processing by ExceptionsController#not_found as */*
  Rendered exceptions/not_found.html.erb within layouts/no_ember (12.4ms)
  Rendered layouts/_head.html.erb (0.1ms)
  Rendered common/_special_font_face.html.erb (0.3ms)
  Rendered common/_discourse_stylesheet.html.erb (0.2ms)
  Rendered application/_header.html.erb (0.1ms)
  Rendered text template (0.0ms)
Completed 404 Not Found in 19ms (Views: 0.4ms | ActiveRecord: 8.4ms)

In the config file /var/www/discourse/config/discourse_defaults.conf I noticed this:

# enable if you really need to serve assets in prd
serve_static_assets = false

So I set that to true and relaunched Discourse.

The content is now being served, if I enter the container and request it locally:

me@my-linode:/var/discourse$ ./launcher enter app
root@www-app:/# curl -I http://localhost:3000/images/d-logo-sketch.png
HTTP/1.1 200 OK
Date: Wed, 01 Jul 2015 10:37:49 GMT
Status: 200 OK
Connection: close
Last-Modified: Tue, 30 Jun 2015 17:09:26 GMT
Content-Type: image/png
Content-Length: 15031

However I am getting 502 proxy errors if I go to subdomain.host.com in my web browser, so I’m going to look at Apache to see if the problem is with the proxying.

Is there any reason that setting serve_static_assets = true is a bad idea? If this is a performance issue I can probably handle it, the site is likely to be very low traffic – tens of people per day. If there’s a preferred mechanism whereby static content is served by something other than rails, feel free to inform me :smiley: It seems likely that I’m overlooking something in Nginx but I don’t know what.

(Sam Saffron) #4

Sure, plenty, no idea why you would enable that our docker install is smart about serving all static files from nginx, if you start bypassing it then odds are you are going to hit some severe perf issues if you don’t know what you are doing.

You should be proxying NGINX (port 80 in the container) not port 3000 which is the web.


I thought as much.

Port 80 isn’t working for me… as above, all static content is failing to be served:

me@my-linode:/var/discourse$ ./launcher enter app
root@www-app:/# service nginx status
 * nginx is running
root@www-app:/# curl -I http://localhost:80/images/d-logo-sketch.png
curl: (7) Failed to connect to localhost port 80: Connection refused
root@www-app:/# ls -l /var/log/nginx/*.log
-rw-r--r-- 1 www-data www-data 0 Jun 30 10:12 /var/log/nginx/access.log
-rw-r----- 1 www-data www-data 0 Jul  1 09:28 /var/log/nginx/error.log

Since /etc/nginx/conf.d/discourse.conf says

server {
  access_log /var/log/nginx/access.log log_discourse;
  listen unix:/shared/nginx.http.sock;

…I suspect this is related to my previous issues with that socket file.

(Sam Saffron) #6

Yeah, I will fix that template up today, its not nuking the old socket file on startup. Though … why are you even using the socket style?

(Jeff Atwood) #7

@riking already fixed the template so it deletes the old socket file.

(Sam Saffron) #8

Not really, but I just fixed it


@riking can you please test?


No idea. It’s an out-of-the-box installation, I didn’t configure it to do anything unusual.

Time to re-install, perhaps.


I’ve just upgraded (using the web-based upgrade) and noticed that /etc/nginx/conf.d/discourse.conf uses the socket style by default. Is that not meant to be the case?

Sure enough:

me@my-linode:/var/discourse# ./launcher enter app
root@www-app:/# curl -I http://localhost:80/
curl: (7) Failed to connect to localhost port 80: Connection refused
root@www-app:/# service nginx status
 * nginx is running

So I edited /etc/nginx/conf.d/discourse.conf to get Nginx listening on container port 80 instead of the socket file. Note that it was listening on the socket file by default, fresh from upgrade:

server {
  access_log /var/log/nginx/access.log log_discourse;
  # listen unix:/shared/nginx.http.sock;
  listen 80;

…and bingo:

root@www-app:/# service nginx restart
* Restarting nginx nginx 
root@www-app:/# curl -I http://localhost:80/
HTTP/1.1 302 Found
Server: nginx


After the upgrade /var/www/discourse/config/discourse_defaults.conf was happily back to using rails only for dynamic content and Nginx for static:

# enable if you really need to serve assets in prd
serve_static_assets = false

So what’s going on here? Is Discourse meant to be listening on that socket file out-of-the-box after a fresh upgrade?

(Kane York) #11

No, because web.socketed.template.yml is, notably, missing from samples/standalone.yml:


Aha. My app.yml does indeed refer to web.socketed.template.yml:

  - "templates/cron.template.yml"
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/sshd.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.socketed.template.yml"

I suspect because I (mistakenly?) followed instructions here:

Thanks for the help, all seems resolved now. Very pleased :smile: