Running Discourse at / while serving a custom app at /tickets on the same domain

Hi everyone,

I’m trying to confirm the correct architecture for serving a custom application at a sub‑path while keeping Discourse at the root (/), without modifying Discourse internals.

What I want (final goal)

https://mydomain.com/         → Discourse
https://mydomain.com/tickets  → Custom ticket system (Go + Gin)

Requirements:

  1. Discourse must remain at / must live at /tickets
  2. Same domain
  3. No Discourse plugin

Current environment

  1. OVH VPS (Ubuntu)Discourse running in Docker (/var/discourse)
  2. Custom Go app running on the same server at 127.0.0.1:8080
  3. External nginx installed on the host (not inside the container)

I am NOT trying to run Discourse in a subfolder like /forum. Oh and before somone asks yes I have tried to use the Discourse tickets plugin - does not work like I want it to.

You can do it easily with nginx, while it is not recommended, I am not aware of discourse using /tickets route for anything.

Thanks for the quick reply! I am using nginx and struggling. This is my configuration and still no luck.

This is inside my app.yml file

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

/etc/nginx/sites-enabled/filename

server {
    listen 80;
    server_name mydomain.com;

    # ---- Tickets app ----
    location ^~ /tickets {
        proxy_pass http://127.0.0.1:5000;
        proxy_http_version 1.1;
        proxy_redirect off;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Discourse auth headers
        proxy_set_header X-Discourse-Username $http_x_discourse_username;
        proxy_set_header X-Discourse-User-Id $http_x_discourse_user_id;
        proxy_set_header X-Discourse-Groups $http_x_discourse_groups;
    }

    # ---- Discourse ----
    location / {
        proxy_pass http://127.0.0.1:4000;
        proxy_http_version 1.1;
        proxy_redirect off;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Can you elaborate exactly where you are struggling?

2 Likes

I think those are probably your best instructions, though. You’ll follow those instructions, but sort-of backward. You’ll have your external reverse proxy serve / to Discourse and /tickets to your app.

@pfaffman So what I’m taking away is: reuse the concept, not the configuration — put an external reverse proxy in front that routes:

  • / → Discourse

  • /tickets → my custom app

Discourse remains unaware of /tickets entirely.
So look at this, right: Serve Discourse from a subfolder (path prefix) instead of a subdomain

1 Like

I think the external nginx is the easiest way to do it. It would be possible to make a template that allowed the internal one to to it, but it’s more complicated and, I think, for little gain.

Yeah, but you don’t need to make any changes to the discourse container other than removing the ssl/let’s encrypt templates and maybe using a socket. (So, really, not much in that topic is of much help.)

I have got it working!

Thank you both for your replies!

“Tickets” link I added to the Discourse header works as well, when set to blank NOT self, as /tickets is then treated as a Discourse route instead and tries to just swap the react view. Blank forces a full page reload.