Discourse: a self-hosted forum in Rails and Ember, and what the install actually requires
GitHub describes it as A platform for community discussion. Free, open, simple.. The repository metadata lists Ruby as its primary language. The metadata lists the GPL-2.0 license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- Discourse is a GPL-2.0 community forum you run yourself, written as a Ruby on Rails API with an Ember.js front end, on PostgreSQL and Redis. The install is well documented, but it asks for four moving parts and a toolchain on both Ruby and Node.
- Who is it for?
- Discourse suits an organisation willing to operate PostgreSQL, Redis and a Rails app in Ruby 3.4+, and it does not suit a team whose users sit on browsers older than the latest stable release, since that is the only support statement on offer. Verify first, on a throwaway machine, by following the Ubuntu/Debian setup guide and confirming your image actually ships Ruby 3.4+, PostgreSQL 15 and Redis 7 rather than the versions its distribution defaults to.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A Rails JSON API, an Ember front end, and the seam between them
Discourse is two applications meeting at a documented boundary. The back end is a Ruby on Rails app that responds to requests RESTfully in JSON. The front end is an Ember.js app that talks to that API and nothing else. That split is the first thing to understand about the codebase, because it decides where your own code has to live.
Server-side work, permissions, rendering of anything the browser must trust, and data access go in Ruby. Anything interactive goes in Ember, which the repository carries under frontend/ alongside app/, lib/, config/ and db/. A plugin is therefore a two-language artifact, not a PHP-style drop-in file: the Data Explorer plugin, which the project describes as advanced tools like SQL analysis, is one of the named examples, alongside the chatbots powered by Discourse AI. If your team writes Ruby but no JavaScript, the front end is the part of the work you will have to buy or borrow.
Ruby 3.4+, PostgreSQL 15 and Redis 7 as the floor
The minimum versions are stated before anything else: Ruby 3.4+, PostgreSQL 15 and Redis 7. PostgreSQL is the main data store, so it holds your users, topics and posts. Redis is described as a cache and for transient data, which is a narrower job than a cache usually implies and matters when you are sizing or backing up a server.
Here is the failure mode to plan for. A stock Ubuntu or Debian image in 2026 will not necessarily give you any of those three numbers, and the README does not document a supported path for running on an older database or an older Ruby. The requirement is a check, not a preference, so an image built a year ago fails at setup rather than degrading at runtime. Plan the container or the VM from the required versions upward, not from the base image you already have. Note also that Postgres and Redis are not optional extras: the platform stores threads in Postgres and needs Redis present, so a single-VM install is really a four-service install once Rails, Postgres and Redis are counted.
Five setup paths, and only one of them is the production answer
Development environments are documented five ways: Docker through a Dev Container in VS Code, which is the recommended route, or the Docker CLI; then macOS, Ubuntu/Debian, and Windows. Each is a separate guide on the project's meta site. For production there is a different document entirely, the Discourse Install Guide at docs/INSTALL.md, and the repository keeps that file in its docs/ directory.
The development entry point is a script the JavaScript side wires up. In package.json, which is marked private and carries the GPL-2.0-only license field, the dev script is:
"scripts": {
"dev": "bin/dev"
}The practical difference between the dev container and the Ubuntu guide is who owns the database lifecycle. A dev container hands you a working stack; a bare-metal guide leaves PostgreSQL and Redis as yours to install, configure, upgrade and back up. If you are evaluating this platform, that gap is the evaluation: the same forum costs very different amounts of work depending on whether the container is your deployment target or only your laptop.
A plugin is linted by the core frontend commands
Plugins live in a top-level plugins/ directory, and the repository's own tooling reaches into them. The lint task fans out across every lint script at once, and the JavaScript task covers the front end, whatever script/list_bundled_plugins returns, and themes, configured so that a single warning fails the run:
"lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"",
"lint:js": "eslint ./frontend $(script/list_bundled_plugins) ./themes --cache --concurrency auto --no-error-on-unmatched-pattern --max-warnings 0"What that means for a third-party plugin author is specific rather than general: your code is not shipped outside the checks the core project runs on itself, and a single warning fails the task. The root also carries themes/ targets, so a theme is linted by the same commands. The cost is that a plugin author inherits the core project's formatting and lint expectations without a separate configuration of their own.
Ruby and Node in the same checkout, plus hooks and a licence check
Open the root and the toolchain bill arrives all at once. The Ruby side is Gemfile, Gemfile.lock, Rakefile, config.ru, .rspec and .rspec_parallel, .rubocop.yml and .annotaterb.yml, and a Brewfile for macOS dependencies. The JavaScript side is package.json, pnpm-lock.yaml and pnpm-workspace.yaml, eslint.config.mjs, .prettierrc.cjs, .prettierignore and .jsdoc. Beside them sit lefthook.yml for git hooks, .editorconfig, .gitattributes, .git-blame-ignore-revs, and .licensed.yml with .licensee.json for licence detection.
A contributor therefore needs a Ruby toolchain and a Node toolchain, and a working lefthook setup, before the first pull request is realistic. The presets are unusually specific: @discourse/lint-configs is a shared package, stylelint and prettier and eslint all run through concurrently, and typescript is pinned at ^6.0.3 with @glint/ember-tsc providing type checking for the Ember side. For a team that already standardises on this stack that is an advantage. For a team that does not, it is an onboarding cost that has nothing to do with running a forum.
Contributing starts with a signature, not a branch
The contribution path has a legal gate in front of the code. Before contributing, the project asks you to read the complete mission statements on discourse.org, then read and sign the Electronic Discourse Forums Contribution License Agreement, then read CONTRIBUTING.md, which covers submitting bugs, requesting features and preparing code for a pull request. A code of conduct document is linked from the same numbered list.
For an outside company this is the item most likely to slow a fork down, and it is not optional in the instructions as written. Signed CLA, then bugs and feature requests through the documented process, then a pull request. CODEOWNERS sits at the repository root next to CONTRIBUTING.md, so review routing is declared in the tree rather than left to whoever reads the request first.
The practical consequence for an evaluator: if you plan to carry a private modification of Discourse, the CLA covers contributions you send upstream, and it is a different question, which the project does not answer here, what your obligations are for a fork you never submit. Ask that question before you build a roadmap on the assumption that internal divergence is frictionless.
Security fixes are announced in release notes, not in the tag list
Because every line of code is public and the project says so plainly, the security posture of a given install is legible to anyone running it. Reporting a problem goes to the security guide in docs/SECURITY.md, which covers both the measures in place and how to report an issue. Fixed issues are announced in the release notes for each version.
That last point has a practical edge. The recent tag list for this repository shows a single entry, an internal asset attachment tag named _gh-attach-assets dated 2026-07-15, rather than a series of numbered version tags. So the tags view is not a place to look up which build fixed a given advisory, and the project directs you to the release notes instead. If you run Discourse, put a subscription to releases.discourse.org into your upgrade process, because that is the channel the README names. An install that upgrades by watching the repository will not see the signal it needs.
Self-hosting or official hosting, and who carries the pager
The project states the fork in its own terms: you can self-host on your own infrastructure, and if you would rather skip setup, maintenance and server management, official hosting is offered. Those three words are the whole cost model. Setup is the five guides and docs/INSTALL.md. Maintenance is upgrading Ruby, PostgreSQL and Redis underneath a running forum while people post in it. Server management is everything after that.
Choose by asking which of the three your team already has. An organisation with PostgreSQL and Redis in production, Ruby release engineering, and someone who owns uptime already has the expensive parts, and self-hosting is the cheaper path. An organisation that wants a community forum and has no platform team will spend more than the hosting price on the first upgrade, and the README does not offer a managed upgrade path for a self-run install. The plugins are the same either way, since the Data Explorer and Discourse AI examples are named regardless of who runs the server.
One more boundary worth noting: support is stated for the latest stable releases of Safari, Chrome, Edge and Firefox, with an aim to support Safari on iOS 16.4+, and no fallback is documented for anything older. A reader on a locked device fleet is outside what the project claims to support.
Editorial conclusion
Discourse suits an organisation willing to operate PostgreSQL, Redis and a Rails app in Ruby 3.4+, and it does not suit a team whose users sit on browsers older than the latest stable release, since that is the only support statement on offer. Verify first, on a throwaway machine, by following the Ubuntu/Debian setup guide and confirming your image actually ships Ruby 3.4+, PostgreSQL 15 and Redis 7 rather than the versions its distribution defaults to.
Frequently asked questions
how to install Discourse
Five development setup guides are given: Docker through a Dev Container in VS Code, which is recommended, or the Docker CLI, plus macOS, Ubuntu/Debian and Windows. For production, the project points to the Discourse Install Guide at docs/INSTALL.md. Minimum versions are Ruby 3.4+, PostgreSQL 15 and Redis 7.
How do I install Discourse on Ubuntu?
There is a dedicated Ubuntu/Debian setup guide, and the Docker route is offered as an alternative with either a VS Code Dev Container or a CLI. The README states the version requirements but does not spell out the package installation commands, so the guide on the meta site carries the actual steps.
How do I set up a Discourse development environment?
Pick one of the setup guides for Docker, macOS, Ubuntu/Debian or Windows, install the minimum versions, then run the dev script wired up in package.json, which invokes bin/dev. Further developer documentation lives in the Developer Documentation section on meta.discourse.org.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/discourse-discourse)