Zum Inhalt springen
myvpsguide

Discord-Bot dauerhaft betreiben: Unit, Token, Neustartschleifen

Einen Bot als systemd-Dienst aufsetzen, den Token sicher ablegen, Neustartschleifen verhindern, die zur Sperre führen und merken, wenn der Bot online aussieht, aber nichts mehr tut.

veröffentlicht 19.08.2026
3 min lesezeit
fortgeschritten

Ein Discord-Bot ist ein langlebiger Prozess mit einer offenen Verbindung. Das klingt anspruchslos und ist es auch, bis er nachts abstürzt, in eine Neustartschleife läuft und die Plattform die Verbindungen deines Servers zeitweise abweist.

Diese Anleitung baut den Bot so auf, dass das nicht passiert.

Grundlage: eigener Benutzer, feste Abhängigkeiten#

useradd -r -m -d /opt/botti -s /usr/sbin/nologin botti
cd /opt/botti && sudo -u botti git clone <repo> app
# Python
sudo -u botti python3 -m venv /opt/botti/venv
sudo -u botti /opt/botti/venv/bin/pip install -r app/requirements.txt

# Node
sudo -u botti npm ci --omit=dev --prefix /opt/botti/app

npm ci statt npm install und eine gepinnte requirements.txt sind hier kein Feinschliff: Ein Bot, der nach einem Neustart plötzlich eine andere Bibliotheksversion zieht, fällt genau dann aus, wenn niemand hinsieht.

Der Token gehört nicht ins Repository#

Der Bot-Token ist das Passwort. Wer ihn hat, steuert den Bot, mit allen Rechten, die er auf den Servern hat.

install -o botti -g botti -m 600 /dev/null /etc/botti.env
cat > /etc/botti.env <<'ENV'
DISCORD_TOKEN=…
DATENBANK_URL=…
ENV
chmod 600 /etc/botti.env
Einmal veröffentlicht heißt sofort ungültig machen

Ein Token, der versehentlich in einem Repository, in einem Screenshot oder in einer Protokollzeile gelandet ist, wird nicht durch Löschen des Commits wieder geheim, er ist in der Historie und in fremden Kopien. Der einzige richtige Schritt ist, ihn im Entwicklerportal neu zu erzeugen. Automatisierte Sucher finden veröffentlichte Token in Minuten.

Und: Der Token darf nicht ins Protokoll. Ein print(config) beim Start schreibt ihn ins Journal, wo er dann monatelang steht.

Die systemd-Unit, mit Bremse#

# /etc/systemd/system/botti.service
[Unit]
Description=Discord-Bot
After=network-online.target
Wants=network-online.target
# Bremse: mehr als 5 Starts in 5 Minuten = Dienst bleibt aus
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Type=simple
User=botti
WorkingDirectory=/opt/botti/app
EnvironmentFile=/etc/botti.env
ExecStart=/opt/botti/venv/bin/python -u bot.py
Restart=on-failure
RestartSec=15

# Speicherleck begrenzen, statt den Server mitzureißen
MemoryMax=512M

# Härtung: der Bot braucht nichts davon
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/botti/daten

[Install]
WantedBy=multi-user.target
systemctl daemon-reload && systemctl enable --now botti
journalctl -u botti -f
Warum RestartSec und StartLimit zusammengehören

Ein falscher Token oder eine kaputte Abhängigkeit lässt den Bot beim Start scheitern. Mit Restart=always und ohne Bremse versucht er es dutzendfach pro Minute, jeder Versuch baut eine Verbindung zur Plattform auf. Deren Antwort darauf ist eine zeitweilige Sperre, und die trifft dann alle Bots auf derselben IP-Adresse. Fünfzehn Sekunden Pause und eine Obergrenze verhindern das.

Der Unterschied zwischen „läuft“ und „funktioniert“#

Ein Bot kann in der Prozessliste stehen, in Discord als online erscheinen und trotzdem nichts mehr tun: Die Ereignisschleife hängt, eine Aufgabe blockiert, die Datenbankverbindung ist tot.

Deshalb ein Lebenszeichen aus dem Bot heraus, nicht von außen:

# im Bot, alle 60 Sekunden aus der laufenden Schleife heraus
async def herzschlag():
    while True:
        pfad.write_text(str(int(time.time())))
        await asyncio.sleep(60)
# außen: Datei älter als 3 Minuten = etwas hängt
find /opt/botti/daten/herzschlag -mmin +3 && echo "Bot antwortet nicht"

Diese Prüfung gehört in dieselbe Überwachung wie der Rest (Monitoring aufsetzen). Ein reiner Prozess-Check beantwortet die falsche Frage.

Grenzen der Plattform respektieren#

Discord begrenzt, wie oft ein Bot Anfragen stellen darf. Die Bibliotheken halten sich in der Regel daran, wenn man sie lässt:

  • Antwortcode 429 ernst nehmen und die mitgelieferte Wartezeit einhalten, nicht sofort erneut versuchen.
  • Nachrichten nicht in Schleifen verschicken; Sammelaktionen entzerren.
  • Ab einer bestimmten Servergröße verlangt die Plattform Aufteilung auf mehrere Verbindungen (Sharding). Die Bibliothek meldet das rechtzeitig, die Meldung nicht überlesen.
# Wie oft läuft der Bot in Grenzen? Journal zählt mit:
journalctl -u botti --since "24 hours ago" | grep -ci "rate limit"

Mehrere Bots auf einer Maschine#

Ein Benutzer, ein Verzeichnis, eine Unit pro Bot. Das kostet fünf Minuten mehr und verhindert, dass ein Absturz oder ein kompromittierter Bot an die Daten des anderen kommt.

Wer lieber Container nimmt: Dieselbe Trennung, andere Werkzeuge und bei Podman läuft der Bot ohne Root-Rechte, was hier gut passt (Podman ohne Root).

Häufige Fragen#

Reicht ein Raspberry Pi zu Hause?#

Technisch ja. Praktisch hängt der Bot dann an deiner Internetverbindung, deiner Stromversorgung und deiner SD-Karte. Für einen Bot, den andere benutzen, ist ein VPS die ruhigere Wahl.

Wie viel RAM braucht ein Bot?#

Meist wenig, die Größenordnung liegt bei einigen hundert Megabyte, je nach Bibliothek und Zahl der Server. MemoryMax in der Unit begrenzt den Schaden, wenn ein Leck auftritt.

Wie aktualisiere ich ohne Ausfall?#

Kurz gar nicht: Ein Neustart dauert Sekunden. Wer es sauberer will, wartet auf einen Moment ohne laufende Interaktion und startet dann, echte unterbrechungsfreie Updates lohnen sich für die wenigsten Bots.

Was ist mit Datenbank?#

Ein Bot mit Zustand braucht eine. SQLite reicht für viele Fälle; sobald mehrere Prozesse schreiben, wird es ein Serverdienst (PostgreSQL oder MariaDB).

Kann ich den Bot in eine Zeitsteuerung legen?#

Für Aufgaben, die nur stündlich laufen, ja, dann ist ein systemd-Timer der richtige Weg statt eines dauerhaften Prozesses. Für Reaktionen auf Nachrichten muss die Verbindung stehen bleiben.

Kurz gesagt#

  • Eigener Benutzer, feste Abhängigkeitsversionen, Token in einer 600-Datei.
  • StartLimitBurst plus RestartSec, sonst führt der Absturz zur Sperre.
  • MemoryMax begrenzt Speicherlecks auf den Bot statt auf den Server.
  • Lebenszeichen aus der Ereignisschleife, nicht Prozess-Check von außen.
  • Ein veröffentlichter Token wird neu erzeugt, nicht gelöscht.
MRMedia

Geschrieben aus dem laufenden Betrieb: MRMedia betreibt eigene Proxmox- Hosts, einen Backup-Server und Kundendienste in der EU. Fehler in einer Anleitung sind Fehler im eigenen Betrieb. Korrekturen bitte über Discord.