Concord is a self-hosted, open-source Discord alternative. Familiar enough to feel like home, better enough to justify the switch. One
docker compose upto own your community's data. AGPL-3.0, no CLA.
Screenshots coming soon — in the meantime, try
docker compose -f docker/docker-compose.yml up -dand see for yourself!
- What is Concord?
- Quick Start (Self-Host)
- Features
- Configuration
- Development
- Architecture
- Contributing
- License
Concord is a self-hosted, open-source community platform built as a drop-in Discord replacement. Run it on your own server in minutes with a single docker compose up. You own your data, your community, and your future — no vendor lock-in, no data mining, no proprietary walls.
It ships with real-time chat, forum channels (Reddit-style), file uploads, role-based permissions, push notifications, and more. AGPL-3.0 licensed with no CLA — your contributions stay yours and can never be relicensed.
Prerequisites: Docker and Docker Compose.
git clone https://github.com/CodesWhat/concord.git
cd concord
docker compose -f docker/docker-compose.yml up -dThen open http://localhost:8080. The database migrates automatically on startup. Register a new account to get started — the first user to create a server becomes its owner.
S3 storage setup (Garage)
The Docker Compose stack includes Garage for S3-compatible file storage. After first start, create the bucket:
# Connect to the Garage admin API and set up the cluster
docker compose -f docker/docker-compose.yml exec garage /garage node id 2>/dev/null | head -1
# Use the node ID from above:
docker compose -f docker/docker-compose.yml exec garage /garage layout assign -z dc1 -c 1G <NODE_ID>
docker compose -f docker/docker-compose.yml exec garage /garage layout apply --version 1
# Create an API key and bucket
docker compose -f docker/docker-compose.yml exec garage /garage key create concord-key
docker compose -f docker/docker-compose.yml exec garage /garage bucket create concord
docker compose -f docker/docker-compose.yml exec garage /garage bucket allow concord --read --write --key concord-keyUpdate the S3_ACCESS_KEY and S3_SECRET_KEY in docker/docker-compose.yml with the key ID and secret from the key create output.
Optional configuration: For Docker, edit the environment variables directly in docker/docker-compose.yml. For local development, copy apps/api/.env.example to apps/api/.env. Set your SMTP credentials for email delivery, S3 details for file uploads, and VAPID keys for push notifications. See the Configuration section for all available variables.
Chat & Messaging
- Real-time messaging — WebSocket gateway with instant delivery, edit, delete, and "(edited)" tags
- Threads — Threaded replies within channels
- Typing indicators — Animated "X is typing..." bar with 8-second auto-expire
- Presence tracking — Live online/idle/DND/invisible status synced across all clients
- Markdown rendering — Code blocks, links, lists, tables, task lists via react-markdown
- Unread tracking — Per-channel unread counts with mention badges
- Slowmode — Per-channel message rate limiting enforced server-side
Files & Media
- File uploads — Drag and drop, paste, or click to upload; S3-backed storage
- Avatar upload — User profile avatars stored in S3
Forum Channels
- Reddit-style forums — Forum channel type alongside text channels
- Voting — Upvote/downvote posts with live vote counts
- Comments — Nested comments on forum posts
- Post management — Create, edit, and delete forum posts
Roles & Permissions
- Role-based permissions — Bitmask permission system with named roles
- Channel overrides — Per-channel permission overrides per role
- Role hierarchy — Enforcement prevents users from acting above their role
- Kick & ban — Kick or ban members with hierarchy checks; ban list with unban support
Servers & Invites
- Server management — Create, join, edit, and delete servers
- Invite links — Shareable invite codes with configurable expiry and usage limits
- Leave server — Members can leave servers; wrapped in a transaction for safety
Notifications & Communication
- Push notifications — Web Push for @mentions; works on desktop and mobile
- Password reset — Email-based forgot-password flow via configurable SMTP
User Experience
- User profiles — Bio, avatar, display name, status
- Quick switcher — Cmd+K fuzzy search across servers and channels
- PWA installable — Install as a native app on desktop and mobile
- Responsive UI — 4-panel desktop layout with mobile-optimized bottom navigation
Operations
- Auto-migration — Database migrations run automatically on API startup
- Rate limiting — Global and per-route rate limits via @fastify/rate-limit
- S3-compatible storage — Works with MinIO, Cloudflare R2, AWS S3, or any compatible provider
For Docker deployments, set these in docker/docker-compose.yml. For local development, copy apps/api/.env.example to apps/api/.env:
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
REDIS_URL |
Redis connection string |
AUTH_SECRET |
Secret for session/auth token signing (required) |
CORS_ORIGIN |
Allowed frontend origin (e.g. https://concord.example.com) |
SMTP_HOST |
SMTP server host for email delivery |
SMTP_PORT |
SMTP server port (typically 587 or 465) |
SMTP_USER |
SMTP username |
SMTP_PASS |
SMTP password |
SMTP_FROM |
From address for outgoing emails |
S3_ENDPOINT |
S3-compatible storage endpoint (e.g. https://s3.amazonaws.com) |
S3_BUCKET |
Storage bucket name |
S3_ACCESS_KEY |
Storage access key |
S3_SECRET_KEY |
Storage secret key |
VAPID_PUBLIC_KEY |
VAPID public key for Web Push notifications |
VAPID_PRIVATE_KEY |
VAPID private key for Web Push notifications |
VAPID_SUBJECT |
VAPID subject (e.g. mailto:admin@example.com) |
Prerequisites: Node.js 22+, pnpm 10+, Docker (for Postgres, Redis, and MinIO)
# Clone
git clone https://github.com/CodesWhat/concord.git
cd concord
# Install dependencies
pnpm install
# Start database services
docker compose -f docker/docker-compose.dev.yml up -d
# Copy environment config
cp apps/api/.env.example apps/api/.env
# Run database migrations
cd apps/api && pnpm drizzle-kit push && cd ../..
# Seed sample data (optional)
cd apps/api && pnpm tsx src/seed.ts && cd ../..
# Start development servers
pnpm devThen open http://localhost:5173 — the API runs on port 3000, proxied through Vite.
# Run all apps in dev mode (web + api)
pnpm dev
# Build all packages
pnpm build
# Run database migrations
cd apps/api && pnpm drizzle-kit push
# Generate a new migration
cd apps/api && pnpm drizzle-kit generateProject conventions
- Small, single-purpose files — No file exceeds ~300 lines
- Explicit types — No
any, typed parameters and return types everywhere - One route per file —
routes/messages.tshandles all message endpoints - Service layer separation — Routes handle HTTP, services handle business logic
ServiceResult<T>pattern —{ data, error }tuples instead of thrown exceptions- Colocated tests —
routes/messages.ts→routes/messages.test.ts
Turborepo monorepo with three packages:
concord/
├── apps/
│ ├── web/ # React 19 + Vite 6 + Tailwind CSS v4
│ └── api/ # Fastify 5 + Drizzle ORM + WebSocket gateway
├── packages/
│ ├── shared/ # Shared types, permissions, snowflake utilities
│ └── config/ # Shared ESLint + TypeScript config
└── docker/ # Docker Compose for dev and production
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite 6, Tailwind CSS v4, Zustand |
| Backend | Fastify 5, TypeScript, Drizzle ORM |
| Database | PostgreSQL 17, Redis 7 |
| Auth | Better Auth (session-based, Drizzle adapter) |
| Real-time | WebSocket (ws), Redis pub/sub for fan-out |
| IDs | Snowflake (64-bit, custom epoch 2026-01-01) |
| Storage | S3-compatible (MinIO, AWS S3, Cloudflare R2) |
Contributions are welcome. See CONTRIBUTING.md for setup instructions, code style, and the PR process.
This project is AGPL-3.0 with no CLA — your contributions can never be relicensed.
AGPL-3.0 — no CLA. By contributing, you agree your contributions will be licensed under the same terms. Your code stays yours.