Selbst hosten
Bot, Website und Datenbank selbst betreiben, für die Entwicklung oder für deine eigene Community.
Um Roleplay+ Tickets zu nutzen, brauchst du diese Seite nicht. Die Seite ist für Betreiber, die ihre eigene Instanz laufen lassen, und für die Entwicklung.
#Voraussetzungen
- Node.js 20.11 oder neuer
- Docker für PostgreSQL oder PostgreSQL 15 oder neuer
- Eine Discord-Anwendung mit einem Bot-Nutzer
#Aufbau des Repositorys
| Ordner | Inhalt |
|---|---|
apps/bot | Der discord.js-Bot: Panels, Tickets, Transkripte, Automationen, Befehle und eine interne HTTP-API |
apps/web | Next.js-Website, Doku, Dashboard, Discord-Anmeldung, Abrechnung und die Transkript-Ansicht |
packages/shared | Konfigurationsschemas mit Standardwerten, die Variablen-Engine, Pläne und der API-Vertrag |
packages/db | Datenbankschema, Migrationen und Demo-Daten |
Der Bot hält die Verbindung zu Discord. Die Website liest und schreibt Einstellungen in der Datenbank. Über die interne API des Bots holt sie Live-Daten des Servers und lässt ihn Panels senden.
#Discord-Anwendung
- Erstell eine Anwendung im Discord Developer Portal (öffnet in einem neuen Tab).
- Erstell unter Bot den Bot und kopier sein Token. Schalt die privilegierten Intents Server Members und Message Content ein. Damit sieht der Bot die Mitglieder des Servers und den Text von Nachrichten. Präfix-Befehle, eigene Befehle, Automationen, Transkripte und die Prüfung Ersteller hat den Server verlassen brauchen sie.
- Kopier unter OAuth2 die Client-ID und das Client-Secret. Füg die Redirect-URL
${PUBLIC_URL}/api/auth/callbackhinzu, für die lokale Entwicklunghttp://localhost:3000/api/auth/callback.
#Konfiguration
Kopier .env.example nach .env im Hauptverzeichnis des Repositorys. Beide Apps lesen diese Datei.
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
DISCORD_TOKEN=
# Optional: Slash-Befehle sofort und nur auf einem Server registrieren
DISCORD_DEV_GUILD_ID=
DATABASE_URL=postgres://tickets:tickets@localhost:5433/tickets
PUBLIC_URL=http://localhost:3000
# 32 oder mehr zufällige Zeichen: openssl rand -hex 32
SESSION_SECRET=
# Discord-Nutzer-IDs mit Zugriff auf die Admin-Seite der Plattform
PLATFORM_ADMINS=
BOT_API_URL=http://localhost:4100
BOT_API_PORT=4100
BOT_API_SECRET=
# Verschlüsselt Whitelabel-Bot-Tokens; Bot und Web brauchen denselben Wert
ENCRYPTION_KEY=
# Optional: Abrechnung
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_PRICE_MONTHLY=
STRIPE_PRICE_YEARLY=
STRIPE_PRICE_WHITELABEL_MONTHLY=
STRIPE_PRICE_WHITELABEL_YEARLY=
# Optional: Extras für die Website
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
NEXT_PUBLIC_SUPPORT_URL=SESSION_SECRET verschlüsselt die Discord-Tokens angemeldeter Nutzer und signiert ihre Sitzungen. BOT_API_SECRET schützt die interne API zwischen Website und Bot. Nutze für beide lange Zufallswerte und leg sie nie im Repository ab.
ENCRYPTION_KEY verschlüsselt die Tokens von Whitelabel-Bots. Ohne den Wert wird SESSION_SECRET genutzt. Bot und Website brauchen denselben Wert. Änderst du ihn später, lassen sich gespeicherte Tokens nicht mehr lesen, und Kunden müssen sie neu einfügen.
#Lokale Entwicklung
cp .env.example .env
docker compose up -d db # PostgreSQL auf localhost:5433
npm install
npm run db:migrate
npm run commands:deploy # registriert die Slash-Befehle
npm run dev # Bot und Website, Website auf Port 3000Ohne DISCORD_DEV_GUILD_ID kann es bis zu einer Stunde dauern, bis Discord neue Slash-Befehle überall zeigt.
Um dir das Dashboard ohne Discord-Anwendung anzusehen, setz DEV_LOGIN=1, führ npm run seed aus und öffne http://localhost:3000/api/auth/dev. Diese Anmeldung funktioniert nicht in Produktion.
#Produktion
docker compose --profile prod up -d --buildDas baut die Images, führt die Migrationen einmal aus und startet den Bot und die Website auf Port 3000. Stell einen Reverse Proxy mit TLS vor die Website und setz PUBLIC_URL auf ihre öffentliche Adresse. Nur die Website muss aus dem Internet erreichbar sein. Die Bot-API bleibt im Docker-Netzwerk.
Hochgeladene Panel-Bilder liegen unter ${PUBLIC_URL}/media/…, und Discord lädt sie von dort. Sie erscheinen nur in Discord, wenn PUBLIC_URL eine öffentliche https-Adresse ist. Lokal lässt der Bot sie weg, Bildlinks funktionieren trotzdem.
#Abrechnung mit Stripe
Die Abrechnung ist optional. Ohne sie zeigt die Bezahlseite Bald verfügbar, und Premium-Schlüssel von der Admin-Seite funktionieren trotzdem.
- Leg in Stripe ein Produkt mit einem monatlichen und einem jährlichen Preis an. Trag die Preis-IDs in
STRIPE_PRICE_MONTHLYundSTRIPE_PRICE_YEARLYein, den geheimen Schlüssel inSTRIPE_SECRET_KEY. - Füg einen Webhook-Endpunkt
${PUBLIC_URL}/api/billing/webhookmit den Ereignissencheckout.session.completed,customer.subscription.created,customer.subscription.updated,customer.subscription.deletedundinvoice.paidhinzu. - Trag das Signing-Secret des Webhooks in
STRIPE_WEBHOOK_SECRETein. - Für das Whitelabel-Add-on legst du ein zweites Produkt mit einem Monats- und einem Jahrespreis an und trägst die Preis-IDs in
STRIPE_PRICE_WHITELABEL_MONTHLYundSTRIPE_PRICE_WHITELABEL_YEARLYein.
#Skalieren
Die Web-App kann beliebig viele Replikas haben. Der Bot skaliert in Clustern: Jeder Bot-Container betreibt einen Teil der Shards des Haupt-Bots und einen Teil der Whitelabel-Bots, und die Web-App schickt jede Anfrage an den Container, der den Server bedient.
- Setz
BOT_CLUSTER_COUNTauf die Zahl der Bot-Container, zum Beispiel3. - Setz
DISCORD_SHARD_COUNTauf eine feste Shard-Zahl, ein Vielfaches der Cluster-Zahl und mindestens eine pro 2.500 Server, zum Beispiel6. - Lass den Bot-Dienst mit so vielen Replikas und derselben Umgebung laufen. Jeder Container sucht sich selbst einen freien Cluster-Platz.
- Gib der Web-App dieselben zwei Werte und deploy beide neu.
Der Plattform-Admin zeigt jeden Cluster unter Bots. Einrichtung in Dokploy, Rolling Deploys und Details stehen in docs/deployment.md im Repository.
Wenn du eine öffentliche Instanz betreibst, bist du der Betreiber. Füll die Vorlagen für Impressum, Datenschutzerklärung und Nutzungsbedingungen mit deinen Angaben aus, bevor du die Instanz für andere öffnest.