Every conference organiser eventually hits the same ceiling: per-seat pricing that scales with your success, no control over attendee data, and a chat system that disappears the moment the event ends. Atria was built to knock down that ceiling. It is a fully self-hosted event management and professional networking platform that gives you the features of Hopin or Bevy without the ongoing bill or the vendor lock-in.
What is Atria?
Atria is an open-source platform for managing professional events — conferences, corporate retreats, academic workshops, nonprofit galas, and everything between. It combines event scheduling with attendee networking, real-time multi-level chat, sponsor management, and hybrid video streaming in a single application.
“Atria is an event management and professional networking platform designed to facilitate meaningful connections both during and after events.”
Atria Source Code on GitHub Atria Documentation Live Demo
What sets it apart
- 📅 Multi-day event scheduling — sessions with speakers, roles, and drag-and-drop agenda management
- 💬 Multi-level real-time chat — general, Q&A, networking, session-specific, and backstage channels, all via Socket.IO
- 🤝 Attendee networking — icebreaker prompts, connection requests, profile discovery by role and interests
- 🎥 Hybrid video streaming — Vimeo, Mux (with signed playback), Zoom, and Jitsi supported out of the box
- 💎 Sponsor tiers — Platinum to Bronze with drag-and-drop reordering, logos auto-converted to WebP
- 🔐 Granular RBAC — five event roles (Admin → Organizer → Moderator → Speaker → Attendee) plus org-level roles
- 📩 Direct messaging — attendees can connect and message each other after meeting at a session
- ⚖️ AGPL-3.0 licensed — full source, full data control
Atria Tech Overview
Atria is a two-tier web application: a Python/Flask ASGI backend and a React 18 SPA frontend, connected by a REST API and Socket.IO WebSockets. PostgreSQL stores all event data; Redis powers real-time Socket.IO clustering and the application cache; MinIO (or any S3-compatible service) handles file and image storage.
How real-time chat works
Flask-SocketIO runs on top of Eventlet (the async transport). When multiple backend instances are deployed, Redis DB 1 acts as the Socket.IO message broker, ensuring a message sent to one instance reaches clients connected to any other. Redis DB 3 tracks presence (who is online) and typing indicators. Without Redis, the app runs single-instance with in-memory Socket.IO — fine for development.
Stack at a glance
| Layer | Technology |
|---|---|
| Backend | Python 3.13, Flask, SQLAlchemy, Flask-SocketIO |
| Real-time | Flask-SocketIO + Eventlet + Redis clustering |
| Auth | Flask-JWT-Extended (HTTPOnly cookies, 1h access / 30d refresh) |
| API docs | Flask-Smorest (OpenAPI/Swagger at /new-swagger) |
| Database | PostgreSQL 15 + Alembic migrations |
| Cache / pub-sub | Redis 7 (3 logical DBs) |
| Storage | MinIO or S3-compatible (3 buckets: public / auth / private) |
| Frontend | React 18, Vite 6, TypeScript 5.6, Mantine UI 7.16 |
| State | Redux Toolkit 2.5 + RTK Query |
| Forms | React Hook Form 7.54 + Zod validation |
| Video | Jitsi SDK, Mux player, Vimeo player |
| Animation | GSAP 3.13, Lenis 1.3 |
The production frontend is built with Playwright/Chromium prerendering and served by Nginx with strict CSP security headers.
Self-Hosting Atria with Docker
Get Docker 🐋
Install Docker on your system before proceeding:
- Linux: Official Docker Engine install guide
- Windows / Mac: Docker Desktop
Verify installation: docker --version && docker compose version
Atria requires three external services beyond the application itself: PostgreSQL, Redis (optional but recommended), and MinIO or S3 for file storage. The Docker Compose file bundles PostgreSQL — you supply MinIO separately or point at any S3-compatible bucket.
git clone https://github.com/thesubtleties/atria.git
cd atria
cp .env.example .env
cp .env.development.example .env.development
Edit .env.development with at minimum:
# Database (matches .env)
POSTGRES_USER=dev_user
POSTGRES_PASSWORD=change_this_password
POSTGRES_DB=atria_dev
SQLALCHEMY_DATABASE_URI=postgresql://dev_user:change_this_password@db:5432/atria_dev
# Security — generate fresh keys before exposing publicly
SECRET_KEY=replace_with_long_random_string
JWT_SECRET_KEY=replace_with_different_long_string
ENCRYPTION_KEY=replace_with_fernet_key
# Frontend URL (for CORS)
FRONTEND_URL=http://your-server-ip:5173
VITE_API_URL=http://your-server-ip:5000/api
# Storage (point at your MinIO or S3)
MINIO_ENDPOINT=minio.yourdomain.com
MINIO_ACCESS_KEY=your_access_key
MINIO_SECRET_KEY=your_secret_key
MINIO_USE_SSL=true
MINIO_EXTERNAL_URL=https://minio.yourdomain.com
Then start the development stack (includes seeded sample data):
docker compose -f docker-compose.dev-vite.yml up -d
Or use the interactive chooser script:
./dev-environment-chooser.sh
Open:
- Dashboard:
http://localhost:5173 - API:
http://localhost:5000/api - Swagger:
http://localhost:5000/new-swagger
To skip the sample data seed:
SEED_DB=false docker compose -f docker-compose.dev-vite.yml up -d
Services explained
| Service | Port | Purpose |
|---|---|---|
frontend |
5173 | React 18 SPA (Vite dev server) |
backend |
5000 | Flask API + Socket.IO |
db |
5432 | PostgreSQL 15 |
| Redis | 6379 | Optional (redis-dev compose variant) |
| MinIO | 9000 | External — configure separately |
Production deployment
The production compose (docker-compose.production.yml) uses hardened Docker images and expects a reverse proxy (Nginx Proxy Manager, Traefik, Caddy) in front. No ports are exposed except the Nginx-served frontend on port 80.
docker compose -f docker-compose.production.yml up -d
Key changes for production in .env.development:
FLASK_ENV=production
FLASK_DEBUG=0
LOG_LEVEL=warning
GUNICORN_WORKERS=4
SEED_DB=false
ALLOWED_HOSTS=atria.yourdomain.com
MINIO_USE_SSL=true
Generate strong secrets:
# SECRET_KEY and JWT_SECRET_KEY
python -c "import secrets; print(secrets.token_urlsafe(32))"
# ENCRYPTION_KEY (Fernet)
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
Enabling Redis for multi-instance scaling
Without Redis, Socket.IO runs in-memory — fine for a single instance. To enable clustering and presence tracking, add Redis to the compose file and configure:
REDIS_URL=redis://redis:6379/0
SOCKETIO_REDIS_URL=redis://redis:6379/1
Use docker-compose.redis-dev.yml for a local multi-instance setup with Traefik load balancing:
docker compose -f docker-compose.redis-dev.yml up -d
This spins up two backend instances load-balanced by Traefik, with Socket.IO messages brokered through Redis so clients connected to either instance see all messages.
Configuring email notifications (SMTP2GO)
Atria uses SMTP2GO for transactional email (invitations, notifications). Sign up for a free SMTP2GO account and add to .env.development:
SMTP2GO_API_KEY=your_smtp2go_api_key
MAIL_DEFAULT_SENDER=[email protected]
Without this, the application works but email features (invitation links, notification emails) are disabled.
Setting up your first event
Once Atria is running:
1. Create an organisation — the top-level container for all your events. One Atria instance can host multiple independent organisations.
2. Create an event — set the event name, dates, description, and cover image. Events can span multiple days with multiple concurrent sessions.
3. Add sessions — create sessions with start/end times, assign speakers and their roles. Sessions can have a video stream URL (Vimeo, Mux, Zoom meeting link, or a Jitsi room).
4. Invite attendees — share the event join link. Attendees register and choose their roles. The icebreaker system prompts them to share a conversation starter shown to other attendees when sending a connection request.
5. Go live — during the event, attendees join session chats, send direct messages, and connect with each other. The backstage channel is visible only to organisers and speakers for behind-the-scenes coordination.
AGPL-3.0 Attribution Note
Atria is AGPL-3.0 licensed. If you self-host and modify it, the source must remain available to your users. The licence also requires retaining a small attribution line in the event navigation sidebar:
atria is made with ❤️ by sbtl
(with links to atria.gg and sbtl.dev). A commercial licence without this requirement is available — contact [email protected].
Conclusion
Atria fills a gap that surprisingly few open-source projects address: the full event lifecycle from scheduling through networking and follow-up, all in one self-hosted stack. Most open-source alternatives focus on ticketing (Pretix) or academic scheduling (Indico) — Atria focuses on the attendee experience, with the real-time chat and networking tools that make events feel alive.
The Flask + PostgreSQL + Redis architecture is straightforward to operate, and the optional Redis mode means you can start simple and scale horizontally later.
Alternatives worth comparing:
- Pretix — excellent self-hosted ticketing and registration; no networking or live chat features
- Indico — CERN-developed academic conference management; strong for scientific events, less polished UX
- OSEM — Ruby on Rails, community conference focus, simpler feature set
- Hopin — the SaaS benchmark; per-attendee pricing, no self-hosting
Frequently Asked Questions
Can I run multiple events simultaneously?
Yes — Atria is multi-tenant. One instance can host multiple organisations, each with multiple concurrent events. Attendees, sessions, and chats are fully isolated per event.
Does it support in-person-only events, or only virtual?
Both, and hybrid. Sessions can have no video stream (in-person only), a live stream URL (virtual), or a Jitsi room (built-in video conferencing). The platform does not enforce a single event format.
Is MinIO required, or can I use AWS S3?
Any S3-compatible endpoint works. Set MINIO_ENDPOINT to your S3 endpoint, MINIO_ACCESS_KEY / MINIO_SECRET_KEY to your S3 credentials, and MINIO_USE_SSL=true. The variable names use “MINIO” but the underlying SDK connects to any S3-compatible service.
What happens to chat messages after the event ends?
All messages are persisted in PostgreSQL and remain accessible. Atria does not delete chat history when an event ends — attendees can still read the session discussions and continue direct message threads.
Can I import attendees in bulk?
The current version supports inviting attendees individually or via a shareable link. Bulk CSV import is not yet a built-in feature — check the GitHub roadmap for planned additions.
How do I back up my data?
Back up the PostgreSQL database with a standard pg_dump and your MinIO bucket data with mc mirror (MinIO Client). The Docker Compose setup keeps PostgreSQL data in a named volume — snapshot the volume or use pg_dump on a schedule.
Comments