A comprehensive, open-source self-hosted Discord bot for managing school communities. Features a secure student verification system, admin dashboard, warning management, ticket system, and multi-language support—all containerized with Docker and backed by MongoDB.
Repository: GitHub - MoritzKlasen/OpenSDB
- Overview
- Core Features
- Architecture
- Prerequisites
- Quick Start
- Configuration Guide
- Slash Commands Reference
- Admin Dashboard
- Ticket System
- Localization
- Developing Locally
- Troubleshooting
- Security Considerations
- Contributing
OpenSDB is designed specifically for school Discord servers to:
- Verify student identities and assign them appropriate roles
- Monitor server behavior with a banned words filter and warning system
- Manage administrative tasks through an intuitive web dashboard
- Support multi-language environments (English & German built-in)
- Create support and verification workflows via ticket systems
- Track and report user activity and verification metrics
The entire system runs in Docker containers for easy deployment and scaling.
- Student Verification – Verify users with their first and last name, automatically assigning verification numbers and roles
- Unverification – Remove verification status and associated roles when needed
- User Comments – Add contextual notes to verified students (e.g., accommodations, issues)
- Deanonymization – View student's real name and recent warnings (admin/team only)
- Prohibited Word Filter – Automatically detect banned words and notify admins
- Warning System – Issue, track, and delete warnings per student
- Admin Notifications – Get real-time alerts in a dedicated admin channel with quick action buttons
- Comment Prompts – Add notes directly from ban notifications
- Ticket System – Students can create support tickets or verification requests
- Auto-role Assignment – Assign roles to new members or upon verification
- Team Role Management – Designate team members with elevated permissions
- Role Customization – Configure separate roles for teams, verified users, and new members
- Multi-language Support – English and German localization with per-server language settings
- Localized Message Updates – Language changes automatically update all bot messages
- CSV Import/Export – Bulk import student data or export for analysis
- Metrics API – Track verification rates with JSON/CSV endpoints
- Message Tracking – Bot tracks and manages message updates for localization
- Secure Admin UI – JWT-authenticated web dashboard with HTTPS support
┌─────────────┐
│ Discord Bot │ (Node.js + discord.js)
│ Bots │ • Processes commands & interactions
│ Service │ • Monitors messages for banned words
│ │ • Memory: 256M, CPU: 0.50
└──────┬──────┘
│
├────────────────┬──────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼────┐ ┌──────▼─────┐
│ MongoDB │ │ Admin Web │ │ Nginx │
│ │ │ Server │ │ Reverse │
│ (mongo:7) │ │ (Express) │ │ Proxy │
│ │ │ Memory: │ │ (SSL/TLS) │
│ Port: 27017 │ │ 128M, │ │ Ports: │
│ Database │ │ CPU: 0.25 │ │ 80, 443 │
└─────────────┘ └───────────┘ └────────────┘
| Component | Technology | Version |
|---|---|---|
| Bot Runtime | Node.js | 20-slim |
| Web UI Runtime | Node.js | 18-alpine |
| Discord Library | discord.js | 14.25+ |
| Web Framework | Express.js | 5.2+ |
| Database | MongoDB | 7 |
| Reverse Proxy | Nginx | alpine |
| Authentication | JWT + bcrypt | node packages |
| Language Locales | JSON | en.json, de.json |
- Git – For cloning the repository
- Docker & Docker Compose – Install Docker Desktop or Docker + Compose
- Discord Bot Token – Create application at Discord Developer Portal
- Server ID – Your Discord guild ID (enable Developer Mode, right-click server > Copy Server ID)
- OpenSSL – For generating self-signed HTTPS certificates (macOS/Linux: usually pre-installed)
- Node.js 18+ – Only if developing locally without Docker
- Minimum: 512MB RAM, 1 CPU core
- Recommended: 1GB RAM, 2 CPU cores
- Disk: 1GB free (including MongoDB data growth)
git clone https://github.com/MoritzKlasen/OpenSDB.git
cd OpenSDBCreate .env in the project root:
nano .env # edit with your valuesRequired variables:
# Discord Configuration (obtain from Developer Portal)
DISCORD_TOKEN=your-bot-token-here
CLIENT_ID=your-application-id-here
ALLOWED_GUILD_ID=your-server-id-here
# Database
DB_URI=mongodb://mongo:27017/botdb
# Admin UI Credentials
ADMIN_USERNAME=admin
ADMIN_PASSWORD=choose-a-strong-password
JWT_SECRET=generate-a-random-jwt-secret
# Server Configuration
ADMIN_UI_PORT=8001
# Optional: Metrics API Authentication (Grafana, etc.)
METRICS_BASIC_USER=grafana
METRICS_BASIC_PASS=changeMe!
⚠️ Security Warning: Never commit.envto version control. Ensure it's in.gitignore.
For production HTTPS support:
cd nginx/certs
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout opensdb.key -out opensdb.crt \
-config ../openssl.cnf
cd ../..The Nginx config expects: opensdb.key and opensdb.crt
# Build and start all services in the background
docker compose up --build -d
# Verify services are running
docker compose psThe bot commands are automatically registered when the bot connects. To manually register:
node deploy-commands.jsThis must be run once after setup (it uses DISCORD_TOKEN, CLIENT_ID, ALLOWED_GUILD_ID from .env).
- HTTP:
http://SERVER-IP:8001/login.html - HTTPS:
https://SERVER-IP/login.html
Login with credentials from your .env file (ADMIN_USERNAME, ADMIN_PASSWORD).
| Variable | Purpose | Example | Required |
|---|---|---|---|
DISCORD_TOKEN |
Bot authentication token | AaBbCcDdEeFfGgHhIiJjKk... |
✅ |
CLIENT_ID |
Discord application ID | 1234567890987654321 |
✅ |
ALLOWED_GUILD_ID |
Restrict bot to one server | 1234567890987654321 |
✅ |
DB_URI |
MongoDB connection string | mongodb://mongo:27017/botdb |
✅ |
ADMIN_USERNAME |
Dashboard login username | admin |
✅ |
ADMIN_PASSWORD |
Dashboard login password | MyS3curePass! |
✅ |
JWT_SECRET |
JWT signing secret (long random string) | AaBbCcDdEeFfGgHhIiJjKk... |
✅ |
ADMIN_UI_PORT |
Dashboard port (inside container) | 8001 |
Optional (default: 8001) |
METRICS_BASIC_USER |
Metrics API auth username | grafana |
Optional |
METRICS_BASIC_PASS |
Metrics API auth password | changeMe! |
Optional |
- Go to Discord Developer Portal
- Create a New Application
- Go to "Bot" → Click "Add Bot"
- Under TOKEN, click "Copy" and paste into
DISCORD_TOKENin.env - Go to "OAuth2" → "URL Generator"
- Scopes:
bot - Permissions:
Administrator(or scope:applications.commands,send_messages,manage_roles,manage_channels)
- Scopes:
- Copy the generated URL and use it to invite the bot to your server
- Copy your Guild ID (right-click server → Copy Server ID) → paste into
ALLOWED_GUILD_ID
The bot uses Discord's slash commands for all interactions. Commands are admin-restricted unless otherwise noted.
Verify a student and assign them a verification number and role.
- Permissions: Server Owner, Team Role
- Result: Student receives verified role, verification number assigned
- Database: Stores name, Discord tag, ID, and verification date
Remove verification status and associated roles from a student.
- Permissions: Server Owner, Team Role
- Result: Verified role removed, database record deleted
Issue a warning to a verified student.
- Permissions: Server Owner, Team Role
- Requirements: User must be verified
- Notifications: Sends DM to user notifying them
- Database: Stores reason, issuer, timestamp
Add or update contextual notes about a student.
- Permissions: Server Owner, Team Role
- Requirements: User must be verified
- Use Cases: Behavioral notes, accommodations, special circumstances
Display a verified user's real name and recent warnings (privileged view).
- Permissions: Everyone can view basic info; Server Owner/Team see full details (comments + warnings)
- Requires: User must be verified
- Shows: Name, Discord tag, last 3 warnings with issuer and date
Add a word to the banned words filter.
- Permissions: Server Owner, Team Role
- Effect: Future messages containing this word trigger admin notifications
Remove a word from the banned words filter.
- Permissions: Server Owner, Team Role
Configure roles for different user statuses.
- Permissions: Server Owner, Administrator, Team Role
- Options:
teamrole: Users with this role can manage botverifiedrole: Role given to verified studentsonjoinrole: Role auto-assigned to new members (removed upon verification)
- Note: At least one role required
Set the channel where banned word alerts are sent.
- Permissions: Server Owner, Administrator, Team Role
- Alerts Include: User mention, channel, message preview, quick action buttons
Display the current server language setting.
- Permissions: Everyone
Change the server's language (affects all bot responses and messages).
- Permissions: Administrator, Server Owner, Team Role
- Options:
en(English),de(German) - Effect: Updates all localized messages in real-time
Create a ticket panel with a button for students to open support or verification requests.
- Type:
supportorverify - Category: Category where new tickets will be created
- Overrides: Optional custom title, description, button text
- Features:
- Auto-creates private channels per user
- Team members automatically get access
- Closed tickets remain visible to team only
- Messages are language-tracked for automatic translation
The web UI at /dashboard provides:
- Search: Filter by Discord tag, first name, or last name
- View All Verified Students: Full list with verification numbers and dates
- Edit Comments: Click comment to edit inline
- Delete Warnings: Remove specific warnings with confirmation
- Warning History: View all warnings per student with issuer and date
- Export CSV: Download all verified students and warnings
- Import CSV: Bulk import student data (upsert by Discord ID)
- CSV Columns:
verificationNumber,discordTag,discordId,firstName,lastName,comment,warnings(JSON),verifiedAt
- Search Bar: Real-time filtering
- Dark Mode Toggle: User preference stored in localStorage
- Logout: Clear session and return to login
- JWT Authentication: Token-based session (1 hour expiry)
- HTTPS Ready: Works with Nginx reverse proxy and SSL
- HttpOnly Cookies: Tokens stored securely, not accessible to JavaScript
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/api/login |
POST | None | Authenticate with username/password |
/api/verified-users |
GET | JWT | Fetch all verified users |
/api/remove-warning/:discordId/:index |
DELETE | JWT | Delete specific warning |
/api/update-comment/:discordId |
PUT | JWT | Update user comment |
/api/export-users |
GET | JWT | Download CSV of all users |
/api/import-users |
POST | JWT | Upload and import CSV |
/api/metrics/users-per-day |
GET | BasicAuth | Cumulative verification metrics (JSON/CSV) |
Ticket panels allow students to create support requests or verification channels.
- Admin Creates Panel:
/ticketpanel support #support-tickets - Button Appears: Students see a button to "Open Ticket"
- Private Channel Created: Named
support-[username]orverify-[username] - Permissions:
- Student can view and message
- Team role members auto-added
- Others cannot see the channel
- Closing: Student or team clicks "Close Ticket"
- Channel name becomes
🔒-[original-name] - Student loses access (team retains access for records)
- Channel name becomes
Channels store metadata in the topic:
status:open; type:support; opener:123456789
This allows the bot to track ticket state and ownership.
Ticket messages are automatically tracked and updated when server language changes.
OpenSDB supports multiple languages. Built-in: English and German.
Each server has its own language setting (stored in MongoDB).
- Default: English
- Change Command:
/language set deor/language set en
- Create
/src/locales/[lang].json(e.g.,fr.jsonfor French) - Add language code to
SUPPORTEDset insrc/utils/i18n.js - Add subcommand choices in
/src/commands/setlanguage.js - Restart the bot
{
"language": { "current": "...", "setSuccess": "..." },
"errors": { "noPermission": "..." },
"ticketPanel": {
"support": { "title": "...", "desc": "...", "button": "..." },
"verify": { ... }
},
...
}Use placeholders: {userName}, {reason}, etc.
- Node.js 18+: nodejs.org
- MongoDB 7+: mongodb.com/try or via Docker
- Git
# 1. Clone and install
git clone https://github.com/MoritzKlasen/OpenSDB.git
cd OpenSDB
npm install
# 2. Create .env (same as production)
nano .env
# 3. Start MongoDB locally (optional, if not using Docker)
# On Linux (Debian/Ubuntu):
sudo apt-get install -y mongodb
sudo systemctl start mongodb
sudo systemctl enable mongodb
# 4. Run the bot
node src/index.js
# 5. In another terminal, run the admin UI
node src/admin-server.js
# Dashboard available at http://localhost:8001OpenSDB/
├── src/
│ ├── index.js # Bot entry point
│ ├── admin-server.js # Web UI server
│ ├── loadCommands.js # Command loader
│ ├── deploy-commands.js # Slash command registration
│ ├── commands/ # Slash command definitions
│ │ ├── verify.js
│ │ ├── warn.js
│ │ ├── ticketpanel.js
│ │ └── ...
│ ├── events/ # Discord event handlers
│ │ ├── handleInteractions.js # Button/modal/command logic
│ │ ├── handleBannedWords.js # Message filtering
│ │ └── guildMemberAdd.js # Auto-role on join
│ ├── database/
│ │ ├── connect.js # MongoDB connection
│ │ └── models/ # Mongoose schemas
│ │ ├── VerifiedUser.js
│ │ ├── ServerSettings.js
│ │ ├── BannedWord.js
│ │ └── LocalizedMessage.js
│ ├── utils/
│ │ ├── i18n.js # Translation helper
│ │ ├── localizedSend.js # Send + track messages
│ │ ├── ticketPanelRenderer.js
│ │ └── updateLocalizedMessages.js
│ ├── admin-ui/
│ │ ├── login.html # Login page
│ │ ├── dashboard.html # Main dashboard
│ │ └── assets/
│ │ ├── dashboard.js # Dashboard frontend logic
│ │ ├── style.css # Styling
│ │ └── favicon.png
│ └── locales/
│ ├── en.json # English translations
│ └── de.json # German translations
├── docker-compose.yml # Service orchestration
├── Dockerfile.bot # Bot container
├── Dockerfile.web # Web UI container
├── nginx/
│ ├── nginx.conf # Reverse proxy config
│ ├── ssl_params.conf # SSL/TLS settings
│ ├── openssl.cnf # Certificate generation config
│ └── certs/ # (Git-ignored) SSL certificates
├── package.json # Dependencies
├── .env # (Git-ignored) Configuration
└── README.md
- Commands:
/src/commands/*.js– Add new slash commands here - Events:
/src/events/*.js– Modify bot behavior - Locales:
/src/locales/*.json– Add/edit translations - Styles:
/src/admin-ui/assets/style.css– Dashboard appearance - Database Models:
/src/database/models/*.js– Extend data schema
Bot not responding to commands:
- Verify bot is online:
docker compose ps(bot service running) - Check logs:
docker compose logs bot --tail 20 - Ensure bot has permissions in your server: Settings → Integrations → Bot
- Verify
DISCORD_TOKEN,CLIENT_ID,ALLOWED_GUILD_IDin.env
"Invalid Token" errors:
- Copy token from Discord Dev Portal (not application ID)
- Regenerate token if exposed
MongoDB connection fails:
docker compose logs mongo
docker compose exec mongo mongosh # Test connectionLost data:
- Data persists in Docker volume:
db:/data/db - To backup:
docker compose exec mongo mongodump --out /tmp/backup
Can't access dashboard:
- Check if web service is running:
docker compose ps web - Try:
docker compose logs web - Verify
ADMIN_UI_PORTmatches in.env - Default URL:
http://localhost:8001(local) orhttp://IP:8001(remote)
Login fails:
- Verify
ADMIN_USERNAMEandADMIN_PASSWORDin.envmatch login attempt - Check JWT_SECRET is set and consistent
- Clear browser cookies: Settings → Privacy → Cookies → Clear all
Certificate problems:
# Regenerate certificates
rm -rf nginx/certs/*
cd nginx/certs
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout opensdb.key -out opensdb.crt -config ../openssl.cnf
cd ../..
docker compose restart nginxMixed content warnings:
- Ensure
.envdoesn't havehttp://URLs - Nginx config should redirect HTTP → HTTPS
"Address already in use":
# Find process using port
lsof -i :8001 # macOS/Linux
netstat -ano | findstr :8001 # Windows
# Kill process or change port in docker-compose.ymlPorts required (can be changed in config):
80– HTTP (Nginx)443– HTTPS (Nginx)8001– Admin UI (can be modified)27017– MongoDB (internal only)
Check resource usage:
docker statsAdjust limits in docker-compose.yml:
deploy:
resources:
limits:
memory: 256M # Increase if bot is slow
cpus: "0.50" # Increase if hitting CPU limitView logs in real-time:
docker compose logs -f bot # Bot logs
docker compose logs -f web # Admin UI logs
docker compose logs -f nginx # Web server logs
docker compose logs -f mongo # Database logs
docker compose logs -f # All servicesEnable verbose logging:
Add NODE_ENV=development to .env (some modules log more)
- Admin Credentials: Use strong passwords (16+ characters, mixed case, numbers, symbols)
- JWT Secret: Generate with
openssl rand -base64 32 - Never commit
.env: Ensure.gitignoreincludes it - Token Expiration: Admin sessions expire after 1 hour; requires re-login
- HTTPS/SSL: Use self-signed certificates for development, proper CA certificates for production
- Nginx Reverse Proxy: Handles TLS termination
- Docker Network: Services communicate over internal bridge network
- Port Exposure: Only expose ports 80/443; keep MongoDB port 27017 internal
- Grant Minimal Permissions: Only grant roles the bot actually needs
- Role Positioning: Bot's highest role must be above roles it assigns/removes
- Channel Permissions: Set explicitly; don't rely on @everyone permissions
- Student Data: Stored in MongoDB; ensure server is secure
- Message Logging: Bot can see all messages in monitored channels
- GDPR Compliance: Implement data deletion on
/unverify(currently implemented) - Comment Visibility: Only team members and owner see comments/warnings
- Case Insensitive: Filters match regardless of capitalization
- Partial Matching: Detects words even within other words (e.g., "bad" in "badly")
- Notification Only: Filter notifies admins; doesn't auto-delete (gives context)
- Update Dependencies:
npm updateweekly/monthly - Backup Database: Regular MongoDB exports
- Monitor Logs: Check logs for errors, warnings
- Review Warnings: Periodically audit issued warnings and comments
- Fork & Clone: Create a GitHub fork and clone locally
- Create Branch:
git checkout -b feature/my-feature - Code Style: Use existing code patterns (consistent formatting)
- Test Locally: Run with
npm install && node src/index.js - Commit:
git commit -m "Add [feature]: description" - Push & PR: Push to fork and create pull request
- 🌍 New Language Support: Add locales (e.g., French, Spanish)
- 🎨 UI Improvements: Enhance dashboard design/UX
- 🔧 Bug Fixes: Report and fix issues
- 📖 Documentation: Improve guides and examples
- ✨ New Features: Suggest features via Issues
Use GitHub Issues to report bugs or request features:
- Bug Report: Use template
- Feature Request: Use template
OpenSDB is open source under the ISC License. Modify and use freely for educational purposes.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with ❤️ by McScheleba
Last Updated: January 2026