Open-source project
Canop/miaou avatar
Canop/miaou

Miaou is a self-hosted Node chat server built around plugins

A chat server with OAuth2 authentication, persistent and searchable history, video and audio, markdown formatting, private and public rooms, stars, votes, embedded games, and many other features

553 stars71 forksJavaScriptNOASSERTION

At a glance

What is it?
Miaou is a JavaScript chat server with OAuth2 sign-in, PostgreSQL-backed searchable history, socket.io for live messages, WebRTC for audio and video, and a plugin system that the README points at as the place for most new features. It ships with a Dockerfile and a Compose file, and the deployment story is the easiest part of the project.
Who is it for?
Adopt Miaou when you want a chat server for a community or a small team that you run yourself, and when you want the feature set extended through plugins rather than through a fork. Do not adopt it for a large deployment, since the stack pins Node at 10 or newer with socket.io 2.x and the Compose file ships a database password of `miaou`, which is a development configuration.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 141 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

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

Editorial analysis

A chat server whose features live in plugins

Miaou is described in the README as a chat server with authentication, persistent and searchable history, rich markdown formatting, video, private rooms, conversation highlighting, plugins, persisted notifications, code and table rendering, specialized link boxing, github hooks, bots, and many other features. The repository description adds OAuth2 authentication, stars, votes and embedded games.

What makes it worth reading is the last item on that list rather than the first few. The README says many features are implemented as plugins, and that is where you should look first, with a pointer to the plugin development documentation at `plugins/README.md`.

That is a real architectural choice rather than a packaging detail. A chat server accumulates features quickly, because each community wants something slightly different, and a codebase where every addition is a new core release gets slow to change and slow to fork. Here the extension point is explicit and documented, so the things that vary between communities live outside the core and the core stays small enough to reason about.

The stack is described as mostly JavaScript, with node, PostgreSQL, OAuth2, socket.io, WebRTC, express, Bluebird, Redis, Pug, Passport.js, hu.js, jQuery, sass/scss, travis-ci, and nginx. The two database-backed technologies pull in opposite directions and the project uses both on purpose: PostgreSQL for the durable record of messages and rooms, and Redis for the live state and session storage.

The project is JavaScript with a MIT licence, copyright 2014 Denys Séguret, and the licence section adds that most of Miaou follows the MIT Licence with exceptions specified in a separate `license.md` file. The homepage is miaou.dystroy.org, where the README says anybody can create a room for public or private use, and the last push was on 2026-06-04.

Install it with Docker Compose

The installation documentation is in `installation.md`, but the repository also ships everything needed to run the thing with Docker, and the Compose file is the clearest statement of how the pieces fit together:

yaml
version: '2'

services:

  miaou:
    build: .
    ports:
      - "80:8204"
    links:
      - postgres
      - redis
    depends_on:
      - postgres
      - redis
    env_file:
      - docker/miaou-default.env # define default environment variables
      - docker/miaou.env # allow to override or add local environment variables

  postgres:
    image: postgres
    ports:
      - "5432"
    volumes:
      - psql_data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: miaou
      POSTGRES_PASSWORD: miaou
      PGPASSWORD: miaou

  redis:
    image: redis
    volumes:
      - redis_data:/data
    ports:
      - "6379"

volumes:
  psql_data:
  redis_data:

Three services, and the wiring is the whole architecture. Miaou itself is built from the Dockerfile in the repository root, listens on port 8204 inside the container and is published on port 80 of the host, and it declares a dependency on both PostgreSQL and Redis so they start first.

The two env files are a deliberate layering. `docker/miaou-default.env` holds the defaults the project ships, and `docker/miaou.env` is the one you edit to override or add local values, which means your own settings live in a file that is not part of the project's defaults.

The database credentials are the weak point of this file. The user, the password and the PGPASSWORD are all set to `miaou`, and PostgreSQL is published on a host port. That is a development configuration and it should not survive contact with a real deployment, so changing it is the first thing to do after the first successful start.

The named volumes, `psql_data` and `redis_data`, are what make the data survive a container rebuild, so `docker compose down` without the volume flag is safe and `docker compose down -v` is not.

What the Dockerfile tells you about the runtime

The Dockerfile is short and it pins the runtime in a way that matters more than usual for a project of this age:

dockerfile
FROM node:10

USER root
RUN mkdir -p /var/www/miaou
WORKDIR /var/www/miaou

# NPM install (this is done before copying the whole application, in order to be cached)
COPY package.json /var/www/miaou/
RUN yarn add gulp
RUN yarn

# Copy and build application
COPY . /var/www/miaou/
RUN yarn run gulp build

# Define exposable ports
EXPOSE 8204

# Define default command
CMD ["node", "--use_strict", "main.js"]

The base image is `node:10`. That is a single major version, and it lines up with the `engines` field in the package manifest, which asks for Node `>=10.0.0`, and with the dependency set, where socket.io is at 2.x and express at 3.x.

The comment about copying package.json first is the standard layer caching trick, and it is worth noting that the build installs `gulp` explicitly before running `yarn`, because gulp is listed as a runtime dependency rather than a development one, so a plain production install of the manifest would not bring it in.

The build step is `yarn run gulp build`, which compiles the assets and the views, and the `gulpfile.js` at the repository root is what it reads. The final command runs `main.js` with `--use_strict`.

So the deployment shape is: a Node process serving HTTP on 8204, Pug templates rendered server side, socket.io carrying the live messages, Redis holding session and presence state, and PostgreSQL holding the durable history. That last combination is the design decision behind the searchable history, since a chat server that keeps everything in memory cannot search anything from last year.

If you want to run it without Docker, the repository has a `start.sh`, a `restart.sh` and a `kill.sh` at the root, a `Vagrantfile` with a `vagrant/` directory for a local virtual machine, and `config-default.js` for the configuration.

Plugins, themes and the shape of the source tree

The top level of the repository shows how the project is organised, and it is worth walking through because it explains the plugin claim.

There is `plugins/` with its own README for plugin development, `src/` for the application source, `views/` for the Pug templates, `themes/` with a `themes.md` describing them, `libs/` for shared code, `sql/` for the database schema, `tests/` for the test suite, and `graphics/` and `src/rsc/` for assets. Then `config-default.js` for configuration, `main.js` as the entry point, `views/` for templates, and `benchmark/` with a `bench.sh` for load testing.

Three of those deserve a note.

The `sql/` directory is the schema, and its presence is the answer to the question of how a chat server keeps a searchable history. The messages live in PostgreSQL, and the schema in the repository is what you load before the first start.

The `themes/` directory with a `themes.md` means the visual layer is separated from the templates. For a community server, being able to restyle without touching the application code is most of the difference between a chat server you run and one you fight.

The `tests/` directory matters for a different reason. The contributing guidance in the README is specific: come and discuss before coding, and always test yourself and run the test suite before doing a pull request. A plugin system with a documented test requirement is a project that expects plugins to be checked, and the test tooling sits alongside the linters in the manifest, with `@biomejs/biome` at 1.9.4 and ESLint 9 with the flat config file `eslint.config.mjs` at the root, plus `biome.json`.

The `benchmark/` directory and `bench.sh` are another good sign. A chat server with WebRTC calls and a large room list is a load-sensitive service, and shipping a benchmark harness with the project means performance work has a repeatable starting point.

Authentication, storage and the plugin surface in detail

The dependency list is where the feature set becomes concrete.

Authentication is OAuth2 throughout, with Passport.js at the core and four strategies in the manifest: `@passport-next/passport-google-oauth2` pinned to a GitHub reference rather than a version range, `passport-github2`, `passport-oauth` and `passport-reddit`. So an account is tied to an external identity, and the server never stores a password for it. The sessions use `express-session` with `connect-redis` at 3.4.1, which means session state lives in Redis and survives a server restart.

The live messaging is socket.io at 2.2.0 on the server and socket.io-client at 2.3.1, with a separate `double-ended-queue` pinned to the exact version `2.1.0-0`.

Audio and video are WebRTC, which the README lists in the stack even though there is no WebRTC package in the manifest, so the peer connection is presumably established by the browser client rather than by a server library.

Rich content is handled client side and server side. `cheerio` at a recent range is there for HTML parsing, `pug` at 3.0.0 renders the views, `hu.js` and `jQuery` are in the list, with `sass/scss` for the stylesheets compiled by gulp. `file-type` at 10.9.0 and `busboy` for multipart uploads point at the video and audio handling, `web-push` at 3.4.4 is the browser push support behind the persisted notifications, and `iconv-lite` handles character set conversion for the markdown and link boxing features.

The features the README lists map onto those libraries fairly directly. Rich markdown formatting, code and table rendering and specialized link boxing are rendering concerns. Video and audio are upload plus WebRTC. Persisted notifications are `web-push`. Bots are a plugin-shaped feature, and the github hooks and stars and votes from the repository description are the sort of thing the plugin system exists for.

One detail in the manifest is worth flagging for an operator. `request` and `follow-redirects` are dependencies, and `request` is a long-deprecated HTTP client, and `double-ended-queue` is pinned to a prerelease-looking version string. This is a codebase whose dependency set reflects its era, which is fine for a self-hosted service but worth knowing before you put it on the public internet.

Where Miaou fits, and where it does not

The intended audience is visible in the README's own instructions. If you want to install Miaou, the installation documentation is available, and then the README invites you to come and ask for advice in one of the dedicated chat rooms, noting that they are currently more active between 8 and 19 GMT. It also asks that if you run your own server, you tell them, because they are happy to learn about installations.

That is a small community server project with a public instance, and the fit is a community, a small team, a course, or an internal channel that wants its own instance rather than a shared one.

The alternative approaches are worth naming concretely. A hosted chat service gives you no data ownership and no self-hosting, which is the opposite of what this project is for. A general purpose forum gives you structure but not live presence. A newer real-time chat framework gives you a modern stack and typically a plugin ecosystem with far more contributors, but it will not give you the specific set of behaviours Miaou has grown around its markdown rendering, its link boxing and its particular notion of rooms and stars. The difference in approach is that Miaou is a server you own end to end, with the data in your PostgreSQL instance and the extension model in documented plugins.

The limits are equally clear. The runtime pins Node 10 and socket.io 2.x, which is a decade-old baseline, and the Docker base image matches it. The Compose file exposes PostgreSQL and Redis on host ports with a default password of `miaou`. The licence is MIT for most of the project with exceptions listed separately, so a redistribution has to read `license.md` rather than assume. And there are no GitHub releases, so there is no versioned artefact to pin to; a deployment tracks whatever commit you pulled, and the last push was on 2026-06-04.

For a community that wants its own chat and is comfortable running a database, that is a fair trade. For a high-traffic public service, the operational basics here are not there yet.

Editorial conclusion

Adopt Miaou when you want a chat server for a community or a small team that you run yourself, and when you want the feature set extended through plugins rather than through a fork. Do not adopt it for a large deployment, since the stack pins Node at 10 or newer with socket.io 2.x and the Compose file ships a database password of `miaou`, which is a development configuration. Verify first that the Node version you run matches the `engines` field, that you replace the default PostgreSQL credentials in `docker-compose.yml` before exposing the service, that your OAuth2 providers are configured in `config-default.js`, and that the licence exceptions listed in `license.md` do not conflict with your own distribution, since most of the project is MIT but not all of it.

Frequently asked questions

What is Miaou and what does it do?

Miaou is a chat server with authentication, persistent and searchable history, rich markdown formatting, video, private rooms, conversation highlighting, plugins, persisted notifications, code and table rendering, specialized link boxing, github hooks and bots. It is written mostly in JavaScript on Node.js, and a public instance runs at miaou.dystroy.org.

How do I install a Miaou server?

The installation documentation is in `installation.md`, and the repository also ships a Dockerfile and a `docker-compose.yml` with three services: Miaou itself on port 8204 published on port 80, a PostgreSQL service with a named `psql_data` volume, and a Redis service with a `redis_data` volume. Configuration lives in `docker/miaou-default.env` with overrides in `docker/miaou.env`.

How do you add features to Miaou?

Through plugins. The README says many features are implemented as plugins and points to the plugin development documentation in `plugins/README.md` as the first place to look. Contributions are welcome, with the guidance to discuss before coding and to always run the test suite before opening a pull request.

How does Miaou handle authentication?

With OAuth2 through Passport.js, using strategies for Google, GitHub, OAuth and Reddit, so no password is stored for a user. Sessions use express-session with connect-redis, and the durable message history lives in PostgreSQL while Redis holds session and live state.

What licence is Miaou under?

Most of Miaou follows the MIT Licence, and the README states that exceptions are specified in `license.md`. The copyright line reads 2014 Denys Séguret. The package manifest also lists the project licence as MIT, so the exceptions file is the part to read before redistributing.

Official sources

  1. Canop/miaou on GitHub
  2. Issues
  3. Project website
  4. 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/canop-miaou.svg)](https://hysenlabs.com/projects/canop-miaou)

Was this useful?