CLI tool
discuitnet/discuit avatar
discuitnet/discuit

Discuit: a self-hosted Reddit alternative built on Go, React, MariaDB and Redis

A free and open-source community discussion platform.

551 stars77 forksTypeScriptAGPL-3.0

At a glance

What is it?
Discuit is the open-source codebase behind discuit.org, a community discussion platform that positions itself as an alternative to Reddit. The backend is Go, the frontend is React, MariaDB holds the data and Redis holds transient state, and the project ships three ways to run it: a local build, a Docker image with separate architecture Dockerfiles, and a Nix flake that provisions the databases for you.
Who is it for?
Discuit fits an organisation or individual who wants a community platform with no platform dependency, a real REST API, and a database schema they own, and who is prepared to run MariaDB and Redis as well as the Go binary. It does not fit anyone who needs search, server side rendering, private messaging or an RSS feed today, because the project roadmap lists all four as unfinished, and it does not suit a commercial hosted service without reading the AGPL-3.0 terms carefully.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Discuit is and the stack behind discuit.org

Discuit is the codebase that powers discuit.org, which is described as an open-source community platform and an alternative to Reddit. The technology choices are listed directly: Go for the backend, React for the frontend, MariaDB as the main datastore, and Redis for transient data.

That split of responsibilities is the one architectural decision worth understanding. Anything durable goes to MariaDB, and the SQL migration files live in a `migrations` directory, which means the schema is versioned and applied by a migration runner rather than by hand. Anything short-lived goes to Redis, and the Go dependency list confirms the client is redigo rather than a wrapper around a different protocol. A community platform has a lot of transient state: sessions, rate limit counters, cached feeds. Keeping it out of the relational database keeps the write path of posting a comment to a small set of tables.

The source tree divides into `cli` for the command-line interface, `core` for the core backend functionality, `internal` for Go packages private to the project, `migrations` for the SQL files, `server` for the REST API, and `ui` for the React frontend. The REST API and the frontend are separate directories with their own concerns, and the API documentation is published separately at docs.discuit.org.

The go.mod file shows the module path is github.com/discuitnet/discuit, with Go 1.21 as the language version. The direct dependencies include gorilla/mux for HTTP routing, golang-migrate for the migration files, the MySQL driver, redigo for Redis, yaml.v2 for configuration, and two image libraries, h2non/bimg and golang.org/x/image, which line up with the image posting feature.

The repository publishes no GitHub releases, so the version you get is the default branch, and the last push was on 2026-10-19.

Getting a development stack running on Ubuntu

The documented prerequisites are Go 1.21 or higher, MariaDB 11.3 or higher, Redis, and Node.js with NPM. The instructions give the Ubuntu commands for the three services you cannot install from a tarball:

shell
    sudo apt update

    # Install and start MariaDB
    sudo apt install mariadb-server
    sudo systemctl start mariadb.service

    # Install and start Redis
    sudo apt install redis-server
    sudo systemctl start redis.service

    # Install Node.js and NPM
    sudo apt install nodejs npm

The database is then created by hand through the MariaDB CLI, with a note that you may use a different database name:

shell
    # Open MariaDB CLI
    mariadb -u root -p --binary-as-hex

    # Create a database named discuit (you may use a different name)
    create database discuit;

    # Enter exit (or press Ctrl+D) to exit
    exit;

The `--binary-as-hex` flag is not decoration. Without it the client can mangle binary data, and a forum with image attachments is exactly the case where that bites.

One more system dependency is easy to miss, because it is not a service. Discuit uses `libvips` for fast image transformations, and on Ubuntu the instruction is `sudo apt install libvips-dev`. It is a native library with a development package, so on a machine where you only installed the runtime you will get a build failure rather than a clean error message from the application.

The clone is a single line that also moves you into the directory:

shell
    git clone https://github.com/discuitnet/discuit.git && cd discuit

Config, build, migrate, serve, and the rule about running from the root

Configuration is a file rather than a set of flags. You create a file named `config.yaml` in the root directory, copy the contents of `config.default.yaml` into it, and enter the required parameters. The repository root holds both `config.default.yaml` and a `config/` directory, and there is also a `.env.example` listing the environment variable names the server understands, including `DISCUIT_DB_ADDR`, `DISCUIT_DB_USER`, `DISCUIT_DB_PASSWORD`, `DISCUIT_DB_NAME`, `DISCUIT_REDIS_ADDRESS`, `DISCUIT_HMAC_SECRET`, `DISCUIT_CAPTCHA_SECRET`, `DISCUIT_IMAGES_FOLDER_PATH` and `DISCUIT_CSRF_OFF`.

The three commands that follow are short enough to look trivial and are in fact the whole lifecycle. The frontend and backend are built together:

shell
    ./build.sh

Then the schema is brought up to date:

shell
    ./discuit migrate run

And the server is started:

shell
    ./discuit serve

One constraint is stated in bold in the documentation and it matters more than any of the above: do not install the discuit binary using `go install` or move it somewhere else, because it uses files in this repository at runtime and so it should only be run from the root of the repository. A community server that reads its templates, its static assets and possibly its migrations from paths relative to the working directory is not a binary you can drop into a systemd unit from anywhere. If you want it as a service, the working directory has to be the checkout.

Admin rights are granted from the command line after you create an account, with `./discuit admin make username`.

The Docker path and the volume that is not persisted

The container route needs an explicit architecture choice. There is a Dockerfile per architecture in the `docker/` directory, and the documented build for the common case is:

shell
   docker build -t discuit -f docker/Dockerfile.amd64 .

The note alongside it says that for a different architecture you change the `-f` flag to the matching Dockerfile, and that the project currently supports `linux/amd64` through docker/Dockerfile.amd64 and `linux/arm64` through docker/Dockerfile.arm64. This is an Apple Silicon and ARM server deployment detail, and it is handled properly rather than left to a single multi-arch base image.

The run command mounts three named volumes, one for MySQL, one for Redis and one for images:

shell
   docker run -d --name discuit -v discuit-db:/var/lib/mysql -v discuit-redis:/var/lib/redis -v discuit-images:/app/images -p 8080:8080 discuit

The documentation is explicit that the database persists across restarts while the included config.yaml does not, and that you will need to mount the file to the container if you want to persist the configuration. That is the sharp edge in this setup. The same applies to the site name, the address it binds to and any secret you set, because the container's environment is otherwise whatever the image ships with, and a container recreated from the same image comes back with the same defaults.

The port note is also worth reading twice, because the wording is confusing. Discuit runs on port 8080 inside the container, so the 8080 outside the container does not matter, so long as it maps to 8080 on the inside. The compose file in the repository takes a different approach, mapping `8080:80` and setting `DISCUIT_ADDR: ":80"` in the environment, so the port the server binds inside the container is configurable rather than fixed.

Stopping and starting again are the plain Docker commands:

shell
   docker stop discuit
shell
   docker start discuit

The site is then reachable at `http://localhost:8080`.

The Nix flake, and what it removes from the setup

For anyone on Nix or NixOS there is a third route, and it is the shortest of the three. The repository includes flake.nix and flake.lock, and the command is one line:

sh
nix develop

The documented effects are that it installs all required packages, starts local MariaDB and Redis servers with logs in `.mysql/` and `.redis/` respectively, and creates the `discuit` database and user automatically. When you exit the shell, MariaDB and Redis stop automatically.

That last behaviour is the real feature. The local setup described earlier leaves two services running under systemd on your machine, and the flake keeps them scoped to the shell session that needs them. The `.mysql/` and `.redis/` log directories also mean you can see what the services printed without hunting through journal output.

The prerequisite is noted as important: you need Nix flakes enabled and a recent version of Nix to use this. Flakes are still behind an experimental feature flag in many Nix installations, so the first thing to check is whether your configuration turns them on, not whether the command runs.

Compare the three routes and the trade is clear. The local build gives you a tree you can edit and run with ./discuit serve, the Docker image gives you a reproducible artifact with per-architecture Dockerfiles and persistent volumes, and the flake gives you a reproducible environment with no services left running afterwards. The flake and Docker also solve the problem that the binary must run from the repository root, since the container mounts the application at /app and the flake shell stays in the checkout.

The roadmap shows what is missing, and the gap is large

The roadmap is unusually honest, because it is a checkbox list in the project documentation rather than a marketing page, and several of the missing entries are features people expect from a discussion platform.

Unchecked are filtering posts by topic, an explore page, filtering link posts by URL or domain, a single page for handling reports across multiple communities, temporary bans, user and community mentions with @user and +community, poll posts, server side rendering for better SEO, direct messages, multiple feeds, search, a moderation log, RSS feeds, wiki pages for communities, post drafts, viewed post history, and flairs to group posts within a community.

Three of those deserve emphasis. Search is the one that separates a small forum from a platform, and it is not there. Server side rendering is listed against better SEO, which tells you the React frontend is client rendered today, so a self-hosted community that wants to be indexed by search engines has a problem it cannot solve with configuration. Direct messages are absent, which means the platform has no private communication layer at all.

What is done is a solid forum core: dark mode, user created communities, a set of UI preferences including compact mode, infinite scroll toggle, notification choices and default feed sort, community and user muting, pinned posts and comments, locked individual comments, image posts, video embeds for Youtube and Vimeo, image galleries, saved posts and comments, user profile pictures and user badges.

The moderation story is the part that shapes the product. A user who moderates several communities has to handle reports in each one separately, because the unified report page is unchecked, and there is no moderation log, so the record of what a moderator did lives only in the database and not in a per-community history. For a community running on this code, that is an operational decision to make up front rather than discover later.

Licence, configuration surface and the security-adjacent settings

Discuit is released under the GNU Affero General Public License, version 3 or later, with the copyright line reading Copyright (C) 2024 Previnder. AGPL-3.0 is the part of the decision that needs attention rather than acceptance, because its network use clause is the reason it was written. The ordinary GPL covers programs you convey to others, and the AGPL adds a condition for modified versions that are used over a network. For a community platform that people log into over HTTP, that is the exact scenario the license targets, and it is a different position from running unmodified code as a hobby site. Read the LICENSE file and talk to whoever handles licensing at your organisation before exposing a modified version publicly, and this is not legal advice.

The configuration surface is wide and mostly documented by example in `.env.example`. Beyond the database and Redis settings, the file exposes a session cookie name, an HMAC secret, a CSRF off switch, a flag to disable logging to a file, pagination limits and a default feed sort, certificate and key file paths for TLS, a rate limit kill switch and a maximum image size.

Two of those deserve a closer look. The captcha verification is skipped if empty, so an unset `DISCUIT_CAPTCHA_SECRET` means no captcha, which is convenient in development and a decision you should make consciously rather than inherit. And the admin API key is described as allowing API requests carrying a query parameter of the form `adminKey=value` to bypass rate limits, which means the key travels in a URL, where it can end up in logs, in proxy logs and in browser history.

The compose file shows the same settings in environment form, with `DISCUIT_SITE_NAME`, `DISCUIT_SESSION_COOKIE_NAME: "DSID"`, `DISCUIT_REDIS_ADDRESS`, `DISCUIT_FORUM_CREATION_REQ_POINTS: "10"` and `DISCUIT_MAX_FORUMS_PER_USER: "10"`, which tells you that creating a community costs the user points and that the number of communities per user is capped by configuration.

Editorial conclusion

Discuit fits an organisation or individual who wants a community platform with no platform dependency, a real REST API, and a database schema they own, and who is prepared to run MariaDB and Redis as well as the Go binary. It does not fit anyone who needs search, server side rendering, private messaging or an RSS feed today, because the project roadmap lists all four as unfinished, and it does not suit a commercial hosted service without reading the AGPL-3.0 terms carefully. Before you deploy it, copy config.default.yaml to config.yaml and set the database credentials, the HMAC secret and the image folder path, decide whether the captcha secret stays empty, and run the binary from the repository root, since the documentation says it reads files from the tree at runtime.

Frequently asked questions

What is Discuit and what stack does it use?

Discuit is the codebase behind discuit.org, an open-source community discussion platform positioned as an alternative to Reddit. The backend is Go, the frontend is React, MariaDB is the main datastore and Redis holds transient data.

How do I run Discuit locally?

Install Go 1.21 or higher, MariaDB 11.3 or higher, Redis, Node.js and libvips, then clone the repository, copy config.default.yaml to config.yaml, run ./build.sh, run ./discuit migrate run and start the server with ./discuit serve. The binary must be run from the root of the repository because it reads files from the tree at runtime.

Can I run Discuit with Docker or Nix?

Yes. The documentation gives a docker build using docker/Dockerfile.amd64 or docker/Dockerfile.arm64 and a docker run command with named volumes for MySQL, Redis and images, and a nix develop command that installs the packages, starts local MariaDB and Redis and creates the discuit database automatically.

What features does Discuit still lack?

The roadmap lists search, server side rendering, direct messages, RSS feeds, post drafts, poll posts, user and community mentions, multiple feeds, a moderation log, wiki pages for communities, a unified report page for moderators of several communities and temporary bans as unfinished.

What licence is Discuit released under?

Discuit is released under the GNU Affero General Public License, version 3 or later, with the copyright line Copyright (C) 2024 Previnder. The repository publishes no GitHub releases, and the last push was on 2026-10-19.

Official sources

  1. discuitnet/discuit on GitHub
  2. Issues
  3. License: AGPL-3.0
  4. Project website
  5. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/discuitnet-discuit.svg)](https://hysenlabs.com/projects/discuitnet-discuit)