Last chance for "subfolder support"

(Staticinvocation) #1

I run a pretty large forum, with over 3000 active users and, according to Google Analytics, about 40 on the site in real-time. We’ve also been users of Discourse for over a year now, and I’ve been supporting the project for over 2 years. But now I’m about to give up on it.

I have been trying for longer than I’d like to admit to get subfolder support working. I’ve rebuilt the containers countless times and nuked the site entirely twice to try to get it to work properly. The biggest problems we face with this configuration is that uploads simply don’t work. uploads.json returns 404 and we cannot upload any files. Also, youtube videos would break when we linked to them. There are absolutely no error logs for either of these issues.

I’ve seen the Sitepoint forum and their setup is exactly what we need and yet after countless hours we can’t get the configuration just right. This has been a real frustrating experience seeing another community achieve the exact results I’ve been trying to get for about 6 months.

So if you’re running a site in this kind of configuration… I would absolutely love it if you could share your “secret sauce” to getting it working.


  • Uploads & youtube completely broken on “subfolder” configuration
  • Other communities do it just fine apparently

Sorry if this post sounded dramatic, but I really do love this software but these issues are a real show-stopper.


(Jeff Atwood) #2

Weird – we have multiple hosted enterprise customers on subfolder with no issues. So I know it works, otherwise several enterprise customers would not be paying us money :upside_down:

There is a reason we only offer subfolder on enterprise hosting plans, though. It’s significantly more complex.


(Staticinvocation) #3

I will throw money at you if you can get it working & we can host it.


(cpradio) #4

I just sent an invite to @Falco because I know he did a lot of testing of a sub-folder install early on, he might be able to provide assistance too.


(Rafael dos Santos Silva) #5

Hey, thanks for the invite @cpradio.

Discourse runs pretty well nowadays on subfolder, there are still very minor bugs, but more and more are fixed everyday.

I can guarantee, uploads and oneboxing work fine if you just follow the subfolder guide.


(Matt Palmer) #6

As @codinghorror said, it’s complicated. That being said, there’s absolutely no “secret sauce” we’re holding back for our own customers – I’ve just looked at the config we use for sitepoint, and all the relevant parts of their config are substantively identical to what @neil put into the subfolder support topic.

Given the symptoms you’re describing, it feels to me most likely that you’re missing the symlinking of public/subfolder/uploads to public/uploads, but without seeing your entire config, relevant logs, and how the site is (mis)behaving in the real world, we’re all going to be guessing blindly as to what exactly is going wrong.

It would also be helpful to know how the requests are getting to the app: are you proxying from another system entirely, or do you have all requests going to one (say) nginx or apache server, and that is sending requests for /subfolder to discourse directly, and sending all other requests to some other app server?

It could also very well be a bug in the configuration of whatever is doing the proxying (especially if you’ve got multiple layers of proxy going on). From experience, I can say that it’s all too easy to mangle a request path in an unexpected way and send entirely the wrong request to a backend. It’d be handy to see request/response captures at each link in the proxying chain, to try and identify those kinds of problems.


(Staticinvocation) #8

Thanks everyone for your considerations.

We’re running behind Varnish cache, and use it for all of our routing.

We do something like this:

        if(req.url ~ "^/forum" || req.url ~ "^/admin" || req.url ~ "^/message-bus" || req.url ~ "^/sidekiq" || req.url ~ "^/user_avatar") {
            set req.backend_hint = forum;

Our full config is as follows:

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

    ## which TCP/IP ports should this container expose?
      - "8002:80"   # fwd host port 80   to container port 80 (http)
      db_default_text_search_config: "pg_catalog.english"
      ## Set db_shared_buffers to 1/3 of the memory you wish to allocate to postgres
      ## on 1GB install set to 128MB on a 4GB instance you may raise to 1GB
      db_shared_buffers: "2048MB"
      ## Which Git revision should this container use? (default: tests-passed)
      version: stable

      #version: v1.3.4

      LANG: en_US.UTF-8

      ## TODO: How many concurrent web requests are supported?
      ## With 2GB we recommend 3-4 workers, with 1GB only 2

      ## TODO: List of comma delimited emails that will be made admin and developer
      ## on initial signup example ','

      ## TODO: The domain name this Discourse instance will respond to

      ## TODO: The mailserver this Discourse instance will use
      DISCOURSE_SMTP_ADDRESS:         # (mandatory)
      #DISCOURSE_SMTP_PORT: 587                        # (optional)
      DISCOURSE_SMTP_USER_NAME: redacted      # (optional)
      DISCOURSE_SMTP_PASSWORD: redacted               # (optional)
      #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (optional, default true)

      ## The CDN address for this Discourse instance (configured to pull)


    ## These containers are stateless, all data is stored in /shared
      - volume:
          host: /var/docker-discourse/shared/standalone
          guest: /shared
      - volume:
          host: /var/docker-discourse/shared/standalone/log/var-log
          guest: /var/log

    ## The docker manager plugin allows you to one-click upgrade Discourse
        - exec:
            cd: $home/plugins
              - mkdir -p plugins
              - git clone
    #          - git clone
    #          - git clone

        - exec:
            cd: $home
              - mkdir -p public/forum
              - cd public/forum && ln -s ../uploads && ln -s ../backups
              - rm public/uploads
              - rm public/backups
        - replace:
           global: true
           filename: /etc/nginx/conf.d/discourse.conf
           from: proxy_pass http://discourse;
           to: |
              rewrite ^/(.*)$ /forum/$1 break;
              proxy_pass http://discourse;
        - replace:
           filename: /etc/nginx/conf.d/discourse.conf
           from: etag off;
           to: |
              etag off;
              location /forum {
                 rewrite ^/forum/?(.*)$ /$1;
        - replace:
             filename: /etc/nginx/conf.d/discourse.conf
             from: $proxy_add_x_forwarded_for
             to: $http_x_platinum_ip
             global: true

Emails & other sensitive details have been redacted. You’ll also notice that our config is very similar to that given in the howto thread.


(Rafael dos Santos Silva) #9

Did you try without the varnish?

I use subfolder, but on my setup there is a nginx in front of everything.


(Staticinvocation) #10

What does your nginx config look like?


(Matt Palmer) #11

What do the requests look like (particularly for failed uploads and such) at each stage of the proxying pipeline?


(Rafael dos Santos Silva) #12

It’s at my work, and I’m at my vacation now.

But from memory it’s a pretty standard proxy_pass nginx block.

    location ~ ^/forum {
        proxy_pass http://discourse:8000/forum;
        proxy_set_header    Host            $host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-for $remote_addr;
1 Like

(Staticinvocation) #13

I’m going to play around with Varnish on a development server and report back.


(system) automatically bumped #14

(Jeff Atwood) #17

Did you ever get this working? Subfolder is still quite complicated, but it does work and we fix any edge conditions we find, which are usually minor based on pathing URLs in various places.