DeskHub
DeskHub ist ein vollständiges, selbst gehostetes Helpdesk-System. Kunden erstellen und verfolgen Supportanfragen über ein individuell gestaltbares Kundenportal. Das Support-Team bearbeitet Tickets, E-Mails, Aufgaben und Wissensartikel zentral über die Weboberfläche, die Windows-App oder die Android-App.
Aktuelle Versionen: Server 1.0.66 · Chrome-Erweiterung 2.0.0 · WordPress-Plugin 1.2.2 · Android-App 3.4.5 · Windows-Programm 2.11.1 · Minecraft-Plugin 1.1.0
Diese Anleitung ist auch für Einsteiger geeignet. Über das Inhaltsverzeichnis kommt ihr direkt zum gewünschten Thema. Die Abschnitte Plugins entwickeln und API und Webhooks richten sich an Entwickler.
Funktionen
- Kundenportal mit Ticket-Erstellung, Ticketstatus, Wissensdatenbank und frei gestaltbaren Seiten
- Digitaler Assistent im Kundenportal: beantwortet Fragen aus Wissensdatenbank und eigenen Antworten, erstellt auf Wunsch das Ticket, mit Fragen-Log, Rückmeldung 👍/👎 und eigenen Wortgruppen (ohne externen KI-Dienst)
- Mitarbeiterbereich mit Ticketlisten, Filtern, gespeicherten Ansichten, Zuweisungen und internen Notizen
- Wiedervorlage („auf später legen“), Beobachter, ähnliche Tickets und Artikel beim Bearbeiten und Erinnerung an Kunden vor dem automatischen Schließen
- Automatik: Tickets beim Eingang oder Öffnen zuweisen, Status automatisch auf „Offline“, automatische Abmeldung, Ticket-Sperre gegen Doppelbearbeitung
- E-Mail: Versand über SMTP (auch pro Absenderadresse), automatischer Ticketimport über IMAP
- Abteilungen, Teams und Rollen mit Berechtigungen, die pro Abteilung unterschiedlich sein können
- SLA-Pläne, Eskalations- und Ticketregeln, Geschäftszeiten und Feiertage
- Berichte mit frei zusammenstellbarem Bericht-Baukasten und CSV-Export
- Integrationen: API-Schlüssel, Webhooks und eine Schnittstelle zum Anlegen von Tickets aus anderen Systemen
- Überwachung: Warnung bei Störungen des E-Mail-Abrufs, Verbindungsanzeige in den Apps
- Plugins zum Nachrüsten eigener Funktionen
- Update-Funktion für Programmdateien und Datenbank, Backups und Datenschutz-Funktionen
- Import aus osTicket inklusive Abteilungen, Nachrichten und Anhängen
- Windows-Programm und Android-App mit hellem und dunklem Design, Push-Benachrichtigungen, Verwaltung nach Rechten und Android-Widget in drei Größen, direkt aus dem Mitarbeiterbereich herunterladbar
- Minecraft-Plugin (Paper, Spigot, BungeeCord in einer Datei) zum Melden von Spielern und Problemen als Ticket
- Chrome-Erweiterung (auch Edge und Brave; Windows, Mac, Linux) mit Ticket-Ansicht, Antworten, Aufgaben, Status, Zähler und Benachrichtigungen; Windows-Programm auch für Linux und Mac (Mac nur selbst zu bauen)
Einblicke
Demo-Video (mit Beispieldaten)
Klick auf die Vorschau öffnet das Video (deskhub-demo.mp4, Full HD, 30 Bilder pro Sekunde, etwa 3:50 Minuten, mit passender Musik). Alle Namen, Tickets und Antworten darin sind erfunden. Es ist eine echte Aufnahme mit Mauszeiger, Tippen und Scrollen: Kundenportal mit digitalem Assistenten, Anmeldung, Übersicht, Ticketliste, Ticket mit Wiedervorlage und Beobachtern, Verwaltung des Assistenten mit Fragen-Log und das Windows-Programm.
Musik und Ton: Die Musik folgt den Kapiteln des Videos (ruhiger Start, Zupf-Arpeggio im Kundenportal, Beat im Mitarbeiterbereich, voller Klang beim Assistenten, ruhiger im Windows-Programm, Riser und großer Schlussakkord zum Abspann). Dazu kommen leise Tipp-, Klick- und Übergangsgeräusche genau zu den Zeitpunkten der Aufnahme. Alles wird beim Bauen des Videos selbst erzeugt (tools/demo-video/make_music.js): reine Synthese aus einer einfachen Akkordfolge, ohne Aufnahmen, Samples oder fremde Melodien. Sie enthält damit nichts von Dritten und ist nicht bei GEMA oder einer anderen Verwertungsgesellschaft angemeldet. Wer das Stück weitergibt, sollte es auch nicht anmelden.
Digitaler Assistent im Kundenportal
Übersicht im Mitarbeiterbereich
Ticket mit Wiedervorlage, Beobachtern und passenden Artikeln
Fragen-Log des Assistenten
Windows-Programm
Neues Ticket erstellen
Kunden-Login
Mitarbeiter-Login
Inhaltsverzeichnis
- Was ist was?
- Erstinstallation
- Schnellstart
- Anmelden
- Für Kunden: Ein Ticket erstellen
- Für Mitarbeiter: Tickets bearbeiten
- Für Admins: Das Adminportal
- E-Mails versenden (SMTP)
- E-Mails automatisch abrufen (Postfächer)
- Automatisierung (Cronjobs)
- Status und automatisch Offline
- Digitaler Assistent
- Wiedervorlage, Beobachter, ähnliche Tickets, Kundenerinnerung
- Ticket-Sperre und automatische Zuweisung
- SLA-Pläne
- Gespeicherte Ansichten
- Berichte und Bericht-Baukasten
- Integrationen: API-Schlüssel und Webhooks
- Rechte und Rollen
- Überwachung und Störungsmeldungen
- Windows-App und Android-App
- System-Update und Datenbank-Update
- Import aus osTicket
- Plugins verwenden
- Plugins entwickeln
- Plugin- und Theme-Webseite
- API und Webhooks (für Entwickler)
- Sicherheit und Datenschutz
- Backup
- Demo-Video neu erzeugen
- Hilfe, etwas funktioniert nicht
Was ist was?
DeskHub hat drei Bereiche:
| Bereich | Für wen? | Adresse |
|---|---|---|
| Kundenportal | Eure Kunden | eure-domain.de/ |
| Mitarbeiterbereich | Support-Team und Admins | eure-domain.de/staff/ |
| Apps | Support-Team und Admins am PC und unterwegs | Windows-App, Android-App, Chrome-Erweiterung (WordPress-Plugin und Minecraft-Plugin als Download) |
Ein Admin-Konto ist ein Mitarbeiter-Konto mit der Rolle „Admin“. Beim Anmelden gibt es keinen Unterschied, nur bei dem, was man danach sieht.
Erstinstallation
Voraussetzungen (im Zweifel euren Hosting-Anbieter fragen):
- PHP 8.2 oder neuer
- Eine MySQL-Datenbank (für kleine Installationen und Tests geht auch SQLite)
- PHP-Erweiterung
imap, wenn E-Mails automatisch abgerufen werden sollen - PHP-Erweiterung
zipfür Theme-Upload, Plugin-Installation und System-Update per ZIP
So geht’s:
- Alle DeskHub-Dateien auf den Server hochladen (zum Beispiel per FTP).
- Im Browser
eure-domain.de/install/aufrufen. - Dem Assistenten folgen: Datenbank-Zugangsdaten, Website-Name, erstes Admin-Konto.
- Danach unter
eure-domain.de/staff/login.phpmit dem neuen Konto anmelden.
Der Assistent prüft zuerst die Voraussetzungen (PHP 8.2, Datenbanktreiber, openssl, beschreibbare Ordner; curl, zip und HTTPS sind empfohlen). Das Admin-Passwort braucht mindestens 10 Zeichen mit Groß- und Kleinbuchstaben, Ziffer und Sonderzeichen. Zum Schluss spielt er alle Datenbank-Änderungen ein, erzeugt den Verschlüsselungsschlüssel und sperrt sich selbst. Fehler bei der Datenbankverbindung werden verständlich erklärt (falsches Passwort, Server nicht erreichbar, Datenbank fehlt).
Ganz wichtig: Löscht anschließend den Ordner install vom Server (oder sperrt ihn). Der Assistent überschreibt eine bestehende Installation nie: Gibt es schon eine config/config.php mit Datenbank und Mitarbeiterkonten, zeigt er „Bereits installiert“. Wollt ihr bewusst neu anfangen, legt zuerst ein Backup an und entfernt dann config/config.php, install/.installed und die Datenbank (bei SQLite die Datei database/deskhub.sqlite).
Schnellstart
Direkt nach der Installation läuft DeskHub, kann aber noch keine E-Mails verschicken oder abrufen. Arbeitet diese Liste einmal von oben nach unten ab:
| # | Was | Wo | Warum |
|---|---|---|---|
| 1 | Abteilungen anlegen (z. B. „Technik“, „Vertrieb“) | Adminportal → Abteilungen | Jedes Ticket gehört zu genau einer Abteilung |
| 2 | SMTP einrichten (E-Mail-Versand) | Adminportal → Einstellungen → E-Mail | Damit Kunden Bestätigungen bekommen |
| 3 | Postfach einrichten (E-Mail-Abruf, optional) | Adminportal → Postfächer (Abruf) | Damit eingehende Mails zu Tickets werden |
| 4 | Automatisierung prüfen | Adminportal → Einstellungen → Cron-Jobs | Damit Versand, Abruf und Prüfungen von selbst laufen |
| 5 | Mitarbeiter anlegen | Adminportal → Mitarbeiter | Damit nicht nur ihr allein Tickets bearbeitet |
Anmelden
Es gibt zwei getrennte Logins:
- Kunden melden sich unter
/login.phpan (oder erstellen ohne Konto ein Ticket). - Mitarbeiter und Admins melden sich unter
/staff/login.phpan.
Ein Kunden-Konto hat keinen Zugang zum Mitarbeiterbereich und umgekehrt.
Für Kunden: Ein Ticket erstellen
- Auf der Startseite „Neues Ticket eröffnen“ wählen.
- Name, E-Mail-Adresse und Anliegen eintragen.
- Nach dem Absenden gibt es eine Ticketnummer auf der Seite und per E-Mail.
- Mit dieser Nummer lässt sich jederzeit unter „Ticketstatus überprüfen“ nachsehen, ob es eine Antwort gibt, auch ohne Konto.
Für Mitarbeiter: Tickets bearbeiten
Im Mitarbeiterbereich gibt es links im Menü:
- Übersicht: in vier Reitern: Überblick (offene, euch zugewiesene, nicht zugewiesene und überfällige Tickets, euer Status und das Team, Gesamtzahlen), Verlauf (Ticketaktivität, SLA-Einhaltung, Status und Priorität), Auswertung (nach Abteilung, Thema und Mitarbeiter, mit CSV-Export) und Zufriedenheit (nur wenn die Abfrage genutzt wird). Der Berichtszeitraum gilt für die letzten drei Reiter
- Tickets: die komplette Liste mit Suche, Filtern und gespeicherten Ansichten; sortiert nach der letzten Aktivität (zuletzt bearbeitete Tickets oben), der Eingang steht beim Darüberfahren in der Spalte „Letzte Aktivität“
- Aufgaben: eigene To-dos, unabhängig von Tickets
- Ticket-Ansicht: links Verlauf und Antwortfeld, rechts die Karten in drei Reitern: Details (Eigenschaften, SLA-Fristen, Absender, Kundenbewertung), Organisation (zugehörige Probleme, Wiedervorlage und Beobachter, Kollaboratoren, Zeiterfassung) und Mehr (passende Artikel und Tickets, Zusammenführen und Löschen, Plugin-Karten). Der gewählte Reiter bleibt beim Neuladen erhalten
- Berichte: Auswertungen zu Antwortzeiten und Ticketaufkommen
- Sperrliste: einzelne E-Mail-Adressen oder ganze Mail-Anbieter blockieren
- Verzeichnis: Kontaktliste aller Kollegen
Vorlagen (Textbausteine): Im Antwortformular zeigt die Auswahl „Vorlage wählen“ nur Vorlagen, die der Abteilung des Tickets zugeordnet sind, dazu die Vorlagen für alle Abteilungen (ohne Abteilung angelegt). Beides ist in der Auswahl gruppiert. Zuordnen könnt ihr eine Vorlage unter Adminportal → Vorlagen.
Mehrere Tickets in eine andere Abteilung verschieben: In der Ticketliste die Tickets markieren, unten bei „Auswahl“ die Abteilung wählen und „Abteilung ändern“ klicken. Die SLA-Fristen werden nach den Regeln der neuen Abteilung neu berechnet, die Verschiebung steht im Aktivitätsprotokoll jedes Tickets. Verschieben dürfen nur Mitarbeiter mit dem Recht „Tickets übertragen“ und nur in Abteilungen, auf die sie Zugriff haben. Tickets, die schon in der Zielabteilung liegen, oder bei denen das Recht fehlt, werden übersprungen und in der Meldung genannt.
In einem Ticket könnt ihr dem Kunden antworten, eine interne Notiz hinterlassen (nur das Team sieht sie), den Status ändern, das Ticket zuweisen, lösen oder schließen. Welche dieser Aktionen möglich sind, hängt von eurer Rolle in der Abteilung des Tickets ab.
Signatur beim Antworten wählen: Im Antwortformular eines Tickets steht unter dem Textfeld die Auswahl Signatur: Meine Signatur, Abteilung „…“ (die Signatur der Abteilung des Tickets) oder Keine Signatur. Darunter zeigt eine Vorschau genau das, was angehängt wird. Voreingestellt ist wie bisher die eigene Signatur, ersatzweise die der Abteilung. Die Signatur wird nur an öffentliche Antworten angehängt, nicht an interne Notizen. Die Mobile-API nimmt beim Antworten (POST /api/staff/v1/ticket_message.php) optional das Feld signature mit own, dept oder none.
E-Mail-Signatur: Unter Mein Profil → Signatur stellt ihr den Text ein, der an eure Antworten angehängt wird (Fett, Kursiv, Liste, Link und Bilder). Bilder fügt ihr mit 🖼️ ein, die Größe ändert ihr, indem ihr das Bild anklickt: Mit dem runden Anfasser an der Ecke ziehen (auch mit dem Finger) oder 25 / 50 / 75 % / Original wählen. Das funktioniert in allen Texteditoren mit Bildern, auch bei Abteilungen und Mitarbeiter-Konten der Verwaltung. Bilder in Signaturen müssen über eine https-Adresse erreichbar sein (die Website-URL der Installation muss mit https:// beginnen), sonst blendet der Sicherheitsfilter sie aus.
Für Admins: Das Adminportal
Im Menü gibt es den Punkt „Adminportal“. Er ist für echte Admins immer sichtbar und für Co-Admins mit passenden Einzelrechten (siehe Rechte und Rollen). Sieht ein Admin den Punkt nicht: einmal ab- und wieder anmelden und prüfen, ob der Bereich eingeklappt ist (Pfeil daneben).
Verwalten
| Punkt | Wofür |
|---|---|
| Abteilungen | Themenbereiche, denen Tickets zugeordnet werden; mit Status, Abteilungsleiter, Mitgliedern und SLA-Plan |
| Prioritäten / SLA | Dringlichkeitsstufen mit Reaktions- und Lösungszeiten |
| SLA-Pläne | Eigene Zeiten pro Abteilung oder Hilfethema |
| Hilfethemen | Auswahl, die Kunden beim Ticket-Erstellen sehen, mit Zuordnung zu Abteilung, Priorität und Team |
| Ticket-Felder, Benutzerdefinierte Listen | Eigene Zusatzfelder für Tickets |
| Vorlagen | Textbausteine für schnelle Antworten |
| Seiten | Frei gestaltbare Inhaltsseiten im Kundenportal (z. B. AGB, Impressum) |
| E-Mail-Adressen | Absender- und Eingangsadressen, jeweils mit Abteilung, Hilfethema, optional eigenem SMTP und Test-Knopf |
| Postfächer (Abruf) | Von wo E-Mails abgerufen werden |
| E-Mail-Vorlagen | Texte der automatisch verschickten Mails |
| Wissensdatenbank | Öffentliche Hilfe-Artikel für Kunden |
| API-Schlüssel, Webhooks | Anbindung anderer Systeme |
| Plugins | Zusatzfunktionen installieren und verwalten |
Kunden
| Punkt | Wofür |
|---|---|
| Kundenverzeichnis | Alle Kunden-Konten im Überblick |
| Organisationen | Mehrere Kunden zu einer Firma bündeln |
Agenten
| Punkt | Wofür |
|---|---|
| Mitarbeiter | Konten anlegen, Abteilungen, Rolle je Abteilung vergeben |
| Teams | Mitarbeiter-Gruppen, z. B. für Zuweisungen |
| Rollen | Berechtigungssets |
System
| Punkt | Wofür |
|---|---|
| Admin-Protokoll | Alle wichtigen Änderungen und fehlgeschlagene automatische E-Mails |
| Ticket-Regeln | Automatische Aktionen bei neuen Tickets |
| Eskalationsregeln | Automatische Aktionen bei überfälligen oder liegengebliebenen Tickets |
| Wiederkehrende Tickets | Regelmäßig neu erstellte Tickets (z. B. monatliche Checkliste) |
| Zeiterfassung | Erfasste Bearbeitungszeiten einsehen |
| Geschäftszeiten | Zeitfenster, in denen die SLA-Uhr läuft, inklusive Feiertage |
| Einstellungen | Name, Logo, Zeitzone, E-Mail, Cron-Jobs, Datenschutz, Design u. v. m. |
| Backup | Manuelle und automatische Sicherungen |
| System-Update | Programm und Datenbank aktualisieren |
Firmenlogo
Unter Einstellungen → Design → Firmenlogo ladet ihr euer Logo hoch (PNG, JPG, GIF oder SVG, höchstens 2 MB). Es erscheint im Kundenportal, in den Anmeldeseiten und im Mitarbeiterbereich. Neben dem Logo steht standardmäßig der Name der Installation; mit „Name neben dem Logo ausblenden“ zeigt DeskHub nur das Logo. Die Vorschau in den Einstellungen hat einen dunklen Hintergrund. Helle Logos sind auf den hellen Seiten des Kundenportals schwer zu erkennen, nehmt dafür lieber eine dunkle oder farbige Variante.
Favicon
Das Symbol im Browser-Tab, in Lesezeichen und auf dem Startbildschirm stellt ihr unter Einstellungen → Design → Favicon ein. Erlaubt sind ICO, PNG, JPG, GIF, WebP und SVG (höchstens 1 MB, am besten quadratisch, z. B. 256×256 Pixel). DeskHub prüft den Inhalt, nicht nur die Endung; SVG-Dateien mit Skripten werden abgelehnt. Das Favicon gilt auf allen Seiten (Kundenportal, Mitarbeiterbereich, Anmeldeseiten, Druckansichten). Ohne Favicon verwendet DeskHub das Logo, ohne beides das Standardsymbol. Browser merken sich Symbole hartnäckig: Nach einer Änderung hilft Strg + F5 oder ein neuer Tab.
Kundenportal-Design (Themes)
Unter Einstellungen → Design lassen sich mehrere Themes als ZIP-Datei hochladen, aktivieren und löschen. Ein aktiviertes Theme gilt für das ganze Kundenportal. Mit „Standarddesign nutzen“ wird es wieder deaktiviert. Der Anzeigename wird aus dem Dateinamen der ZIP übernommen; lädt man ein Theme mit gleichem Namen erneut hoch, ersetzt es die vorhandene Version. Fertige Themes (darunter die Saison-Themes Halloween Nacht und Weihnachten Winter) liegen als ZIP im Ordner theme/ des Projekts. Außerdem könnt ihr Themes direkt aus dem Katalog der Plugin-Webseite installieren: Auf derselben Seite erscheint unter „Themes aus dem Katalog“ das Angebot automatisch. Prüfsumme und Signatur (mit dem unter Plugins hinterlegten Herausgeber-Schlüssel) werden vor der Installation geprüft; aktiviert wird das Theme erst, wenn ihr es selbst aktiviert.
Im Urlaub keine Benachrichtigungen, die Vertretung bekommt sie stattdessen (ab Server 1.0.59): Wer den Urlaubsmodus eingeschaltet hat (Profil oder Plugin „Urlaub und Vertretung“), bekommt keine Mails (neues Ticket, überfällig, Erwähnung, Team-Zuweisung, Eskalation an den Bearbeiter), keine Browser-Push-Meldungen und keine Android-Popups. Stattdessen bekommt die Vertretung (auch über Ketten, ohne Doppelte) diese Benachrichtigungen, damit sie die Tickets bearbeiten kann; ohne Vertretung bekommt niemand etwas. Nach dem Urlaub gilt wieder alles wie vorher. Ausgenommen sind Sicherheitsmails (Anmelde-Wächter, Passwort zurücksetzen) und Systemmeldungen an Administratoren (Postfach, Backup). Bei der SLA-Überschreitung geht die Mail an die Vertretung, ohne Vertretung an die Abteilung.
Anmelde-Wächter (ab Server 1.0.54)
Der Wächter schützt die Anmeldung der Mitarbeiter (Web und Android-/Windows-App) und ist fest in DeskHub eingebaut. Adminportal → Anmelde-Wächter.
- Geräte und Orte merken: Ein Gerät ist ein Browser (Kennung in einem Cookie
dh_device) oder eine App (Gerätename). Ein Ort ist das Land (nur wenn Cloudflare es mitschickt) oder sonst das Netz der IP-Adresse. Die erste Anmeldung eines Kontos wird still gemerkt. - Warnung per Mail: Bei einem neuen Gerät (und, abschaltbar, bei einem neuen Ort) bekommt der Mitarbeiter eine Mail mit Zeit, Gerät, Ort und IP-Adresse und dem Link „Das war ich nicht“. Der Link gilt 7 Tage und einmal. Er macht das Passwort ungültig, beendet alle App-Anmeldungen, vergisst die gemerkten Geräte, beendet laufende Browser-Sitzungen und informiert die Administratoren. Danach legt der Mitarbeiter über „Passwort vergessen?“ ein neues Passwort fest.
- Sperre nach Fehlversuchen: Standard 5 Fehlversuche, dann 15 Minuten gesperrt (einstellbar, 3 bis 20 Versuche, 5 bis 240 Minuten); gilt für Web und App. Auch falsche 2FA-Codes werden jetzt gebremst. Die Sperre wird einmal je Sperrzeit protokolliert und per Mail an den Kontoinhaber und die Administratoren gemeldet.
- Protokoll: Jede Anmeldung, jeder Fehlversuch, jede Sperre und jede „Konto gesichert“-Meldung mit Zeit, Konto, Gerät, Ort, IP und Kanal; mit Zählern der letzten 24 Stunden, Filter und Suche. Einträge werden nach 180 Tagen (einstellbar) gelöscht.
- Für jeden Mitarbeiter: Unter Profil → Sicherheit stehen „Meine Geräte und Anmeldungen“; unbekannte Geräte lassen sich dort entfernen.
- Grenzen: Ohne Fremddienst gibt es keinen genauen Standort; mobile Netze wechseln das Netz oft, darum lässt sich die Ort-Warnung abschalten. Wer Cookies löscht, gilt als neues Gerät. Die Warn-Mail braucht einen funktionierenden Mailversand (Fehlgeschlagenes landet in der Mail-Warteschlange).
Test: tests/login_guard.php.
E-Mails versenden (SMTP)
Das ist der wichtigste erste Schritt: Damit Kunden eine Bestätigung mit ihrer Ticketnummer bekommen, muss der E-Mail-Versand eingerichtet sein.
- Adminportal → Einstellungen → E-Mail.
- Server, Port, Benutzername, Passwort und Absenderadresse eures E-Mail-Anbieters eintragen. Diese Daten findet ihr im Kundenlogin eures Anbieters unter „E-Mail-Konten“ oder „Postfach-Einstellungen“.
- Auf „Test-Mail senden“ klicken. Kommt sie an, funktioniert der Versand.
Eigener Versand pro Absenderadresse: Unter Adminportal → E-Mail-Adressen kann jede Adresse einen eigenen SMTP-Server bekommen (Reiter „Abgehend (SMTP)“). Mit „Testen“ prüft ihr Abruf und Versand jeder Adresse einzeln. Gibt es für eine Adresse keinen eigenen Server, wird der allgemeine verwendet.
Häufigste Stolperfalle: Die Absenderadresse einer Abteilung muss bei eurem Mail-Anbieter existieren und freigeschaltet sein. Sonst blockt der Anbieter den Versand. Im Zweifel die Adresse deaktivieren oder löschen, dann gilt die Standard-Absenderadresse.
Kommt trotz erfolgreicher Test-Mail eine bestimmte automatische Mail nicht an, zeigt das Admin-Protokoll die genaue Fehlermeldung des Anbieters.
Port und Verschlüsselung: „STARTTLS“ gehört zu Port 587, „SSL/TLS“ zu Port 465. Beim Umschalten setzt DeskHub den Port selbst, sofern dort noch ein Standardport steht. Passen beide nicht zusammen, nennt die Fehlermeldung genau das.
Mail-Warteschlange
Scheitert der Versand (SMTP-Server nicht erreichbar, falscher Port, Anbieter-Störung), geht die Mail nicht verloren: DeskHub speichert sie und versucht es alle paar Minuten erneut, nach 5, 10, 20, 40 und 60 Minuten und dann alle 2 bis 6 Stunden, höchstens 10-mal und höchstens 48 Stunden lang. Danach gilt sie als aufgegeben.
- Ansehen und steuern: Adminportal → Mail-Warteschlange (nur Administratoren). Dort stehen Empfänger, Betreff, Versuche und letzter Fehler; pro Mail „Jetzt senden“ oder „Löschen“, dazu „Alle wartenden jetzt senden“, „Aufgegebene erneut versuchen“ und Aufräumen. Erledigte und aufgegebene Einträge löscht DeskHub nach 30 Tagen von selbst.
- Warnung: Wartende Mails zeigt die Statusleiste als Warnung, aufgegebene als Fehler.
- Ausschalten: Mit dem Schalter auf der Seite (Standard: an).
- Nicht in der Warteschlange: Test-Mails (sie sollen sofort den Fehler zeigen) und Adressen mit der Endung
.invalid. - Cron: Der Job „Mail-Warteschlange“ läuft alle 2 Minuten im eingebauten Hintergrundbetrieb. Mit eigenem Cronjob:
*/5 * * * * php /pfad/zu/deskhub/cron/process_mail_queue.php. - Grenzen: Die Warteschlange hilft bei Störungen des Versandwegs. Eine Mail an eine nicht existierende Adresse nimmt der Server meist an und meldet den Fehler erst später; das kann DeskHub nicht erkennen. Mails stehen vollständig (mit Text) in der Datenbank, das Backup enthält sie also auch.
E-Mails automatisch abrufen (Postfächer)
Damit eine Mail an z. B. support@eure-domain.de automatisch als Ticket erscheint, braucht DeskHub Zugriff auf das Postfach per IMAP.
Ein Postfach einrichten
- Adminportal → Postfächer (Abruf) → „Neues Postfach“.
- Server, Port, Benutzername und Passwort eintragen (meist unter „IMAP-Zugang“ beim Anbieter).
- Optional eine Standardabteilung wählen, sonst entscheidet die Empfängeradresse.
- Speichern und in der Liste auf „Testen“ klicken. Läuft der Test, ruft DeskHub das Postfach ab, sobald die Automatisierung aktiv ist.
Mehrere Postfächer
Habt ihr getrennte Postfächer pro Abteilung (z. B. technik@ und vertrieb@), legt ihr für jedes ein eigenes Postfach mit eigener Standardabteilung an. DeskHub ruft alle aktiven Postfächer nacheinander ab.
Eigenes Ticket-Formular pro Abteilung
Unter Abteilungen → Formular (oder im Reiter „Ticket-Formular“ der Abteilung) kann jede Abteilung ein komplett eigenes Formular bekommen. Ist es aktiv, sieht ein Kunde, der diese Abteilung wählt (direkt oder über ein Hilfe-Thema), nur die dort festgelegten Felder: eigene Felder (Text, Mehrzeilig, Auswahl, Checkbox, Zahl, Datum, mit Pflicht und Reihenfolge), Überschrift, Einleitung, Bezeichnungen von Betreff und Beschreibung, Platzhaltertext und Text des Absende-Knopfs. Betreff und Anhang lassen sich ausblenden (ohne Betreff wird „Anfrage “ verwendet). Die allgemeinen Ticket-Felder und die Felder der Hilfe-Themen gelten dann für diese Abteilung nicht. Name und E-Mail werden immer abgefragt. Abteilungen ohne eigenes Formular nutzen weiter das Standardformular.
Eine Adresse einer Abteilung zuordnen
Läuft alles in einem Sammelpostfach zusammen (z. B. per Weiterleitung), muss DeskHub wissen, welche Empfängeradresse zu welcher Abteilung gehört:
- Tragt bei einer Abteilung eine E-Mail-Adresse ein, dann legt DeskHub den Eintrag automatisch an.
- Oder legt unter Adminportal → E-Mail-Adressen weitere Adressen an, auch mehrere auf einmal (eine pro Zeile). Dort lässt sich zusätzlich ein Hilfethema festlegen, das Tickets über diese Adresse automatisch bekommen.
Ist eine Adresse nirgends hinterlegt, landet das Ticket in der Standardabteilung. Ist die zugeordnete Abteilung deaktiviert, wird ebenfalls die Standardabteilung genutzt.
Nach dem Abruf
Pro Postfach legt ihr fest, was mit einer verarbeiteten Mail passiert: als gelesen markieren (Voreinstellung und sicherste Wahl), in einen Ordner verschieben oder löschen.
Automatisierung (Cronjobs)
Einige Aufgaben müssen regelmäßig von selbst laufen:
- E-Mail-Abruf (alle 5 Minuten empfohlen)
- SLA-Prüfung (alle 15 Minuten)
- Eskalationsregeln (stündlich)
- Wiederkehrende Tickets (täglich)
- Automatische Backups (nach Zeitplan)
- Datenanonymisierung (täglich)
Dafür gibt es unter Adminportal → Einstellungen → Cron-Jobs drei Wege:
Option A – Automatischer Hintergrund-Betrieb (Standard): Ist von Anfang an aktiv. Sobald jemand die Website, das Backend oder eine App nutzt, prüft DeskHub im Hintergrund, ob etwas fällig ist, und führt es aus. Hat eure Seite regelmäßig Besucher, reicht das für die meisten Fälle.
Option B – Echter Server-Cronjob: Mit eigenem (v)Server und Shell-Zugriff trägt DeskHub per Klick auf „Jetzt installieren“ die nötigen Cronjobs selbst ein. Dann läuft alles zuverlässig zur exakten Zeit, auch nachts ohne Besucher. Auf einfachem Webhosting ohne Shell ist der Knopf ausgeblendet, dort übernimmt Option A.
Option C – Manuell: Jede Aufgabe hat einen Knopf „Jetzt ausführen“.
Nach der Installation müsst ihr nichts tun, Option A läuft von selbst.
Empfehlung bei einem eigenen Server: Richtet Option B (echten Cronjob) ein und schaltet danach den eingebauten Ersatz unter Einstellungen → Cron-Jobs ab. Der Ersatz läuft nach dem Senden jeder Seite im selben Prozess; ein langer Job (Backup, Mail-Abruf, Upload auf die NAS) belegt dann einen Webserver-Prozess, und hinter Cloudflare kann das zur Fehlerseite „524“ führen. Der Ersatz gibt die Sitzung vor dem Job frei, sodass er die nächste Seite desselben Mitarbeiters nicht mehr blockiert.
Status und automatisch Offline
Jeder Mitarbeiter stellt seinen Status ein (Verfügbar, Beschäftigt, Pause, Offline), im Browser unter Verfügbarkeit & Schichten und in der App unter Verwaltung → Mein Status. Wer 30 Minuten lang nichts tut, geht automatisch auf Offline und bekommt seinen vorherigen Status zurück, sobald er wieder aktiv ist. Als aktiv zählen echte Bedienung (Seitenaufrufe, Klicks und Tipps, Aktionen und Berührungen in der App); Abfragen im Hintergrund halten niemanden online. Ein von Hand gesetzter Status wird nicht von selbst zurückgesetzt. Die Zeit stellt ein Admin unter Verfügbarkeit & Schichten ein (0 = aus). Admins können dort (und in der App durch Antippen eines Teammitglieds) den Status jedes Mitarbeiters ändern; das steht im Aktivitätsprotokoll. Der Live-Chat auf der Kundenseite zeigt automatisch Offline-Mitarbeiter nicht mehr als erreichbar.
Automatische Abmeldung
Im Browser wird ein Mitarbeiter nach der eingestellten Zeit ohne Bedienung abgemeldet (Einstellungen → Allgemein → Sitzungs-Timeout, Standard 30 Minuten; oben rechts zeigt ein Zähler die Restzeit). Als Bedienung zählen Klicks, Tastatureingaben und Mausbewegungen auf der Seite sowie jeder vom Nutzer selbst ausgelöste Seitenaufruf. Nicht als Bedienung zählen die Abfragen, die eine offene Seite im Hintergrund stellt (Ticketliste, Chat, Anwesenheit, „Seite aktualisieren“ bei neuen Antworten): Eine unbeachtet offene Seite hält die Sitzung also nicht am Leben. Mehrere Tabs teilen sich die Zeit; der Zähler gleicht sich alle 30 Sekunden mit dem Server ab. Windows-Programm und Android-App melden sich über ihr eigenes Anmelde-Token an und sind davon nicht betroffen.
Digitaler Assistent
Der Assistent beantwortet Fragen im Kundenportal und ersetzt dabei das Live-Chat-Fenster, solange der Live-Chat ausgeschaltet oder gerade niemand erreichbar ist. Sobald ein Mitarbeiter als „Verfügbar“ gemeldet ist (und der Live-Chat läuft), sehen Kunden wieder den normalen Live-Chat. Im Wartungsmodus ist er nicht aktiv.
- Antworten: zuerst die im Backend hinterlegten zusätzlichen Antworten (Frage, Stichwörter, Text), dann die veröffentlichten Artikel der Wissensdatenbank (nur, wenn sie im Kundenportal eingeschaltet ist). Gesucht wird über die Wörter der Frage, ohne externen KI-Dienst: Kundenfragen verlassen den Server nicht.
- Keine Antwort: Der Assistent fragt, ob er ein Ticket erstellen soll, und erfragt Thema (falls öffentliche Hilfethemen eingerichtet sind), Name, E-Mail-Adresse, Betreff und Beschreibung. Er zeigt eine Zusammenfassung und legt das Ticket nach Bestätigung an. Es durchläuft Ticket-Regeln und automatische Zuweisung, trägt den Tag „Assistent“ und der Kunde bekommt die übliche Eingangsbestätigung.
- Einrichten: Adminportal → Digitaler Assistent (Menü „Verwalten“): ein-/ausschalten, Name, Begrüßung, Text ohne Antwort, Abteilung und Priorität der Tickets, zusätzliche Antworten pflegen und mit „Frage ausprobieren“ testen. Mit der Einstellung „Immer (zum Testen)“ siehst du den Assistenten auch bei besetztem Chat.
- Rückmeldung und Wörter: „Das hat geholfen“ und „Ticket erstellen“ nach einer Antwort werden im Fragen-Log als 👍/👎 festgehalten (Filter „Hat geholfen“ / „Hat nicht geholfen“). Unter „Gleichbedeutende Wörter“ (Tab Einstellungen) pflegst du eigene Gruppen wie „Zugang, Einladung, beitreten“, die der Assistent gleich behandelt.
- Fragen-Log: Auf derselben Seite unter „Fragen-Log“ siehst du jede Kundenfrage mit Ergebnis (eigene Antwort gefunden, Wissensdatenbank, keine Antwort, Ticket gewünscht/erstellt) und der gefundenen Antwort. Filter nach Ergebnis, Zeitraum und Text; „Häufige Fragen ohne Antwort“ fasst gleiche Fragen zusammen und legt mit einem Klick eine neue Antwort an. Gespeichert werden nur Frage und Ergebnis (kein Name, keine E-Mail); Aufbewahrung einstellbar (Standard 90 Tage, 0 = nichts speichern), „Log leeren“ löscht alles. Dafür einmal unter System-Update „Datenbank aktualisieren“ ausführen (Migration 0045).
- Recht für Mitarbeiter: In einer Rolle das Recht „Digitalen Assistenten verwalten“ vergeben (Admins haben es immer).
- Missbrauchsschutz: höchstens 30 Fragen je 10 Minuten und Sitzung, höchstens 3 Tickets pro Stunde und Adresse, verstecktes Spam-Feld, gültiger Sitzungs-Token.
Wiedervorlage, Beobachter, ähnliche Tickets, Kundenerinnerung
- Wiedervorlage: Auf der Ticketseite rechts „Auf später legen“ (in 1 oder 3 Stunden, morgen früh, in 3 Tagen, 1 Woche oder zu einem eigenen Zeitpunkt). Das Ticket verschwindet aus „Offen“ und „Alle“ und steht im Tab „💤 Wiedervorlage“. Zur gewählten Zeit kommt es zurück, der Mitarbeiter bekommt eine Benachrichtigung (Browser-Push und Android-App, Art „Wiedervorlage fällig“). Antwortet der Kunde früher, kommt es sofort zurück. Der Job „Wiedervorlagen“ läuft alle 2 Minuten über den eingebauten Cron oder per Crontab:
*/5 * * * * php cron/process_snoozes.php. - Beobachter: „Ticket beobachten“ auf der Ticketseite. Beobachter bekommen eine Benachrichtigung bei Kundenantworten und Antworten anderer Mitarbeiter („Beobachtetes Ticket aktualisiert“, in den Push-Einstellungen abschaltbar), ohne dass ihnen das Ticket zugewiesen ist.
- Dazu passend: Beim Öffnen eines Tickets zeigt die Karte passende Artikel der Wissensdatenbank (mit „Link kopieren“) und ähnliche bereits gelöste Tickets.
- Kunden erinnern: Einstellungen → Allgemein → „Kunden erinnern“. Reagiert ein Kunde nach einer Antwort X Tage nicht, bekommt er einmalig eine freundliche Mail; ist das automatische Schließen an, nennt sie die Restzeit. Die Frist zum Schließen ändert sich dadurch nicht. Der Text lässt sich unter E-Mail-Vorlagen mit dem Schlüssel
customer_reminderersetzen (Platzhalter{customer_name},{ticket_number},{subject},{ticket_url},{close_note}). Crontab:0 * * * * php cron/remind_customers.php. - App-Schnittstelle:
PATCH /api/staff/v1/ticket_update.phpnimmtsnoozeUntil(Datum/Uhrzeit odernull) undfollowing(true/false) an; Ticketlisten liefernsnoozedUntilundfollowing, Wiedervorlagen mit?snoozed=1. Die Android-App (ab 2.7.0) und das Windows-Programm (ab 2.5.0) nutzen das: Knöpfe „Auf später“ und „Beobachten“ im Ticket, Reiter bzw. Filter „Wiedervorlage“ und „Beobachtet“ in der Liste und die Karte „Dazu passend“. Wiedervorlage und Beobachten funktionieren auch bei einem gerade bearbeiteten (gesperrten) Ticket. - Für alles: einmal unter System-Update „Datenbank aktualisieren“ (Migration 0046).
Digitaler Assistent in den Apps
Android-App (ab 2.9.0, aktuell 3.1.0) und Windows-Programm (ab 2.7.0) haben die Verwaltung des Assistenten fest eingebaut (Verwaltung → „Digitaler Assistent“) mit fünf Bereichen: Einstellungen, zusätzliche Antworten (anlegen, ändern, löschen), Fragen-Log (Kennzahlen, Filter, Suche, häufige Fragen ohne Antwort mit „Antwort anlegen“, Log leeren), Gleichbedeutende Wörter und „Frage ausprobieren". Der Bereich erscheint nur für Administratoren und Mitarbeiter mit dem Recht „Digitalen Assistenten verwalten“; die Schnittstelle api/staff/v1/assistant.php prüft das Recht bei jedem Aufruf und trägt jede Änderung ins Admin-Protokoll ein.
Mehrsprachigkeit (Sprachpakete als Plugin)
Der Quelltext von DeskHub ist deutsch. Jede weitere Sprache ist ein Plugin („Sprachpaket“) und braucht keine Änderung am Server: Paket installieren, aktivieren, fertig. Mitgeliefert sind lang-en (English) und lang-de (Deutsch, macht die Quellsprache im Wechsler sichtbar und dient als Vorlage). Besucher und Mitarbeiter wechseln über die Flaggen (Kundenbereich: oben in der Leiste, Anmeldeseiten: oben rechts, Mitarbeiterbereich: unten in der Seitenleiste); die Wahl steht in einem Cookie (deskhub_lang), sonst gilt die Standardsprache (Adminportal → Sprachen).
- Aufbau eines Sprachpakets:
plugin.json(mit"language": {"code":"fr","name":"Français","flag":"flag.svg","strings":"strings.json"}, ohne Berechtigungen),plugin.php(leer),flag.svg(SVG oder PNG, höchstens 40 KB) undstrings.json. Schlüssel = deutscher Text, Wert = Übersetzung;{}steht für wechselnde Teile („Willkommen, {}“ → „Welcome, {}“),{#}nur für Zahlen,{1}/{2}in der Übersetzung ändern die Reihenfolge. - Wie übersetzt wird: die fertige Seite wird durchsucht (Text zwischen Tags,
placeholder/title/alt, Knopf-Beschriftungen, Texte inconfirm()/alert()); ein Schlüssel muss dem deutschen Text genau entsprechen (Leerraum zählt nicht). Was nicht übersetzt ist, bleibt deutsch. Bei Deutsch läuft nichts davon, die Seiten kommen unverändert. - Sammelmodus für Übersetzer: Adminportal → Sprachen → „Sammelmodus“ merkt sich die Texte aller besuchten Seiten; „Vorlage laden“ liefert eine fertige
strings.jsonmit allen Texten (Bereits Übersetztes ist eingetragen, der Rest leer). - Übersetzungen in den Plugins (neu, ab Server 1.0.50): Jedes Plugin bringt seine Texte selbst mit: Datei
lang/<Sprachcode>.jsonim Plugin-Ordner (zum Beispiellang/en.json, gleiches Format wiestrings.json: Schlüssel = deutscher Text, Wert = Übersetzung,{}und{#}für wechselnde Teile). Wird eine Sprache gewählt, lädt DeskHub diese Dateien aller aktiven Plugins zusätzlich zum Sprachpaket; steht ein Text in beiden, gilt der aus dem Sprachpaket. Eine neue Sprache braucht damit nur das Sprachpaket und je Plugin eine Dateilang/<Code>.json; Plugins ohne Datei bleiben in dieser Sprache deutsch. Adminportal → Sprachen zeigt als Tabelle, welches Plugin für welche Sprache Texte mitbringt. Auch Plugin-Name, Beschreibung und Menüpunkt lassen sich so übersetzen (Schlüssel = der Text ausplugin.jsonbzw.plugin_register_menu). Alle mitgelieferten Plugins haben einelang/en.json(Stand: Seiten, Beschriftungen, Meldungen; Texte, die ein Plugin per Discord, Telegram oder E-Mail an Kunden schickt, bleiben deutsch). Ältere Server ignorieren die Dateien einfach. - Stand English: Kundenportal vollständig, Mitarbeiterbereich: Navigation, Seitentitel, Beschriftungen, Knöpfe, Meldungen und Rückfragen. Lange Hilfetexte in den Einstellungen und alle Daten (Tickets, Namen, E-Mail-Texte) bleiben deutsch. Nicht enthalten: Android-App, Windows-Programm und die Texte der automatischen E-Mails.
Sprachen der Apps (Deutsch und English)
Stand der Übersetzungen: Das mitgelieferte English-Paket (lang-en, ab Version 1.1.0) enthält rund 3400 Einträge: Oberflächen, Meldungen und Fehlertexte. Fehlt noch etwas, zeigt euch der Sammelmodus (Adminportal → Sprachen) genau die deutschen Texte der besuchten Seiten ohne Übersetzung. Die Wörterbücher der Windows- und der Android-App (je rund 2050 Einträge) enthalten auch die Meldungen, die der Server an die Apps schickt. Texte, die ihr selbst in der Datenbank anlegt (Namen von Abteilungen, Status, Vorlagen), bleiben, wie ihr sie eingetragen habt.
Windows-Programm (ab 2.9.0) und Android-App (ab 3.3.0) gibt es auf Deutsch und English. Die Sprache wechselst du über die Flaggen (Windows: in der Kopfleiste und auf der Anmeldung; Android: unter „Mehr“ und auf der Anmeldeseite); ohne Wahl gilt die Sprache von Windows bzw. des Telefons. Die Apps nutzen dafür ein Wörterbuch (desktop/src/lang-en.js, mobile/src/main/assets/lang_en.json): Schlüssel = deutscher Text, {} = wechselnder Teil, {#} = Zahl. Was nicht im Wörterbuch steht, bleibt deutsch. Nicht übersetzt werden Daten vom Server (Tickets, Namen, Texte der E-Mails) und Benachrichtigungen, die der Server schickt. Die Beschriftungen des Android-Widgets folgen der Sprache des Telefons.
Zufriedenheitsabfrage, Cc und Beobachter, Statusseite, Ticket-Vorlagen
- Zufriedenheitsabfrage (CSAT): Einstellungen → Allgemein → „Zufriedenheitsabfrage“. Nach dem Schließen oder Lösen eines Tickets (Wartezeit einstellbar, Standard 30 Minuten) bekommt der Kunde eine Mail mit fünf Sternen; ein Klick öffnet
csat.php, gespeichert wird erst mit dem Knopf (so zählen automatische Link-Prüfungen nicht). Pro Ticket genau eine Abfrage, nur für Tickets, die nach dem Einschalten geschlossen werden; kein Spam, kein Live-Chat. Der Versand läuft über den Hintergrunddienst (cron/send_csat.php, alle 5 Minuten). Die Bewertung steht im Ticket (Web, App, Windows-Programm); die Auswertung (Durchschnitt, Rücklaufquote, Verteilung, nach Mitarbeiter, letzte Kommentare) auf der Übersicht im Web, im Windows-Programm unter Berichte und im Dashboard der App. Schnittstelle:GET api/staff/v1/csat.php?days=30. - Cc und Beobachter: Beobachter (Mitarbeiter) und Cc-Empfänger (E-Mail, bekommen die öffentlichen Antworten in Kopie) gab es im Web; jetzt auch in App und Windows-Programm (Karte „Beobachter und Cc“ im Ticket). Schnittstelle:
POST api/staff/v1/ticket_collaborators.php(add/remove),ticket.phpliefertcollaborators,followersundcsat. - Statusseite: Adminportal → Statusseite (Dienste mit Zustand In Betrieb/Wartung/Eingeschränkt/Ausfall, Störungsmeldungen mit Updates). Öffentlich unter
/status.php(Link „Status“ im Kundenbereich, wenn eingeschaltet). Dienste können deaktiviert werden; dann werden sie ausgeblendet und nicht weiter geprüft. Der Minecraft-Java-Eintrag wird der Kategorie „Apps“ zugeordnet; als Prüfziel sind Domain oder IP mit Port möglich (z. B.play.example.de:25565oder203.0.113.10:25565). Danach den Dienst aktivieren. Die Plugin-Webseite (offizieller Katalog) lässt sich als Dienst „Plugin-Webseite“ überwachen: Mit „Fehlende Standarddienste wiederherstellen“ wird er angelegt (nur wenn inincludes/catalog_defaults.phpein Katalog eingetragen ist), geprüft wird dashealth.phpneben dem Katalog (Prüfart „Plugin-Webseite“, auch am Namen automatisch erkannt). Er ist intern: Er wird geprüft und ist für Mitarbeiter sichtbar (Kategorie „Server & Datenbank“), steht aber nicht auf der öffentlichen Statusseite und ändert deren Gesamtzustand nicht. Mit „Intern machen“ / „Öffentlich machen“ lässt sich das für jeden Dienst umstellen (braucht das Datenbank-Update, Migrationphp_0069). Eine Meldung kann den Dienst gleich umstellen; „Behoben“ setzt ihn zurück, solange keine andere Meldung offen ist. In App und Windows-Programm unter Verwaltung → Statusseite (Zustände ändern und Meldungen veröffentlichen nur als Administrator). Schnittstelle:api/staff/v1/status.php. - Ticket-Vorlagen: Adminportal → Ticket-Vorlagen (Name, Betreff, Text, Abteilung, Hilfethema, Priorität; „für Kunden sichtbar“ zeigt sie auf „Neues Ticket“). Mitarbeiter wählen sie beim Anlegen eines Tickets im Web, im Windows-Programm und in der App (
GET api/staff/v1/ticket_templates.php). Gepflegt werden die Vorlagen nur im Web.
Weboberfläche aus den Apps öffnen
Einstellungen, die es nur im Web gibt (Einstellungen, Backup, Plugins, API-Schlüssel, Webhooks, Ticket-Felder, Vorlagen, Seiten, Postfächer, …), zeigen Windows-Programm und Android-App nicht mehr an: Die Kacheln „(im Browser)“ in der Verwaltung des Windows-Programms (ab 2.9.0) sind entfernt, ebenso die Hinweise und der Knopf „Dienste verwalten“. Im Ticket öffnet „Im Browser“ die Ticketseite (zusammenführen, aufteilen, drucken).
- Rechte: Der Server (
api/staff/v1/web_pages.php) liefert nur Seiten, die der Mitarbeiter öffnen darf (Administrator: alle; „Digitalen Assistenten verwalten“ und „E-Mail-Adressen verwalten“ als Einzelrechte; Erwähnungen und Verzeichnis für alle). Die Weboberfläche prüft die Rechte danach noch einmal selbst. - Anmeldung: Die App holt eine einmalige Adresse (
staff/app_login.php?t=…), die 60 Sekunden gilt und nur einmal funktioniert; sie meldet im Browser an und leitet auf die Seite weiter. Jede Übergabe steht im Admin-Protokoll. Abgelaufene, benutzte oder erfundene Adressen führen zur Anmeldeseite. Dafür einmal „Datenbank aktualisieren“ (Migration 0047). Die Android-App 3.x enthält diese Browser-Übergabe nicht mehr; die Schnittstelle bleibt auf dem Server für das Windows-Programm.
Ticket-Sperre
Wer ein Ticket öffnet, sperrt es für andere (5 Minuten, bei Inaktivität läuft die Sperre ab), damit nicht zwei Personen gleichzeitig daran arbeiten. Normale Mitarbeiter bekommen bei einem gesperrten Ticket einen Hinweis mit dem Namen des Bearbeiters. Administratoren können ein gesperrtes Ticket trotzdem lesen und bearbeiten (Antworten, Notizen, Status) und sehen oben den Hinweis „wird gerade von … bearbeitet“ mit dem Knopf „Sperre aufheben und übernehmen“. Das gibt es im Browser, im Windows-Programm und in der Android-App; das Aufheben steht im Ticket-Verlauf. Jeder darf seine eigene Sperre freigeben. Ein Live-Chat sperrt Administratoren nie aus.
Beim Öffnen automatisch zuweisen
Öffnet ein Mitarbeiter ein Ticket, das noch niemandem zugewiesen ist, wird es ihm zugewiesen (Browser, Windows-Programm und Android-App). Das gilt nicht für geschlossene, gelöste, zusammengeführte oder als Spam markierte Tickets, nicht für Mitarbeiter ohne Recht zum Antworten und nicht, wenn ein Admin ein von jemand anderem bearbeitetes Ticket nur ansieht. Ein bereits zugewiesenes Ticket bleibt beim Bearbeiter. Ausschalten: Einstellungen → Allgemein → „Beim Öffnen automatisch zuweisen“.
Neue Tickets automatisch zuweisen
Im Formular einer Abteilung (Adminportal → Abteilungen → Bearbeiten, auch in der Android-App und im Windows-Programm) steht „Neue Tickets automatisch zuweisen“:
- Nicht automatisch zuweisen: wie bisher.
- Immer an einen bestimmten Mitarbeiter: z. B. alle Tickets von „First Support“ an Lukas. Ist er im Urlaub, bekommt seine Vertretung das Ticket, ohne Vertretung bleibt es unzugewiesen.
- Reihum: der Reihe nach an die Mitarbeiter der Abteilung (Hauptabteilung oder zusätzlich zugewiesen). Mitarbeiter im Urlaub, offline oder außerhalb ihrer Schicht werden übersprungen; ist niemand erreichbar, bekommt trotzdem der Nächste in der Reihe das Ticket.
Das gilt für Tickets aus Formular, E-Mail, API (z. B. das Minecraft-Plugin) und Live-Chat. Reihenfolge: eine Ticket-Regel mit „Mitarbeiter zuweisen“ hat Vorrang, dann die Einstellung der Abteilung, dann der letzte Bearbeiter des Kunden. Von Mitarbeitern von Hand angelegte Tickets bleiben so, wie der Mitarbeiter sie zugewiesen hat. Im Ticket-Verlauf steht „Automatisch zugewiesen (Einstellung der Abteilung)“.
SLA-Pläne
Ein SLA-Plan legt fest, wie schnell reagiert und gelöst werden soll. Unter Adminportal → SLA-Pläne legt ihr Pläne mit Reaktions- und Lösungszeit an und weist sie Abteilungen oder Hilfethemen zu.
Welche Zeiten für ein Ticket gelten, entscheidet diese Reihenfolge:
- SLA-Plan des Hilfethemas
- SLA-Plan der Abteilung
- Zeiten der Priorität
So kann ein Premium-Hilfethema schneller reagieren müssen als der Rest der Abteilung. Die Geschäftszeiten und Feiertage gelten weiterhin.
Gespeicherte Ansichten
In der Ticketliste lassen sich die aktuellen Filter (Status, Zuweisung, Abteilung, Priorität, Überfälligkeit usw.) als Ansicht speichern. Gespeicherte Ansichten erscheinen als Schnellauswahl über der Liste. Ihr könnt sie für euch behalten oder mit dem ganzen Team teilen. Gemeinsame Ansichten sind in Web, Windows-App und Android-App gleich verfügbar. Speichern und Löschen funktioniert direkt über der Ticketliste („Aktuelle Filter als Ansicht speichern“, ✕ neben der Ansicht). Löschen können der Ersteller einer Ansicht und alle Admins.
Berichte und Bericht-Baukasten
Unter Berichte gibt es die Standardauswertungen. Der Bericht-Baukasten erlaubt eigene Auswertungen:
- Gruppieren nach: Abteilung, Hilfethema, Mitarbeiter, Team, Priorität, Status, Quelle, Tag, Woche oder Monat
- Kennzahlen: Tickets gesamt, offen, gelöst/geschlossen, überfällig, durchschnittliche erste Antwort und Lösungszeit sowie SLA-Erfüllung bei Antwort und Lösung
- Zeitraum und Filter: nach Abteilung, Priorität, Mitarbeiter, Hilfethema, Status und Quelle
- Speichern und teilen: Berichte lassen sich benennen, speichern und mit dem Team teilen
- Export als CSV (kompatibel mit Excel)
Jeder sieht nur Zahlen aus Abteilungen, auf die er Zugriff hat. Der Baukasten ist auch in Windows-App und Android-App verfügbar.
Integrationen: API-Schlüssel und Webhooks
Mit API-Schlüsseln und Webhooks verbindet ihr DeskHub mit anderen Systemen (z. B. Monitoring, Formulare, Chat-Tools).
API-Schlüssel (Adminportal → API-Schlüssel): Ein Schlüssel erlaubt einem anderen System, Tickets in DeskHub anzulegen. Beim Erstellen wird der Schlüssel einmalig angezeigt, danach nie wieder; notiert ihn sofort. Pro Schlüssel legt ihr fest, ob er Tickets anlegen und/oder lesen darf, und optional, von welchen IP-Adressen er benutzt werden darf. Schlüssel lassen sich jederzeit deaktivieren. Es gilt eine Begrenzung auf 60 Tickets pro Minute.
Webhooks (Adminportal → Webhooks): DeskHub meldet Ereignisse an eine Adresse eures Systems: Ticket erstellt, Antwort geschrieben, Status geändert, Ticket zugewiesen. Jede Meldung ist mit eurem geheimen Schlüssel signiert, damit das Empfängersystem die Echtheit prüfen kann. Der Zustellstatus steht in der Liste. Schlägt eine Adresse zehnmal hintereinander fehl, wird der Webhook automatisch deaktiviert. Adressen im internen Netzwerk sind aus Sicherheitsgründen nicht erlaubt.
Die technische Beschreibung für Entwickler steht im Abschnitt API und Webhooks (für Entwickler).
Rechte und Rollen
Nicht jeder im Team soll vollen Admin-Zugriff haben. Dafür gibt es Rollen:
- Adminportal → Rollen → „Neue Rolle“.
- Namen vergeben (z. B. „Teamleitung Technik“).
- Ticket-Berechtigungen ankreuzen (antworten, Notizen, zuweisen, schließen, löschen …).
- Optional einzelne Adminportal-Bereiche freischalten (z. B. nur „Abteilungen“ und „Mitarbeiter“). Das macht die Person zum Co-Admin für genau diese Bereiche.
- Unter Mitarbeiter die Rolle zuweisen.
Rolle pro Abteilung
Eine Person kann in verschiedenen Abteilungen unterschiedliche Rollen haben, etwa „Teamleitung“ in Technik und „Agent“ in Vertrieb. Das stellt ihr im Mitarbeiter-Konto unter den zusätzlichen Abteilungen ein. Die Rechte in einem Ticket richten sich nach der Abteilung dieses Tickets, in Web und in beiden Apps. Eine deaktivierte Rolle ersetzt DeskHub durch die Standardrechte eines Agenten.
Einige Bereiche (Backup, System-Update, Ticket-Regeln, Ticket-Felder, Seiten, Kundenverzeichnis, Plugins, API-Schlüssel, Webhooks) bleiben bewusst immer echten Admins vorbehalten. Ein Co-Admin kann sich oder andere nie zum echten Admin machen.
Überwachung und Störungsmeldungen
DeskHub überwacht sich selbst und meldet Probleme, bevor Kunden sie bemerken:
- Postfach nicht erreichbar: Schlägt der E-Mail-Abruf mehrfach hintereinander fehl, erscheint für Verantwortliche ein rotes Banner im Mitarbeiterbereich und in den Apps. Außerdem bekommen die Admins eine E-Mail (höchstens einmal pro 24 Stunden) und eine weitere, sobald das Postfach wieder funktioniert.
- Abruf veraltet: Wurde länger nicht abgerufen, gibt es einen Hinweis.
- Versand fehlgeschlagen: Scheitern ausgehende Mails, steht das ebenfalls im Banner.
- Keine Verbindung zum Server: Die Windows-App und die Android-App zeigen ein Banner, wenn der Server nicht erreichbar ist. Sie versuchen automatisch wieder, die Verbindung herzustellen, zusätzlich gibt es einen Knopf „Jetzt erneut versuchen“.
Die Details zu einer Störung seht ihr unter Adminportal → E-Mail-Adressen und Postfächer (Abruf).
Windows-App und Android-App
Beide Apps sind für Mitarbeiter und Admins gedacht und haben ein helles und ein dunkles Design (umschaltbar oder automatisch nach System).
Download: Im Mitarbeiterbereich gibt es im Menü den Punkt „Apps“. Dort laden angemeldete Mitarbeiter die Windows- und die Android-App herunter und sehen Version, Größe, Prüfsumme, eine Kurzanleitung und die Serveradresse zum Kopieren. Ohne Anmeldung sind die Dateien nicht erreichbar.
Für Admins – Apps bereitstellen: Legt die fertigen Dateien per FTP in den Ordner app_downloads auf dem Server, genau mit diesen Namen: DeskHub-Setup.exe (Windows) und DeskHub.apk (Android). Zum Aktualisieren ersetzt ihr die Datei einfach. Die Seite „Apps“ zeigt automatisch Größe, Datum und Prüfsumme der neuen Datei. Der Ordner wird bei System-Updates nie überschrieben und ist nur über die Anmeldung erreichbar.
Einrichtung:
- App installieren und öffnen.
- Beim ersten Start die Adresse eurer DeskHub-Installation eingeben (z. B.
https://eure-domain.de). Die App merkt sie sich. - Mit dem Mitarbeiter-Konto anmelden.
Was die Apps können:
- Tickets bearbeiten (antworten, Notizen, zuweisen, Status ändern, lösen, schließen), Übersicht, Kundenverzeichnis, internen Chat und Live-Chat
- Wiedervorlage („Auf später“: 1 Stunde bis 1 Woche, im Windows-Programm auch eigener Zeitpunkt), Beobachten, Filter „Wiedervorlage“ und „Beobachtet“ und die Karte „Dazu passend“ (Artikel und ähnliche gelöste Tickets)
- Digitalen Assistenten komplett verwalten: Einstellungen, zusätzliche Antworten, Fragen-Log, Gleichbedeutende Wörter, „Frage ausprobieren“ (nur mit dem Recht „Digitalen Assistenten verwalten“)
- Beim Antworten zeigen die Apps nur die Textbausteine der Abteilung des Tickets (plus die für alle Abteilungen) und bieten wie im Web die Signatur-Auswahl (meine, Abteilung, keine) mit Vorschau. Das setzt einen Server mit diesem Stand voraus; ältere Server liefern die Signaturen nicht, dann antworten die Apps wie bisher.
- Gespeicherte Ansichten nutzen und Berichte aus dem Bericht-Baukasten ansehen
- Störungs- und Verbindungsbanner
- Admins und Co-Admins finden zusätzlich die Verwaltung mit fast allen Adminportal-Bereichen, je nach zugewiesenen Rechten: Abteilungen, Prioritäten, SLA-Pläne, Hilfethemen, E-Mail-Adressen (inkl. Test), Wissensdatenbank, E-Mail-Vorlagen, Organisationen, Mitarbeiter, Teams, Rollen, Admin-Protokoll, Eskalationsregeln, Zeiterfassung, Geschäftszeiten, Sperrliste, Aufgaben
- Systemnahe Bereiche (Backup, System-Update, Plugins, API-Schlüssel, Webhooks, Postfächer, Ticket-Felder, Seiten, Einstellungen) gibt es in der Android-App bewusst nicht; das Windows-Programm öffnet sie auf Wunsch im Browser (siehe Weboberfläche aus dem Windows-Programm öffnen)
Android-App 3.x: komplett neues Design (helle, runde Karten, Blau/Türkis, Dunkelmodus), schwebende Navigation (Start, Tickets, Chat, Kunden, Mehr) und „Mehr“ mit Kacheln für Aufgaben, Status, Benachrichtigungen und die Verwaltung nach Rechten.
Android-Widget (ab 3.1): auf dem Startbildschirm in drei Größen. Klein: Meine offenen und Überfällige. Mittel: vier Kennzahlen und die drei wichtigsten Tickets als Nummern (Tipp öffnet das Ticket). Groß: zusätzlich „Neues Ticket“, „Alle Tickets“ und der eigene Status zum Umschalten. Überfälliges wird rot, im Dunkelmodus ist das Widget dunkel. Es zeigt bewusst keine Betreffs oder Kundennamen. Aktualisiert wird es nach Android-Vorgabe etwa alle 30 Minuten, beim Tippen auf ⟳, beim Öffnen der App und bei jeder Push-Nachricht. Die Statusknöpfe laufen über einen nicht exportierten Empfänger, andere Apps können den Status nicht ändern.
Push-Benachrichtigungen (Android): Die Android-App zeigt Popups bei neuen Tickets, Kundenantworten und Zuweisungen, auch wenn sie geschlossen ist. Das läuft über Firebase Cloud Messaging (Google).
- Standard (nichts einzurichten): Das DeskHub meldet sich beim ersten Senden automatisch beim Push-Dienst des Herausgebers an (
push.phpder Plugin-Webseite, die Adresse leitet sich ausincludes/catalog_defaults.phpab) und schickt nur Geräte-Token und Ticketnummer dorthin. Der Firebase-Schlüssel liegt ausschließlich dort, nie in der App oder in diesem Paket. In der App anmelden und Benachrichtigungen erlauben (ab Android 13 fragt die App einmal danach); mit „Testnachricht an meine Geräte“ unter Einstellungen → Benachrichtigungen → „Android-App: Push-Benachrichtigungen“ prüfen. - Eigenes Firebase-Projekt (für Fortgeschrittene): Wer eine eigene App-Variante mit eigenem Firebase-Projekt betreibt, trägt in
config/config.php'fcm' => ['service_account_file' => '/pfad/ausserhalb/des/webordners/dienstkonto.json']ein (Dienstkonto-Schlüssel aus Projekteinstellungen → Dienstkonten). Eine Oberfläche zum Hochladen gibt es bewusst nicht. Dann geht nichts mehr über den Push-Dienst. Die Dateigoogle-services.jsonder eigenen App kommt beim Bauen in den Ordnermobile/(nicht ausgeliefert).
Einstellbar pro Mitarbeiter: Im Profil (Karte „Android-App: Welche Popups?“) und in der App unter Verwaltung → Benachrichtigungen wählt jeder, wofür er ein Popup bekommt (neues Ticket, Kundenantwort, Zuweisung, Live-Chat, SLA überschritten, Erwähnung) und legt stille Zeiten fest (Serverzeit, auch über Mitternacht). Testnachrichten kommen immer an. Auf Kundenantworten kann direkt in der Benachrichtigung geantwortet werden. Stürzt die App ab, meldet sie das beim nächsten Start an den eigenen Server (Aktivitätsprotokoll, „App-Absturz …“); es gehen keine Ticketinhalte und nichts an Dritte.
Rechte beim Push: Ein Popup bekommt nur, wer das Ticket auch sehen darf (Administrator oder Mitglied der Abteilung des Tickets). Für neue Tickets, Kundenantworten und Live-Chats braucht man zusätzlich das Recht „Antworten“ (Rolle). Eine SLA-Überschreitung melden die App nur dem zugewiesenen Mitarbeiter, Administratoren und Mitarbeitern mit dem Recht „Eskalationsregeln verwalten“, nicht der ganzen Abteilung. Zuweisung und Erwähnung erhält nur, wer Zugriff auf die Abteilung hat. In den Einstellungen („Welche Popups?“) erscheinen jedem nur die Arten, die für ihn überhaupt in Frage kommen; Live-Chat-Popups gibt es nur, wenn der Live-Chat eingeschaltet ist.
Wer bekommt was: ein neues Ticket bekommen alle Admins, Mitarbeiter der Abteilung und Mitarbeiter mit Benachrichtigung für diese Abteilung; eine Kundenantwort der zugewiesene Mitarbeiter (ohne Zuweisung die Abteilung); eine Zuweisung der neue Bearbeiter, aber nicht, wer sich selbst zuweist. Das gilt für Tickets aus Webformular, E-Mail, API und Live-Chat. Ein Tipp auf die Benachrichtigung öffnet das Ticket in der App.
Datenschutz: Standardmäßig steht nur „Neues Ticket #T-123“ in der Nachricht, Betreff und Kundenname verlassen euren Server nicht (auch der Push-Dienst sieht nur Ticketnummer und Geräte-Token). Wer mehr sehen will, schaltet „Betreff und Kundenname in der Benachrichtigung anzeigen“ ein. Jedes Gerät meldet sich beim Ausloggen ab. Pro Mitarbeiter sind bis zu 10 Geräte möglich; abgemeldete oder ungültige Geräte entfernt der Server selbst. Der Versand läuft nach dem Senden der Seite und bremst nichts. Updates: Die Android-App wird nur dann über die alte Version installiert, wenn sie mit demselben Signaturschlüssel erstellt wurde und eine höhere Versionsnummer hat. Nach einem Update die App einmal ganz schließen und neu öffnen.
Update-Hinweis in den Apps
Beide Apps (ab Windows 2.10.0 und Android 3.4.0) fragen beim Start und danach alle 6 Stunden den DeskHub-Server nach der neuesten Version. Der Server fragt die Plugin-Webseite (Schnittstelle api/staff/v1/app_update.php); der Zugangsschlüssel bleibt auf dem Server. Ist dort eine höhere Version veröffentlicht, zeigt die App oben ein Banner „Update verfügbar“ mit Jetzt aktualisieren und Später.
- Windows: Das Setup wird geladen, die SHA-256-Prüfsumme kontrolliert, das Setup gestartet und die App beendet. Im Entwicklungsmodus (nicht installiert) erscheint kein Hinweis.
- Android: Die APK wird geladen und geprüft, dann öffnet sich der Android-Installer. Beim ersten Mal fragt Android einmalig nach „Aus dieser Quelle installieren“. Bei Installationen aus dem Play Store erscheint kein Hinweis (Google aktualisiert selbst).
- Veröffentlichen: In der Plugin-Webseite unter Apps die Datei mit einer höheren Versionsnummer hochladen. Als aktuell gilt immer die höchste Version, nicht die zuletzt hochgeladene.
- Grenzen: Die Prüfsumme stammt vom Server. Die Dateien sind nicht zusätzlich signiert (das Windows-Setup hat keine Code-Signatur). Ein Test geht am einfachsten so: Version N installieren, Version N+1 hochladen, die App neu starten.
Minecraft-Plugin zum Herunterladen
Auf der Seite „Apps“ kann zusätzlich das Minecraft-Plugin (DeskHub-Minecraft.jar, siehe minecraft-plugin/README.md) erscheinen: mit Version, Größe, Prüfsumme und Kurzanleitung (Jar in plugins, config.yml ausfüllen, API-Schlüssel mit dem Recht „Tickets anlegen“, /deskhubmc test). Die Karte lässt sich unter Einstellungen → System („Minecraft-Plugin auf der Apps-Seite anzeigen“) ein- und ausblenden; ausgeblendet ist auch der Download gesperrt. Standard: aus. Die Jar veröffentlicht ihr wie die Apps in der Plugin-Webseite unter Apps (Plattform „Minecraft-Plugin (JAR)“).
Außerdem zeigt die Seite „Apps“ immer die Karten WordPress-Plugin und Chrome-Erweiterung: aktuelle Version, Größe, Prüfsumme, Download und Kurzanleitung. Beide ZIPs veröffentlicht ihr in der Plugin-Webseite unter Apps (Plattform „WordPress-Plugin (ZIP)“ bzw. „Chrome-Erweiterung (ZIP)“); die Versionsnummer wird aus dem Paket gelesen. Ohne veröffentlichte Version steht auf der Karte ein Hinweis.
Chrome-Erweiterung
Im Ordner chrome-erweiterung/ liegt eine Erweiterung für Chrome, Edge und Brave (Manifest V3), die auf Windows, Mac und Linux läuft; ausführlich in chrome-erweiterung/README.md. Seit Version 2.0.0 ist sie ein kleiner Arbeitsplatz in der Browserleiste: Start mit eigenem Status und Kennzahlen, Ticketliste mit Filtern und Suche, Ticket-Ansicht zum Lesen und Antworten (Textbausteine, Signatur, Status danach), interne Notiz, Status, Zuweisung, Wiedervorlage und Beobachten, dazu Aufgaben, Ticket anlegen (auch per Rechtsklick auf markierten Text) und Zähler mit Benachrichtigungen (Abfrage jede Minute). Sie läuft als Popup, in Chromes Seitenleiste oder als eigenes Fenster; es gibt Tastenkürzel (Alt+Shift+N, Alt+Shift+D) und die Adressleisten-Suche „dh“.
- Installieren:
chrome://extensions→ Entwicklermodus → „Entpackte Erweiterung laden“ → Ordnerchrome-erweiterung(eine ältere Version vorher entfernen). Anmelden mit Server-Adresse, E-Mail und Passwort (bei Authenticator mit Code). Es gibt keine Rückfrage und keinen zweiten Anmeldeschritt: Der Serverzugriff steht im Manifest. - Sicherheit: Nur HTTPS, keine Cookies, keine Weiterleitungen; das Token liegt nur im lokalen Speicher der Erweiterung, Abmelden sperrt es auf dem Server und löscht lokale Entwürfe. Der Manifest-Zugriff gilt für alle HTTPS-Adressen, der Code verbindet sich aber nur mit dem angemeldeten Server.
- Grenzen: Meldungen nur bei geöffnetem Browser; Anhänge werden angezeigt, zum Herunterladen das Ticket im Browser öffnen. Ein Ticket zu öffnen sperrt es für andere (wie in der Weboberfläche). Nicht im Chrome Web Store;
node pack.mjserzeugt ein ZIP dafür.
WordPress-Plugin
Im Ordner wordpress-plugin/ liegt das Plugin DeskHub Tickets (ZIP: release/deskhub-tickets-wordpress-<Version>.zip). Besucher einer WordPress-Seite legen damit Tickets in DeskHub an ([deskhub_ticket]) und fragen den Stand ab ([deskhub_status]). Das Plugin nutzt die öffentliche Ticket-API (Formulare mit eigenen Feldern ab Server 1.0.64). Dort wird nur ein API-Schlüssel gebraucht (Verwalten → API-Schlüssel, Recht „Tickets anlegen“, für die Statusabfrage zusätzlich „Tickets lesen“).
- Funktionen: Formular mit den eigenen Feldern und Texten des Hilfethemas aus DeskHub (auch das Formular der Abteilung), Einwilligungs-Kästchen, Statusabfrage mit Verlauf, Spamschutz (Falle-Feld, Mindestzeit, Mengenbegrenzung, optional Cloudflare Turnstile), Verbindungstest, Deutsch und Englisch. Die Farben (Schrift, Rahmen, Feldhintergrund, Knopf) übernimmt das Formular automatisch vom Theme; die Akzentfarbe lässt sich in den Einstellungen fest vorgeben. Ausführlich in
wordpress-plugin/README.md. - Sicherheit: Der Schlüssel liegt nur auf dem WordPress-Server (oder in der
wp-config.php) und geht nie an den Browser. Abteilung, Thema und Priorität sind im Formular unterschrieben. DeskHub selbst lässt sich nicht in einen Rahmen (iframe) einbetten; das Plugin braucht das nicht. - Grenzen: Keine Dateianhänge (die API nimmt nur Text). DeskHub sieht die IP-Adresse des WordPress-Servers, nicht die des Besuchers.
- Stand der Prüfung: Getestet mit einem Nachbau der WordPress-Funktionen und gegen einen echten DeskHub-Server, noch nicht in einer echten WordPress-Installation.
Windows-Programm für Linux und Mac
Das Windows-Programm (Electron) lässt sich auch für Linux und Mac bauen. Dort nutzt es den normalen Fensterrahmen statt der eigenen Titelleiste, ein PNG-Symbol und auf dem Mac ein Bearbeiten-Menü (sonst gehen Kopieren und Einfügen nicht).
- Linux:
npm run build:linuxim Ordnerdesktop/erzeugt ein AppImage und eintar.gz. Auf Linux bauen, dann stimmen die Dateirechte (AppImage kann nur dort gebaut werden). Ein unter Windows gebautestar.gzhat keine Ausführungsrechte: nach dem Entpackensh start-deskhub.shstarten (das Skript liegt im Archiv und setzt die Rechte). Falls Chrome-Sandbox oder Schlüsselbund fehlen: ohne Schlüsselbund wird das Token in einer Datei gespeichert, die nur dein Benutzer lesen kann. - Mac:
npm run build:macerzeugtdmgundzip, aber nur auf einem Mac (Signieren und Beglaubigen geht nur dort und braucht ein Apple-Entwicklerkonto). Ohne Signatur zeigt macOS beim ersten Start eine Warnung; öffnen per Rechtsklick → „Öffnen“. - Autostart: Unter Linux legt das Programm dafür
~/.config/autostart/deskhub.desktopan. - Update-Hinweis: Gibt es nur für Windows (der Server liefert dort das Windows-Setup). Auf Linux und Mac neue Version selbst installieren.
- Noch nicht getestet: Ich konnte das Programm nicht auf Linux oder Mac starten; gebaut und geprüft ist das Archiv, nicht der Betrieb.
System-Update und Datenbank-Update
Adminportal → System-Update hat zwei Teile:
Neue Programmversion installieren: Zeigt verfügbare Versionen und installiert die gewählte mit einem Klick (oder per hochgeladener ZIP). Vor jedem Update wird automatisch ein Backup erstellt. Eure Konfiguration, die Datenbank, hochgeladene Dateien, bereitgestellte Apps, Backups und Plugins werden nie überschrieben. Der Download erfolgt nur über eine geprüfte, verschlüsselte Verbindung. Danach wird die Datenbank automatisch angepasst.
Datenbank aktualisieren: Die Karte „Datenbank“ zeigt, ob die Datenbank zum installierten Programm passt. Wenn nicht, erscheint dort und für Admins oben auf jeder Seite ein Hinweis. Der Knopf „Datenbank aktualisieren“ erstellt zuerst ein Backup und spielt dann alle fehlenden Änderungen ein. Das ist der richtige Weg, wenn ihr Dateien per FTP hochgeladen habt. Scheitert das Backup, wird die Datenbank nicht angefasst.
Signierte Updates: Ist in DeskHub ein Herausgeber-Schlüssel eingebaut (includes/catalog_defaults.php), installiert das System-Update nur Releases, die mit diesem Schlüssel signiert sind. Ein manipuliertes Paket oder ein Release ohne Signatur wird abgelehnt und im Admin-Protokoll vermerkt. Ein manuell hochgeladenes ZIP wird nicht geprüft, ladet nur Pakete aus vertrauenswürdiger Quelle hoch. Es steckt kein Zugangstoken mehr im Programmcode: Die Releases werden öffentlich gelesen. Ist das Repository privat (Gitea meldet beim Laden der Versionen „404“), tragt ihr ein Lese-Token ein: am einfachsten im Adminportal unter System-Update → Zugang zum Update-Server (wird verschlüsselt gespeichert), oder in config/config.php im großen return [ … ]; als 'update' => ['token' => '…'],. In Gitea erzeugt ihr es unter Einstellungen → Anwendungen → Zugriffstoken mit der Berechtigung „repository: Lesen“ (nur Leserecht vergeben). Ein Eintrag in der config.php hat Vorrang.
Release veröffentlichen (für den Herausgeber):
- ZIP des Projekts als
deskhub-<version>.zippacken (ohneconfig/config.php, Datenbank, Backups, Uploads,plugins/,node_modules). - Signieren:
php tools/release-sign.php deskhub-1.0.7.zip herausgeber-privat.pem 1.0.7(derselbe private Schlüssel wie für Plugins und Themes). Das erzeugtdeskhub-1.0.7.zip.sig. - Im Gitea-Release beide Dateien als Anhänge hochladen, mit genau diesen Namen.
Nach jedem Update: Browser-Cache leeren (Strg + F5).
Import aus osTicket
Wer von osTicket auf DeskHub umzieht, kann den Bestand übernehmen: Kunden, Abteilungen, Hilfethemen, Tickets, Nachrichten (Kundennachrichten, Antworten, interne Notizen), Mitlesende und Anhänge. Unterstützt werden SQL-Dumps von osTicket 1.10 bis 1.18, als phpMyAdmin-Export oder mit mysqldump, auch mit einem anderen Tabellenpräfix als ost_.
Vorbereitung
- Backup von DeskHub erstellen (Adminportal → Backup). Der Import lässt sich wiederholen, ohne etwas doppelt anzulegen, ein Backup ist trotzdem sinnvoll.
- Mitarbeiter in DeskHub anlegen. osTicket-Mitarbeiter werden über die E-Mail-Adresse den DeskHub-Mitarbeitern zugeordnet. Wer in DeskHub fehlt, kann nicht zugewiesen werden: Seine Tickets werden unzugewiesen importiert, seine Antworten ohne Mitarbeiter übernommen. Legt deshalb vorher alle Kollegen mit derselben E-Mail-Adresse an wie in osTicket.
- Dump erstellen. In osTicket (oder phpMyAdmin) die komplette Datenbank als SQL exportieren. Der Dump darf groß sein: Ein Export mit mehreren hundert MB (Anhänge und Sitzungsdaten) funktioniert, die Tabellen werden blockweise gelesen.
- Nur bei MySQL-Hosting mit knappen Limits: Große Dateien legt ihr besser per FTP in den DeskHub-Ordner (Option 1), statt sie im Browser hochzuladen.
Durchführung
Adminportal → Einstellungen → „📥 osTicket Import“.
- Hochladen: Entweder den Dateinamen eintragen, wenn die SQL-Datei im DeskHub-Hauptordner liegt (empfohlen, vor allem bei großen Dateien), oder die Datei direkt hochladen (sie wird in Teilen übertragen, deren Größe zum Upload-Limit des Servers passt).
- Analysieren: DeskHub liest die Datei und zeigt, was sie enthält (Kunden, Tickets, Nachrichten, Abteilungen, Hilfethemen, Anhänge). Der Fortschrittsbalken läuft von selbst, das Fenster muss offen bleiben.
- Optionen: Auswählen, was importiert werden soll. Die Reihenfolge ist fest: Kunden → Abteilungen und Hilfethemen → Tickets → Nachrichten → Anhänge. Anhänge setzen die Nachrichten voraus.
- Import: Läuft in kleinen Schritten, mit Fortschritt je Bereich. Am Ende steht eine Zusammenfassung mit Hinweisen.
Was dabei passiert
| osTicket | DeskHub |
|---|---|
| Kunden | Kunden mit Name und E-Mail-Adresse (ohne Adresse werden sie übersprungen). Zugangsdaten werden nicht übernommen, Kunden vergeben bei Bedarf ein neues Passwort. |
| Abteilungen, Hilfethemen | Fehlende werden angelegt, vorhandene mit gleichem Namen wiederverwendet. Hilfethemen kommen mit der richtigen Abteilung und Priorität. |
| Ticketstatus | Offen → offen, Gelöst → gelöst, Geschlossen und Archiviert → geschlossen. Gelöschte Tickets werden nicht importiert. |
| Priorität | Nach Namen, sonst nach Rangfolge (dringendste zuerst). |
| Mitarbeiter | Über die E-Mail-Adresse (siehe Vorbereitung). |
| Quelle | Web, E-Mail, Telefon und API werden übernommen, Sonstiges wird zu Web. |
| Zeiten | Erstellt, zuletzt geändert und gelöst/geschlossen bleiben erhalten. Die erste Antwort wird aus der ersten Mitarbeiter-Antwort abgeleitet. Offene Tickets bekommen neue SLA-Fristen nach euren Zeiten. |
| Nachrichten | Kundennachrichten werden als Text übernommen (Zitate früherer Mails werden entfernt), Antworten und interne Notizen behalten ihre Formatierung. Nachrichten ohne Text werden ausgelassen, außer sie haben einen Anhang. |
| Anhänge | Dateien bis 50 MB. Eingebettete Bilder in Mails (Logos, Signaturen) werden nicht als Anhang übernommen. Gespeichert wird unter einem zufälligen Namen, die Endung bleibt bei bekannten Dateitypen erhalten, alles andere wird .bin. |
Gut zu wissen
- Wiederholbar: Vorhandene Ticketnummern und Kunden werden übersprungen, bereits importierte Nachrichten und Anhänge nicht doppelt angelegt. Ein abgebrochener Import lässt sich also einfach neu starten.
- Löschen: Auf der Optionsseite gibt es „Nur Nachrichten löschen“ und „Alle Tickets löschen“, falls ein Import neu beginnen soll. Beides löscht Daten in DeskHub unwiderruflich, auch echte Tickets, die nicht aus dem Import stammen.
- Nach dem Import: Stichproben ansehen (Ticketliste, ein paar Tickets mit Anhängen), ob die Abteilungen stimmen und ob Kunden ihre Tickets finden.
- Nicht importiert: Eigene Formularfelder, Aufgaben, Wissensdatenbank (FAQ), Benutzerkonten und Passwörter, Mitarbeiter-Konten, Vorlagen, Regeln und Einstellungen. Diese richtet ihr in DeskHub neu ein.
- Dauer: Ein Dump mit rund 1.700 Tickets und 450 MB Anhangsdaten braucht gut 3 Minuten für das Hochladen (bei Direkt-Upload) und etwa eine halbe Minute für Analyse und Import.
Plugins verwenden
Mit Plugins rüstet ihr zusätzliche Funktionen nach, ohne DeskHub selbst zu verändern. Alles läuft unter Adminportal → Plugins (nur für echte Admins).
Aufbau der Seite (ab Server 1.0.53, wie bei WordPress): Drei Reiter. Installiert zeigt jedes Plugin als Zeile mit Zustand (Aktiv, Inaktiv, Fehler, Update), Beschreibung, Version, Berechtigungen und den Aktionen Aktivieren/Deaktivieren, Öffnen, Aktualisieren und Entfernen; oben stehen Filter mit Zahlen (Alle, Aktiv, Inaktiv, Mit Fehler, Update verfügbar) und eine Suche. Plugin hinzufügen enthält den Katalog als Kacheln (mit Suche) und den ZIP-Upload. Katalog & Schlüssel enthält Katalog-Adresse und Herausgeber-Schlüssel.
Geprüfter Modus (Standard, wenn euer DeskHub einen offiziellen Katalog mitbringt): Der Herausgeber eurer DeskHub-Version trägt vor dem Release seinen eigenen Katalog und seinen Signierschlüssel ein (siehe Plugin- und Theme-Webseite). Dann zeigt die Plugin-Seite oben „Geprüfte Plugins“ mit dem aktuellen Angebot, und es gilt:
- Plugins aus dem Katalog müssen mit dem Schlüssel des Herausgebers signiert sein. Nicht signierte oder fremd signierte Katalog-Pakete werden abgelehnt.
- Eigene Plugins lassen sich zusätzlich über „Eigenes Plugin hochladen“ installieren, auch ohne Signatur (siehe unten). Sie sind in der Liste als „Eigenes Plugin / nicht vom Herausgeber geprüft“ markiert.
- Der Katalog lädt automatisch: Er erscheint ohne Klick, DeskHub hält ihn im Hintergrund alle 30 Minuten aktuell (über die Automatisierung), und bei Ausfall des Katalog-Servers bleibt der zuletzt geladene Stand sichtbar. Gibt es für ein installiertes Plugin eine neuere Version, erscheint für Admins oben auf jeder Seite der Hinweis „Plugin-Updates verfügbar“. Installiert wird ein Update nie von selbst, sondern erst, wenn ihr „Aktualisieren“ wählt. Mit „Katalog aktualisieren“ lässt sich der Abruf auf Wunsch sofort auslösen.
Katalog und Schlüssel sind fest in DeskHub eingebaut (includes/catalog_defaults.php, Teil des Programmcodes). Es gibt keine Einstellung, Umgebungsvariable oder Oberfläche, mit der Admins den Katalog ändern oder den Signaturzwang für Katalog-Plugins abschalten können. Der Katalog ist zusätzlich durch einen Zugangsschlüssel geschützt, den DeskHub bei jedem Abruf mitschickt (nur an den offiziellen Katalog, nur über https). Er hält zufällige Besucher fern, ist aber kein Geheimnis gegenüber Admins, die den DeskHub-Code lesen können. Ändern lässt sich das nur durch den Herausgeber mit einer neuen DeskHub-Version. Themes sind davon nur beim Katalog betroffen: Er ist vorgegeben und Themes müssen signiert sein; der manuelle Theme-Upload (nur CSS, Bilder, Schriften) bleibt möglich.
Aus dem Katalog installieren (ohne offiziellen Katalog): Die Plugin-Webseite (siehe Plugin- und Theme-Webseite) liefert einen Katalog. Tragt unter Plugins → „Katalog und Herausgeber-Schlüssel“ die Katalog-Adresse und den öffentlichen Herausgeber-Schlüssel ein (den Schlüssel liefert der Betreiber der Webseite, abrufbar unter /publisher-key.php) und aktiviert „Nur signierte Plugins installieren“. Danach seht ihr alle Plugins mit Version, Beschreibung und angeforderten Berechtigungen und installiert sie mit einem Klick. DeskHub lädt nur über https, vergleicht die Prüfsumme und prüft die Signatur, bevor etwas installiert wird.
Manuell / eigene Plugins installieren (auch im geprüften Modus möglich, damit ihr selbst entwickelte Plugins nutzen könnt):
- Plugin als ZIP-Datei bereithalten. Nennt der Anbieter eine Prüfsumme (SHA-256) oder eine Signatur, tragt sie ein, dann wird das Paket vor der Installation geprüft.
- ZIP hochladen und bestätigen, dass ihr der Quelle vertraut.
- Das Plugin ist danach noch inaktiv. Mit „Aktivieren“ schaltet ihr es ein. Vorher bestätigt ihr die Berechtigungen, die das Plugin anfordert (siehe unten). Dabei wird ein Backup erstellt und das Plugin legt bei Bedarf eigene Datenbank-Tabellen an.
Berechtigungen: Jedes Plugin nennt, welche Erweiterungspunkte es nutzen will: auf Ticket-Ereignisse reagieren, im Hintergrund laufen, Menüpunkte und Seiten anlegen, Bausteine in der Ticketansicht zeigen, eigene API-Endpunkte bereitstellen, eigene Datenbank-Tabellen anlegen. Ihr seht die Liste vor dem Aktivieren und bestätigt sie. DeskHub lässt das Plugin nur diese Erweiterungspunkte registrieren. Fordert eine neue Version zusätzliche Berechtigungen an, wird das Plugin automatisch angehalten, bis ihr die neuen bestätigt habt. Das gilt auch, wenn jemand Dateien per FTP austauscht.
Verwalten: Plugins lassen sich deaktivieren, durch eine neuere Version ersetzen (gleiche Datei erneut hochladen) und entfernen. Beim Entfernen könnt ihr wählen, ob die Daten des Plugins gelöscht werden sollen.
Sicherheit, bitte unbedingt beachten:
- Ein Plugin ist Programmcode und läuft mit allen Rechten des Systems, also auch mit Zugriff auf die gesamte Datenbank. Es gibt keine Abschirmung: Die Berechtigungen begrenzen nur, welche Erweiterungspunkte ein Plugin nutzen darf, nicht was sein Code sonst tut. Wirklichen Schutz bietet die Herkunft: Installiert nur Plugins aus Quellen, denen ihr vertraut, und aktiviert „Nur signierte Plugins installieren“.
- Signatur: Eine Signatur belegt, dass ein Paket unverändert vom Inhaber des hinterlegten Herausgeber-Schlüssels stammt. Ein verändertes Paket, eine fremde Signatur oder eine auf eine andere Version übertragene Signatur wird abgelehnt. In der Plugin-Liste steht bei jedem Plugin „Signiert“ oder „Nicht signiert“ und woher es kam.
- Fehler in einem Plugin legen das System nicht lahm: Das Ticket oder die Seite funktioniert weiter. Nach drei Fehlern wird das Plugin automatisch deaktiviert, der Fehlertext steht in der Plugin-Liste.
- Notausschalter: Legt auf dem Server im Ordner
pluginseine leere Datei namens.disabledan, dann wird kein Plugin mehr geladen. Zum Wiederaktivieren die Datei löschen. - Der Ordner
pluginswird bei System-Updates nie überschrieben.
Mitgeliefertes Plugin: Tagesbericht per E-Mail
Unter Plugins/plugins/tagesbericht-1.0.1.zip (im Projektordner neben DeskHub-Webseite/) liegt ein fertiges Plugin. Es schickt Mitarbeitern jeden Morgen eine Übersicht: offene, unzugewiesene, überfällige und eigene Tickets, Zugänge und Erledigungen der letzten 24 Stunden sowie die fünf ältesten offenen Tickets. Jeder sieht nur Tickets seiner Abteilungen.
Nach Installation und Aktivierung findet ihr im Menü den Punkt „Tagesbericht“: Dort schaltet ihr den Versand ein, legt Uhrzeit, Werktage und Empfänger fest und könnt einen Testbericht an euch schicken. Voraussetzung ist der eingerichtete E-Mail-Versand.
Mitgelieferte Plugins: Virenscan, Spamfilter, Discord/Telegram-Bot, Vertretung, Schichtübergabe, Rundmail, Überwachung, Datenschutz
Diese Plugins liegen als Zip unter Plugins/plugins/. Alle außer dem Discord/Telegram-Bot laufen auf jedem DeskHub ohne Änderung am Server. Die Plugins mit „Adminportal“ (Virenscan, Überwachung, Datenschutz) erscheinen mit den aktuellen Server-Dateien in der Gruppe „Verwalten“, sonst im Hauptmenü; ihre Seiten sind in beiden Fällen nur für Administratoren. Nur der Discord/Telegram-Bot braucht DeskHub 1.0.30 oder neuer: Er kommt mit dem normalen System-Update (Adminportal → Update), nur version.php und bootstrap.php muss man bei Updates weiterhin von Hand hochladen. Installation wie bei jedem Plugin: Adminportal → Plugins → Zip hochladen → Berechtigungen bestätigen → aktivieren. Jedes Plugin bringt eine eigene Seite im Menü mit.
| Plugin | Zip | Berechtigungen | Was es tut |
|---|---|---|---|
| Anhänge-Virenscan | virenscan-1.2.1.zip |
hooks.tickets, hooks.cron, ui.menu, db.migrations | Prüft Anhänge neuer Tickets und Antworten und sperrt gefährliche Dateien (Quarantäne, interne Notiz, Tag „Virus-Verdacht“, Mail an den Administrator). Braucht nichts auf dem Server: Die eingebaute Dateianalyse erkennt Programme und Skripte, getarnte Dateien (zum Beispiel eine .exe als PDF), doppelte Endungen, Office-Makros, PDF-Tricks, Skripte in HTML/SVG und Archive mit solchen Dateien. Optional gleicht eine Hash-Abfrage bei VirusTotal (nur der SHA-256-Wert, kostenloser Schlüssel) Dateien mit bekannter Schadsoftware ab; ClamAV wird zusätzlich genutzt, falls es schon installiert ist. Erkennt keine ganz neuen Viren in normal aussehenden Dokumenten. Menüpunkt im Adminportal, nur für Administratoren. |
| VirusTotal-Anhangsprüfung | virustotal-1.0.0.zip |
hooks.tickets, hooks.cron, ui.menu, db.migrations | Hält jeden Anhang zurück, bis VirusTotal ihn geprüft hat (nur Fingerabdruck, keine Datei); sauber = frei, Schadsoftware = gesperrt, unbekannt = zurückgehalten (oder auf Wunsch hochgeladen). Siehe unten. |
| Spam- und Missbrauchsfilter | spamfilter-1.0.2.zip |
hooks.tickets, ui.menu, ui.sidebar, db.migrations | Bewertet jedes neue Ticket mit Punkten (Phishing-Wendungen, Marken-Nachahmung im Absendernamen, Link-Verkürzer, Wegwerf-Adressen, Wiederholungen/Kampagnen; bekannte Absender bekommen Abzug). Ab 70 Punkten wird das Ticket automatisch als Spam abgelegt, ab 35 erhält es den Tag „Spam-Verdacht“. Freigabe- und Sperrliste, eigene Wörter, Protokoll mit Knöpfen „Kein Spam“ / „Doch Spam“ und eine Bewertung in der Seitenleiste des Tickets. |
| Discord- und Telegram-Bot | community-bot-1.0.2.zip |
api.public, hooks.tickets, ui.menu, db.migrations | Mitglieder legen mit /ticket im Discord oder in Telegram ein Ticket an, bekommen die Ticketnummer zurück und werden bei Antworten und bei Lösung benachrichtigt. Weitere Befehle: /status, /antwort. Der Server nimmt die Anfragen direkt entgegen (kein eigener Bot-Server); Anfragen werden per Signatur (Discord) bzw. Geheimtoken (Telegram) geprüft. Je Person gilt eine Obergrenze pro Stunde. Discord braucht die PHP-Erweiterung sodium. Einrichtung (Anwendungs-ID, Public Key, Bot-Token) auf der Plugin-Seite. |
| Urlaub und Vertretung | vertretung-1.1.0.zip |
hooks.tickets, hooks.cron, ui.menu, db.migrations | Mitarbeiter tragen Abwesenheit mit Vertretung ein. Zum Beginn gehen ihre offenen Tickets an die Vertretung, neue Tickets ebenfalls (auch bei der automatischen Zuweisung der Abteilung), am Ende kommen die noch offenen Tickets zurück. Setzt dafür den Urlaubsstatus im Profil. Ab Server 1.0.56 (Plugin ab 1.1.0 für Server 1.0.55) gibt auch die Abwesenheit im Profil (ohne Plugin) offene Tickets an die Vertretung weiter und nach dem Urlaub zurück. Ab 1.0.55 sieht und bearbeitet die Vertretung während der Abwesenheit auch die Abteilungen des Abwesenden, selbst wenn sie dort sonst keinen Zugang hat (Ketten bis drei Stufen; bei einem abwesenden Administrator die Abteilungen der zugewiesenen offenen Tickets). Braucht den Cron-Aufruf bzw. den Pseudo-Cron. |
| Schichtübergabe | schichtuebergabe-1.1.4.zip |
hooks.cron, ui.menu, ui.sidebar, db.migrations | Am Ende der Schicht schreibt ein Mitarbeiter eine kurze Notiz (für alle oder nur eine Abteilung). Die nächste Schicht sieht sie sofort nach der Anmeldung als deutlichen Hinweis oben auf jeder Seite (rot bei wichtigen Notizen, mit Text und Link), außerdem als „neu“-Zähler im Menü und, wenn wichtig, in der Seitenleiste jedes Tickets. Der Hinweis oben braucht die aktuellen DeskHub-Dateien (staff/_header.php, includes/plugins.php), sonst bleiben Zähler und Seitenleiste. Der Verfasser sieht, wer sie gelesen hat (auch als Bestätigung auf der Übersicht). Alte Notizen werden automatisch gelöscht (Frist nur für Administratoren). Für Mitarbeiter und Administratoren. |
| Störungsmitteilung und Rundmail | rundmail-1.0.1.zip |
hooks.cron, ui.menu, db.migrations | Eine Nachricht an viele Kunden gleichzeitig, zum Beispiel bei Wartung oder Ausfall. Empfänger: Kunden mit offenen Tickets, einer Abteilung oder einer Organisation. Mit Vorlagen, Empfängerprüfung, Probemail und Protokoll; jede Mail geht einzeln raus, der Versand läuft im Hintergrund. Mitarbeiter schreiben nur an Kunden ihrer eigenen Abteilungen (höchstens 200 Empfänger, 5 Rundmails pro Stunde). Für Mitarbeiter und Administratoren. |
| Website- und Server-Überwachung | ueberwachung-1.1.2.zip |
hooks.cron, ui.menu, db.migrations | Prüft Webseiten, Ports und Zertifikate. Bei Ausfall (nach 2 Fehlschlägen in Folge) oder einem Zertifikat, das in 14 Tagen abläuft, legt das Plugin ein Ticket an und schickt eine Mail; nach der Behebung kommt die Entwarnung und das Ticket wird gelöst. Der je Ziel eingestellte Prüfabstand (ab 1 Minute) wird eingehalten: Der Hintergrunddienst von DeskHub läuft jede Minute, mit dem echten Server-Cronjob (Einstellungen → Cron-Jobs → „Neu installieren / aktualisieren“) auch nachts ohne Besucher, sonst nur solange die Seite aufgerufen wird. Für ältere Dateien liegt ein eigener Cronjob bei (plugins/ueberwachung/cron.php). Menüpunkt im Adminportal, nur für Administratoren. |
| Datenschutz | datenschutz-1.2.1.zip |
hooks.cron, ui.menu, db.migrations | Kundendaten aus Tickets ohne Registrierung werden nach einer frei wählbaren Frist (Tage, Wochen, Monate oder Jahre; Standard 30 Tage nach dem Schließen) unwiderruflich anonymisiert. Welche Daten, bestimmen Sie selbst: nur Name, nur E-Mail-Adresse, beides oder komplett (auch IP, Mitleser, Zusatzfelder, Nachrichten und Anhänge). Daten registrierter Kunden bleiben bis zur Löschung auf Antrag, die der Administrator mit einem Klick ausführt. Die automatische Anonymisierung ist nach der Installation aus und muss bewusst eingeschaltet werden. Menüpunkt im Adminportal, nur für Administratoren. |
| authentik-Anmeldung | authentik-1.2.4.zip |
ui.menu, auth.login, auth.customer | Mitarbeiter und Kunden melden sich mit authentik an (OpenID Connect mit PKCE). Mitarbeiter verknüpfen ihr Konto selbst, Kundenkonten werden bei Bedarf angelegt. Benötigt Server 1.0.52. Siehe unten. |
Hinweis zur Berechtigung api.public: Sie erlaubt einem Plugin eine ohne Anmeldung erreichbare Adresse (/api/public/v1/plugin_webhook.php?p=<plugin>&e=<name>). Der Bot prüft jede Anfrage selbst; trotzdem solltet ihr diese Berechtigung nur Plugins geben, denen ihr vertraut.
Mitgeliefertes Plugin: VirusTotal-Anhangsprüfung
Plugins/plugins/virustotal-1.0.0.zip (Quelle: Plugins/plugins/virustotal/, ausführlich in dessen README.md) hält jeden neuen Anhang zurück, bis VirusTotal ihn geprüft hat. Anders als der Virenscan, der VirusTotal erst nachträglich fragt, sperrt dieses Plugin zuerst.
- Ablauf: Anhang sofort gesperrt (
[IN PRÜFUNG], Datei im Ordneruploads/vt-pruefung/) → Abfrage des SHA-256-Fingerabdrucks → sauber: freigegeben; ab Schwelle Scanner (Standard 3) mit Schadsoftware: gesperrt, Tag „Virus-Verdacht“, Hinweis im Ticket, Mail an den Administrator; unbekannt: zurückgehalten, bis ein Administrator unter VirusTotal freigibt oder löscht (einstellbar: freigeben oder hochladen). - Datenschutz: Standardmäßig verlässt keine Datei den Server. „Unbekannte Dateien hochladen“ (bis 32 MB, aus) sendet die Datei an VirusTotal, wo sie gespeichert und Dritten zugänglich wird: nur bewusst einschalten.
- Einrichten: Kostenlosen API Key bei virustotal.com holen, unter VirusTotal eintragen, Schlüssel testen. Ohne Schlüssel wird nichts zurückgehalten; Anhänge von vor dem Einschalten bleiben unberührt.
- Limits: Der kostenlose Schlüssel erlaubt 4 Abfragen pro Minute und 500 pro Tag; das Plugin hält sich daran (4 pro Lauf, 480 pro Tag), dann entsteht eine Warteschlange. Mit echtem Cronjob laufen die Abfragen jede Minute, sonst alle 5 Minuten.
- Grenzen: Unbekannt heißt nicht sauber (neue Schadsoftware kennt VirusTotal oft nicht), darum gilt „zurückhalten“ als Standard; kein Entpacken von Archiven (dafür der Virenscan). Nicht gegen das echte VirusTotal ausprobiert: geprüft ist der Ablauf gegen einen nachgebauten Dienst (
tests/plugin_virustotal.php). Bitte nach dem Einrichten mit einem Testanhang ausprobieren (zum Beispiel einer harmlosen Textdatei).
Mitgeliefertes Plugin: authentik-Anmeldung (OpenID Connect)
Mitarbeiter und Kunden melden sich mit authentik an; auf der Anmeldeseite des Mitarbeiterbereichs erscheint zusätzlich „Mit authentik anmelden“. Das Plugin liegt als Plugins/plugins/authentik-1.2.4.zip (Quelle: Plugins/plugins/authentik/, ausführlich in dessen README.md) und braucht Server 1.0.52 (die Erweiterung für Anmelde-Plugins).
- Einrichten: In authentik einen OAuth2/OpenID-Provider (vertraulich) anlegen, als Umleitungs-URI die Adresse von der Einstellungsseite eintragen (
https://<DeskHub>/staff/plugin_login.php?p=authentik&e=callback), Bereicheopenid email profile(für Gruppen zusätzlichgroups). In DeskHub das Plugin hochladen, aktivieren (Berechtigung auth.login bestätigen) und unter authentik Issuer-Adresse (https://auth.example.de/application/o/<Anwendung>), Client-ID und Geheimnis eintragen, einschalten, Verbindung testen. - Mitarbeiter: Nur wer in authentik bestätigt ist und in DeskHub ein aktives, verknüpftes Mitarbeiterkonto hat. Verknüpft wird selbst unter „Mein authentik-Konto“ (oder automatisch bei der ersten Anmeldung mit gleicher E-Mail-Adresse; abschaltbar mit „Nur verknüpfte Konten“); die Verknüpfung hängt an der festen authentik-Kennung, nicht an der E-Mail-Adresse. Optional nur Mitglieder einer authentik-Gruppe. Mitarbeiterkonten werden nicht automatisch angelegt.
- Kunden (Ticketersteller): In den Einstellungen einschaltbar. Es zählt die in authentik bestätigte E-Mail-Adresse; ein passendes Kundenkonto wird angemeldet, bei Bedarf automatisch angelegt (ohne Passwort, Name aus authentik, Sperrliste wird beachtet), optional nur für eine eigene authentik-Gruppe. Dieselbe Rückkehr-Adresse wie bei Mitarbeitern. Authenticator-Code von DeskHub entfällt dabei (authentik übernimmt das). E-Mail und Passwort funktionieren weiter, auch wenn authentik ausfällt.
- Sicherheit: PKCE,
state,nonce, einmalig und höchstens 10 Minuten gültig; Aussteller, Zielgruppe und Ablauf werden geprüft; das Token kommt direkt von authentik über eine geprüfte HTTPS-Verbindung; das Geheimnis liegt verschlüsselt in der Datenbank; jede Anmeldung und Ablehnung steht im Admin-Protokoll. - Grenzen: Keine Rollen aus Gruppen, kein Single Logout; Kunden werden nur über die E-Mail-Adresse zugeordnet. Nicht an einem echten authentik ausprobiert: geprüft ist der Ablauf gegen einen nachgebauten Anmeldedienst (
tests/plugin_authentik.php,tests/plugin_login.php). Bitte nach dem Einrichten einmal mit einem Testkonto anmelden und im Admin-Protokoll nachsehen.
Mitgeliefertes Plugin: Synology NAS Backup (WebDAV)
Unter Plugins/plugins/nas-backup-2.6.5.zip liegt ein Plugin, das die Backups eures Servers automatisch auf eine Synology NAS (oder einen anderen WebDAV-Server) kopiert. Es ist aufgebaut wie das Plugin „Tagesbericht“: Es braucht nur die Standard-Berechtigungen hooks.cron und ui.menu und verändert nichts am Kern von DeskHub. Installation: Adminportal → Plugins → Zip hochladen → Berechtigungen bestätigen → aktivieren. Danach gibt es auf der Seite Backup den Reiter „Synology NAS Backup“ (kein eigener Menüpunkt in der Seitenleiste; nur Administratoren sehen ihn). Dafür braucht das Plugin keine zusätzliche Berechtigung.
Auf der Synology einrichten:
- Paket „WebDAV Server“ installieren und HTTPS (Port 5006) aktivieren.
- Einen eigenen Benutzer anlegen, der nur Zugriff auf einen freigegebenen Ordner (zum Beispiel
backup) hat. - Den Port im Router freigeben (oder einen Reverse-Proxy auf 443 nutzen) und die NAS über eine feste Adresse erreichbar machen (zum Beispiel Synology-DDNS
meine-nas.synology.me) mit einem gültigen Zertifikat (Let’s Encrypt in der Synology-Systemsteuerung).
So arbeitet es mit der Seite „Backup“ zusammen: Das Plugin schaut alle paar Minuten in den Backup-Ordner des Servers. Jedes Backup, das dort neu liegt (Zeitplan der Seite „Backup“, „Backup jetzt erstellen“, Backups vor Updates), wird auf die NAS kopiert, sobald es geprüft ist (defekte Backups werden nie kopiert). Den Zeitplan stellt ihr also wie gewohnt auf der Seite „Backup“ ein; ist er dort ausgeschaltet, entstehen keine Backups und es gibt nichts zu kopieren. Alle Backups werden automatisch auf Wiederherstellbarkeit geprüft (siehe Abschnitt Backup), ohne dass jemand „Prüfen“ klicken muss.
Auch die Liste „Vorhandene Backups“ auf der Seite „Backup“ zeigt die NAS: Jede Sicherung trägt die Marke „☁ auf NAS“ oder „nur hier“ (mit Knopf „Auf NAS“), und Sicherungen, die nur auf der NAS liegen, stehen ebenfalls in der Liste (mit „Auf Server holen“ und „Von NAS löschen“). Danach lassen sie sich wie jedes andere Backup wiederherstellen. Dafür braucht das Plugin keine zusätzliche Berechtigung (die Liste darf jedes Plugin ergänzen, das einen Reiter unter „Backup“ anbietet).
Die Seite „Synology NAS Backup“ zeigt oben den Status, darunter die Liste der Backups (auf dem Server / auf der NAS, geprüft / defekt) und die Einstellungen:
- Verbindung: IP-Adresse oder Domain, Port (Synology: 5005 HTTP / 5006 HTTPS, über Reverse-Proxy 443), Benutzer, Passwort, HTTPS, Zielverzeichnis auf der NAS (beginnt mit dem Namen des freigegebenen Ordners, zum Beispiel
/usbshare2/Geschichten/). Die Server-URL wird als Vorschau angezeigt, „Verbindung testen“ prüft alles. - Aufbewahrung: maximales Alter in Tagen und maximale Anzahl, beide Regeln gelten gleichzeitig (0 = aus); „Aktuell aktive Regeln“ zeigt, was gilt. Gelöscht werden nur Dateien, die das Plugin selbst angelegt hat (
backup_….zip). - Backups einzeln bewegen: „Auf NAS“ für ein Backup, das noch nicht dort liegt, „Fehlende Backups jetzt kopieren“ für alle. Sicherungen, die nur auf der NAS liegen (zum Beispiel nach einem Serverumzug), holt ihr mit „Auf Server holen“; sie werden geprüft und lassen sich dann auf der Seite „Backup“ wiederherstellen.
- Eigene Backups des Plugins (optional): Mit eigenem Zeitplan (stündlich bis monatlich, Uhrzeit), Inhalt (Datenbank und/oder Dateien, „wichtigste Dateien“ oder alles, Pfade ausschließen) erstellt das Plugin zusätzlich Backups, die nur auf der NAS liegen. „Eigenes Backup jetzt starten“ läuft im Hintergrund.
Große Backups (ab Plugin 2.4): Manche Server oder Proxys vor der NAS nehmen nur Dateien bis zu einer Größe an (Cloudflare: 100 MB, Fehler „HTTP 413“). Das Plugin lädt solche Backups deshalb in Stücken hoch:
- Als eine Datei (bevorzugt): Jedes Stück trägt den Header
Content-Rangeund sagt der NAS, wohin es gehört (Synology DSM 7 kann das). Auf der NAS liegt am Ende direkt die fertige.zip. Nach jedem Stück wird die Größe geprüft, damit ein Server, der den Header stillschweigend ignoriert, auffällt. Bei einem Fehler wird die halbe Datei gelöscht; pro Stück gibt es bis zu vier Versuche (3, 6, 12 Sekunden Pause). - Als Teile (Rückfall): Kann die NAS das nicht, entstehen
backup_….zip.part001,.part002… und zuletzt eine kleine Abschlussdateibackup_….zip.partsmit Größe und Prüfsumme. Erst mit ihr gilt die Sicherung als vollständig. Die Liste zeigt sie als ein Backup; „Auf Server holen“ setzt die Teile wieder zusammen und prüft die Prüfsumme. Von Hand zusammensetzen:cat backup_….zip.part[0-9][0-9][0-9] > backup_….zip(Linux/Synology per SSH) odercopy /b backup_….zip.part0* backup_….zip(Windows, bis 99 Teile). - Einstellungen (Karte „Große Backups in Stücken hochladen“): „Wann in Stücken?“ (automatisch: erst ganz, bei Fehler in Stücken; immer; nie) und die Stückgröße von 10 bis 4000 MB (Standard 200 MB). Lehnt der Server ein Stück mit 413 ab, halbiert das Plugin die Größe selbst und merkt sich den Wert. Hinter Cloudflare (Gratis-Tarif) sind höchstens 100 MB je Stück möglich: dort 50 MB einstellen.
Im Hintergrund und mit Zeitangabe: „Eigenes Backup“, „Auf NAS“, „Fehlende kopieren“ und „Auf Server holen“ laufen nach der Antwort im Hintergrund (kein Warten, kein Cloudflare-Timeout). Das Ergebnis steht im Status, zum Beispiel „Backup erstellen: 12 Min, Hochladen: 4550 MB in 21 Min (3,6 MB/s)“; so seht ihr, ob die Zeit beim Erstellen oder beim Hochladen vergeht. Nach jedem Klick lädt sich die Seite neu (normale Adresse), sodass das automatische Neuladen alle 10 Sekunden den Klick nicht noch einmal absendet. Das Plugin nutzt ab DeskHub 1.0.45 die gemeinsame Backup-Sperre.
Gut zu wissen:
- Jedes Backup wird nach dem Hochladen auf der NAS auf vollständige Größe kontrolliert; unvollständige Dateien werden wieder gelöscht.
- Das Passwort wird verschlüsselt gespeichert. Zugangsdaten werden nie an Weiterleitungen geschickt. Ohne HTTPS sind nur Adressen im eigenen Netz erlaubt. Die Zertifikatsprüfung ist standardmäßig an und lässt sich für ein selbst erstelltes Zertifikat abschalten (dann weniger sicher).
- Schlägt das Kopieren fehl, versucht das Plugin es frühestens nach einer Stunde erneut; die Admin-Adresse bekommt höchstens einmal am Tag eine E-Mail, und der Fehler steht mit Ursache auf der Seite des Plugins.
- Das Plugin läuft über den eingebauten Cron (bei Aktivität im Adminportal) oder einen echten Cronjob, der DeskHub aufruft.
Plugins entwickeln
Anmelde-Plugins (ab Server 1.0.52): Mit der Berechtigung auth.login kann ein Plugin über plugin_register_login('name', fn($req) => …) eine Adresse /staff/plugin_login.php?p=<Plugin>&e=<name> anbieten und mit dem Filter staff.login.buttons Knöpfe auf die Anmeldeseite setzen (Link bauen mit plugin_login_url($slug, $name)). Der Handler gibt ['redirect' => 'https://…'] (nur https, oder http zu localhost), ['staff_id' => 12, 'via' => 'Dienst'] oder ['error' => 'Text'] zurück; DeskHub meldet nur aktive Mitarbeiter an, schreibt ins Admin-Protokoll und begrenzt die Aufrufe. Das Plugin trägt die Verantwortung, wer sich anmelden darf; die Berechtigung wird bei der Aktivierung deutlich als Warnung angezeigt. Für Kunden gibt es die Berechtigung auth.customer: plugin_register_customer_login('name', fn() => …) bietet /plugin_login.php?p=<Plugin>&e=<name> an (Link mit plugin_customer_login_url(), Knöpfe über den Filter customer.login.buttons); der Handler gibt ['redirect' => …], ['error' => …] oder ['customer' => ['email' => …, 'name' => …, 'create' => true|false, 'via' => …]] zurück, DeskHub meldet dann das Konto mit dieser E-Mail-Adresse an und legt es bei create an (zufälliges Passwort, Sperrliste wird beachtet, Eintrag im Admin-Protokoll). Auch die Rückkehr über /staff/plugin_login.php darf ein customer-Ergebnis liefern. Mit plugin_register_login(…, …, true) laufen Adressen auch für schon angemeldete Mitarbeiter (zum Beispiel zum Verknüpfen). Beispiel: Plugins/plugins/authentik/.
Übersetzungen: Ein Plugin kann seine Texte in lang/<Sprachcode>.json (zum Beispiel lang/en.json) übersetzen, ohne dass dafür am Sprachpaket etwas geändert werden muss. Format und Wirkung stehen unter „Mehrsprachigkeit“ weiter oben; ein Beispiel liegt in Plugins/plugin-beispiel/lang/en.json. Tipp: Sammelmodus einschalten (Adminportal → Sprachen), die Plugin-Seiten durchklicken und über „Vorlage laden“ alle noch fehlenden Texte als fertige Vorlage herunterladen.
Dieser Abschnitt richtet sich an Entwickler. Ein vollständiges, lauffähiges Beispiel liegt in Plugins/plugin-beispiel/, ein praxisnahes in Plugins/plugins/tagesbericht/ (jeweils im Projektordner neben DeskHub-Webseite/).
Aufbau
Ein Plugin ist ein Ordner, der als ZIP installiert wird:
mein-plugin/
plugin.json Pflicht: Beschreibung
plugin.php Startdatei (Name über "entry" änderbar), registriert die Erweiterungen
pages/*.php Seiten, die als Menüpunkt registriert sind
migrations/ Datenbank-Änderungen (*.sql)
assets/ js, css, Bilder
Die ZIP darf die Dateien direkt im Wurzelverzeichnis oder in genau einem Unterordner enthalten. Erlaubte Dateitypen: php, json, sql, js, css, png, jpg, jpeg, gif, svg, webp, md, txt, html. Versteckte Dateien (.htaccess usw.) und Pfade mit .. werden abgelehnt. Größe: maximal 10 MB. Direkte Aufrufe von .php, .sql und .json im Plugin-Ordner sind per .htaccess gesperrt (nginx: eigene Regel nötig).
plugin.json
{
"slug": "mein-plugin",
"name": "Mein Plugin",
"version": "1.0.0",
"description": "Kurze Beschreibung",
"author": "Name",
"requires": "1.0.0",
"entry": "plugin.php",
"permissions": ["hooks.tickets", "ui.menu"]
}
| Feld | Bedeutung |
|---|---|
slug |
Pflicht. Eindeutiger Name: Kleinbuchstaben, Ziffern, _ und -, 2–41 Zeichen. Reserviert sind core, system, admin, staff, api. |
name, version |
Pflicht. Version im Format 1.0.0. |
requires |
Optional. Mindestversion von DeskHub; ist die installierte kleiner, wird die Installation abgelehnt. |
entry |
Optional. Startdatei, Standard plugin.php. |
permissions |
Optional. Liste der Erweiterungspunkte, die das Plugin nutzen will (siehe unten). Unbekannte Werte lehnt DeskHub ab. |
Berechtigungen
Ein Plugin muss die Erweiterungspunkte, die es registriert, in permissions angeben. Der Admin bestätigt die Liste bei der Aktivierung. Versucht ein Plugin einen nicht deklarierten Erweiterungspunkt zu registrieren, wird die Registrierung abgelehnt und im Plugin vermerkt (das Plugin läuft sonst weiter).
| Berechtigung | erlaubt |
|---|---|
hooks.tickets |
plugin_add_hook für ticket.*-Ereignisse und Filter mit ticket.-Präfix |
hooks.cron |
plugin_add_hook('cron.run', …) |
ui.menu |
plugin_register_menu (Menüpunkt und Seite) |
ui.sidebar |
plugin_add_filter('ticket.view.sidebar', …) |
api.endpoints |
plugin_register_api |
api.public |
plugin_register_webhook: öffentliche Adresse /api/public/v1/plugin_webhook.php?p=<slug>&e=<name> für Dienste wie Discord oder Telegram. Das Plugin prüft die Echtheit der Anfragen selbst (Signatur oder geheimes Token) und antwortet sonst mit 401. Handler: fn(array $req): array mit method, headers (Namen klein), body (roh, höchstens 256 KB), query, ip; Rückgabe ['status' => 200, 'json' => [...]] oder ['status' => 200, 'body' => '…']. |
db.migrations |
Dateien in migrations/ (werden beim Aktivieren eingespielt) |
Nicht geschützt sind plugin_setting, plugin.uninstall.<slug> und eigene Hooks zwischen Plugins. Wichtig: Das ist eine Prüfung der Erweiterungspunkte, keine Sandbox. Beliebiger PHP-Code im Plugin kann weiterhin auf Datenbank und Dateien zugreifen.
Erweiterungen registrieren
Die Startdatei wird bei jedem Seitenaufruf geladen, solange das Plugin aktiv ist. Sie sollte nur registrieren und schnell sein. Die Funktionen DeskHubs (get_db(), e(), send_mail(), has_permission() usw.) stehen zur Verfügung.
| Funktion | Zweck |
|---|---|
plugin_add_hook($hook, $fn, $priority = 10) |
Auf ein Ereignis reagieren. Rückgabewert wird ignoriert. |
plugin_add_filter($hook, $fn, $priority = 10) |
Einen Wert ergänzen oder verändern. Der Rückgabewert ersetzt den Wert, die Funktion erhält ($wert, $kontext). |
plugin_register_menu($label, $seite, $recht = null) |
Menüpunkt, der pages/<seite>.php öffnet. Optional ein Recht (z. B. 'view_reports'), das der Mitarbeiter haben muss. |
plugin_register_api($name, $fn, $recht = null) |
Eigener Endpunkt GET/POST /api/staff/v1/plugin.php?p=<slug>&endpoint=<name> mit Bearer-Token der Mitarbeiter-API. $fn($staff, $request) gibt ein Array zurück, das als JSON ausgeliefert wird. |
plugin_setting($slug, $key, $default) / plugin_set_setting($slug, $key, $wert) |
Eigene Einstellungen. Sie werden beim Entfernen des Plugins mitgelöscht. |
plugin_hook($hook, $daten) |
Eigenes Ereignis auslösen, auf das andere Plugins reagieren können. |
Ereignisse (Hooks)
| Hook | Wann | Daten |
|---|---|---|
ticket.created |
Ticket wurde erstellt (Portal, E-Mail, Chat, Mitarbeiter, API) | event, ticketId |
ticket.replied |
Antwort oder Notiz wurde geschrieben | event, ticketId, author (staff/customer), internal |
ticket.status_changed |
Status hat sich geändert | event, ticketId, previousStatus |
ticket.assigned |
Zuweisung hat sich geändert | event, ticketId |
cron.run |
Etwa alle 5 Minuten durch die Automatisierung | time |
plugin.uninstall.<slug> |
Beim Entfernen mit „Daten löschen“ | slug |
Filter: ticket.view.sidebar ergänzt einen HTML-Block in der Seitenleiste der Ticketansicht. Kontext: ticketId, ticket, staff. Das Plugin liefert fertiges HTML und muss alle Ausgaben selbst mit e() maskieren.
Ereignisse enthalten nur die ID. Weitere Daten holt das Plugin selbst aus der Datenbank.
Seiten
Eine registrierte Seite pages/log.php erscheint im normalen Mitarbeiter-Layout (Kopf, Menü, Fuß). Verfügbar sind $staff (angemeldeter Mitarbeiter) und $pdo. Es wird nur ausgeliefert, was das Plugin selbst per plugin_register_menu registriert hat. Formulare müssen csrf_field() enthalten und beim Absenden verify_csrf() aufrufen. Weiterleitungen nach dem Speichern sind nicht möglich (die Seite wird innerhalb des Layouts eingebunden), zeigt das Ergebnis also direkt auf derselben Seite an.
Datenbank
Dateien in migrations/ werden beim Aktivieren in Dateinamen-Reihenfolge einmalig ausgeführt und protokolliert. Statements trennt ein ;. Unterschiede zwischen den Datenbanken lösen Dialekt-Dateien:
001_tabelle.sqlite.sqlläuft nur auf SQLite001_tabelle.mysql.sqlläuft nur auf MySQL001_tabelle.sqlläuft auf beiden
Präfixt eure Tabellen mit dem Plugin-Namen (z. B. plugin_meinplugin_log). Zum Aufräumen beim Entfernen reagiert ihr auf plugin.uninstall.<slug> und löscht dort eure Tabellen.
Fehlerverhalten
Jeder Aufruf von Plugin-Code ist abgesichert: Ein geworfener Fehler wird protokolliert und dem Plugin zugeordnet, die aufrufende Seite läuft normal weiter. Nach 3 Fehlern seit der letzten Aktivierung wird das Plugin automatisch deaktiviert. Schwere Fehler (Fatal Error, Syntaxfehler) lassen sich nicht abfangen; DeskHub deaktiviert das gerade ausgeführte Plugin beim nächsten Seitenaufruf. Plugins sollten Fehler daher möglichst selbst behandeln und nur Unerwartetes werfen.
Mini-Beispiel
plugin.json:
{ "slug": "ticket-zaehler", "name": "Ticket-Zähler", "version": "1.0.0" }
plugin.php:
<?php
// Zählt neue Tickets und zeigt die Zahl in der Ticketansicht und auf einer eigenen Seite.
plugin_add_hook('ticket.created', function (array $e) {
$n = (int) plugin_setting('ticket-zaehler', 'anzahl', '0');
plugin_set_setting('ticket-zaehler', 'anzahl', (string) ($n + 1));
});
plugin_add_filter('ticket.view.sidebar', function (string $html, array $ctx) {
$n = (int) plugin_setting('ticket-zaehler', 'anzahl', '0');
return $html . '<div class="card" style="margin-top:16px;padding:14px 16px">Seit Plugin-Start: '
. $n . ' neue Tickets</div>';
});
plugin_register_menu('Ticket-Zähler', 'uebersicht');
pages/uebersicht.php:
<h1>Ticket-Zähler</h1>
<p><?= (int) plugin_setting('ticket-zaehler', 'anzahl', '0') ?> neue Tickets seit der Aktivierung.</p>
Paketieren und testen
- Den Plugin-Ordner als ZIP packen (die Dateien direkt im Wurzelverzeichnis oder in genau einem Unterordner).
- Als Admin unter Plugins hochladen, aktivieren, ausprobieren.
- Tritt ein Fehler auf, steht er in der Plugin-Liste. Notausschalter: leere Datei
plugins/.disabled.
Signieren und veröffentlichen
Wer Plugins oder Themes verteilt, signiert sie mit einem eigenen Schlüsselpaar (RSA, SHA-256). Das Werkzeug dafür liegt im Entwickler-Paket unter tools/plugin-sign.php (für DeskHub-Releases selbst gibt es tools/release-sign.php, siehe System-Update):
php tools/plugin-sign.php keygen ./schluessel # einmalig: privater + öffentlicher Schlüssel
php tools/plugin-sign.php sign mein-plugin.zip ./schluessel/herausgeber-privat.pem
php tools/plugin-sign.php sign-theme mein-theme.zip ./schluessel/herausgeber-privat.pem nordlicht 1.0.0
Die Ausgabe nennt SHA-256 und Signatur. Signiert wird die Nachricht deskhub-plugin, Name (bei Themes theme-<slug>), Version und SHA-256 des ZIP, getrennt durch Zeilenumbrüche, mit RSA-SHA256, Ergebnis in Base64. So lässt sich eine Signatur nicht auf eine andere Version oder ein anderes Paket übertragen. Den privaten Schlüssel nie weitergeben, den öffentlichen geben Admins in DeskHub unter Plugins ein.
Einfacher ist die Plugin- und Theme-Webseite: Sie prüft hochgeladene Pakete, signiert automatisch und stellt den Katalog bereit. Das Katalogformat für DeskHub (zum Nachbauen einer eigenen Quelle):
{ "plugins": [ {
"slug": "tagesbericht", "name": "Tagesbericht per E-Mail", "version": "1.0.0",
"description": "…", "author": "…", "requires": "1.0.0", "permissions": ["hooks.cron", "ui.menu"],
"downloadUrl": "https://plugins.example.de/download.php?type=plugin&slug=tagesbericht&version=1.0.0",
"sha256": "<SHA-256 der ZIP, 64 Hexzeichen>", "signature": "<Base64-Signatur, optional>"
} ] }
Für Themes heißt die Liste themes (ohne requires und permissions). Adressen müssen https:// verwenden und dürfen nicht auf interne Ziele zeigen.
Plugin- und Theme-Webseite
Im Projektordner plugin-webseite/ (neben DeskHub-Webseite/, nicht Teil der DeskHub-Installation auf Kunden-Servern) liegt eine fertige, eigenständige Webseite, von der DeskHub-Installationen Plugins und Themes laden. Sie läuft auf eigenem Webspace (PHP 8.1, SQLite) und braucht kein DeskHub. Sie bietet den Katalog für DeskHub und eine geschützte Verwaltung zum Veröffentlichen mit allen Versionen, Prüfsummen und Signaturstatus. Es gibt keine öffentliche Übersichtsseite. Hochgeladene Pakete werden geprüft (Dateitypen, Pfade, plugin.json, Berechtigungen) und automatisch mit eurem Schlüssel signiert. Einrichtung in zwei Minuten per php einrichten.php, Details in plugin-webseite/README.md.
Geprüfte Plugins für eure Kunden: php einrichten.php (und in der Verwaltung der Bereich „Einstellungen für DeskHub“) gibt die drei Werte aus, die in includes/catalog_defaults.php von DeskHub eingetragen werden: Katalog-Adresse für Plugins, Katalog-Adresse für Themes und euren öffentlichen Schlüssel. Tragt sie vor dem Bauen eines Releases ein. Alle Installationen mit diesem Release laden dann nur Plugins, die ihr auf der Webseite veröffentlicht, also geprüft und signiert habt. Die Datei wird bei System-Updates durch die des Releases ersetzt, Kunden können die Vorgabe also nicht versehentlich verlieren. Der Ordner plugin-webseite/ gehört nicht zur DeskHub-Installation und wird nie auf Kunden-Server kopiert.
Zugangsschutz des Katalogs: docker-build.sh / docker-build.ps1 erzeugen beim ersten Bauen einen Zugangsschlüssel (schluessel/katalog-zugangsschluessel.txt) und geben ihn am Ende aus. Tragt ihn in includes/catalog_defaults.php als access_key ein. Ohne diesen Schlüssel liefern Katalog, Downloads, Vorschaubilder und publisher-key.php nur 401. health.php bleibt offen (Docker-Healthcheck). Nach dem Bauen: Image auf dem Server austauschen und ein DeskHub-Release mit dem eingetragenen Schlüssel veröffentlichen.
Vorschaubilder: Das Bild eines Plugins oder Themes ist nur beim ersten Veröffentlichen nötig (oder liegt als vorschau.png im ZIP). Es bleibt bei neuen Versionen erhalten, auch wenn die alte Version vorher entfernt wurde, und lässt sich in der Verwaltung beim Eintrag ersetzen oder entfernen.
Verwaltung (admin.php): Geordnet in Reiter: Übersicht (Zahlen, Systemstatus, Warnung bei fehlendem Zugangsschlüssel), Pakete (Plugins links, Themes rechts), Apps (Windows, Android, Minecraft, WordPress-Plugin und Chrome-Erweiterung mit der aktuellen Version), Push-Dienst und Einstellungen (Werte für DeskHub, Abmelden). Die Seite hat ein Favicon, passt sich hell und dunkel an und funktioniert auf dem Handy.
Apps, Plugins und Erweiterungen veröffentlichen: Unter „Apps“ Plattform wählen (Windows-EXE, Android-APK, Minecraft-Plugin-JAR, WordPress-Plugin-ZIP, Chrome-Erweiterung-ZIP), Versionsnummer eintragen (zum Beispiel 3.4.4; bei den beiden ZIPs darf das Feld leer bleiben, die Nummer steht dann im Plugin-Kopf bzw. in der manifest.json), Datei hochladen, optional „Änderungen“ (erscheinen im Update-Hinweis der Apps). Die höchste Version gilt als aktuell. DeskHub bezieht sie über den geschützten Endpunkt app-release.php und zeigt sie auf der Seite „Apps“ an; die Apps zeigen daraus ihren Update-Hinweis.
Upload-Grenzen: Das Docker-Image erlaubt Uploads bis 310 MB (PHP) bzw. 320 MB (Caddy). Steht davor ein eigener Proxy, muss er es ebenfalls erlauben (nginx: client_max_body_size 320m;). Cloudflare im Gratis-Tarif lässt höchstens 100 MB je Upload zu. Ist eine Datei zu groß, meldet die Seite das mit den aktuellen Grenzen und meldet nicht mehr ab.
API und Webhooks (für Entwickler)
Dieser Abschnitt beschreibt die Schnittstellen für Fremdsysteme. Einrichten (Schlüssel erzeugen, Webhooks eintragen) tun Admins im Adminportal, siehe Integrationen. Alle Beispiele nutzen https://support.example.de als Adresse eurer Installation.
Ticket-API
Basis-Adresse: https://support.example.de/api/public/v1/tickets.php
Authentifizierung: Jeder Aufruf braucht einen API-Schlüssel (Format dh_ plus 48 Hexzeichen), entweder im Header X-API-Key: dh_… oder als Authorization: Bearer dh_…. Der Schlüssel wird im Adminportal unter API-Schlüssel erzeugt und nur einmal angezeigt. Er hat die Rechte „Tickets anlegen“ und/oder „Tickets lesen“ und kann auf IP-Adressen beschränkt sein. Aufrufe von nicht erlaubten Adressen werden wie ein falscher Schlüssel behandelt (401). Verwendet die API nur über HTTPS und nur in serverseitigem Code, nie im Browser eurer Besucher.
Hat der Schlüssel eine IP-Beschränkung („Erlaubte IPs“) und kommt der Aufruf von einer anderen Adresse, antwortet die API mit 401 und dem Code IP_NOT_ALLOWED; die Meldung nennt die Adresse, die DeskHub sieht (hinter Proxy oder Cloudflare oft nicht die erwartete). Ein falscher, unbekannter oder abgeschalteter Schlüssel liefert weiter nur UNAUTHENTICATED.
Anfragen und Antworten sind JSON (UTF-8). Fehler haben immer diese Form:
{ "error": { "code": "INVALID_EMAIL", "message": "Bitte eine gültige E-Mail-Adresse angeben." } }
Ticket anlegen
POST /api/public/v1/tickets.php, Recht „Tickets anlegen“, Header Content-Type: application/json.
| Feld | Pflicht | Beschreibung |
|---|---|---|
name |
ja | Name des Anfragenden, höchstens 120 Zeichen |
email |
ja | Gültige E-Mail-Adresse des Anfragenden (hierhin gehen die Antworten) |
subject |
ja | Betreff, höchstens 255 Zeichen |
message |
ja | Nachricht, höchstens 50.000 Zeichen |
helpTopicId |
nein | ID eines aktiven Hilfethemas; legt Abteilung und Priorität fest, sofern nicht selbst angegeben |
departmentId |
nein | ID der Abteilung |
priorityId |
nein | ID der Priorität |
| fields | nein | Die Angaben zum Kundenformular: { "<Feld-ID>": "Wert", … }. Nur mit fields prüft DeskHub die Felder des Formulars (Pflichtfelder, Auswahlwerte, Zahl, Datum) und speichert die Werte im Ticket; ohne fields bleibt alles wie bisher. Hat die Abteilung ein eigenes Formular ohne Betreff oder Beschreibung, dürfen subject und message entfallen (Betreff „Anfrage “, Text aus den Feldern). Fehler heißen INVALID_FIELD, die Meldung ist für Besucher gedacht. |
Die IDs seht ihr im Adminportal in der Adresszeile beim Bearbeiten (…?edit=<ID>). Ohne Angaben gelten die Standardabteilung und die erste Priorität der Prioritätenliste. Ticket-Regeln, SLA-Pläne und Benachrichtigungen laufen wie bei jedem anderen Ticket. Der Kunde bekommt die übliche Bestätigungs-E-Mail. Das Ticket hat die Quelle api.
curl -X POST https://support.example.de/api/public/v1/tickets.php \
-H "X-API-Key: dh_0123456789abcdef0123456789abcdef0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{"name":"Erika Muster","email":"erika@example.de","subject":"Rechnung fehlt","message":"Bitte Rechnung 4711 erneut senden.","helpTopicId":3}'
Antwort 201 Created:
{ "number": "T-1042", "status": "open" }
Hilfethemen und Kundenformular abfragen
Website-Formulare (zum Beispiel das WordPress-Plugin) holen sich damit dasselbe Formular, das Kunden im Kundenportal sehen. Recht „Tickets anlegen“.
GET /api/public/v1/tickets.php?topics=1liefert die öffentlichen, aktiven Hilfethemen:{ "topics": [{ "id", "name", "path", "depth", "parentId", "departmentId" }] }.GET /api/public/v1/tickets.php?form=1&helpTopicId=3(oderdepartmentId=2) liefert das Formular des Hilfethemas:{ "form": { "title", "intro", "ownForm", "subject": { "show", "label" }, "message": { "show", "label", "hint" }, "submitLabel", "fields": [{ "id", "label", "type", "required", "options", "helpHtml", "width", "section", "radioInline" }] } }. Hat die Abteilung ein eigenes Formular, gelten dessen Texte und Felder, sonst die allgemeinen Felder und die des Hilfethemas. Feldtypen:text,textarea,select,radio,checkbox,number,date.helpHtmlist sicheres HTML (Links mit absoluter Adresse).
Ticketstatus abfragen
GET /api/public/v1/tickets.php?number=T-1042&email=erika@example.de, Recht „Tickets lesen“.
Beide Parameter sind Pflicht. Die E-Mail-Adresse muss zum Ticket passen, sonst antwortet die API mit 404 (so erfährt niemand etwas über fremde Tickets). Interne Notizen werden nie ausgegeben.
{
"ticket": {
"number": "T-1042",
"subject": "Rechnung fehlt",
"status": "answered",
"createdAt": "2026-10-15 09:12:03",
"updatedAt": "2026-10-15 10:40:51",
"messages": [
{ "author": "customer", "message": "Bitte Rechnung 4711 erneut senden.", "createdAt": "2026-10-15 09:12:03" },
{ "author": "staff", "message": "Die Rechnung ist unterwegs.", "createdAt": "2026-10-15 10:40:51" }
]
}
}
status ist einer von open, pending, answered, on_hold, resolved, closed. Zeiten sind Serverzeit im Format JJJJ-MM-TT hh:mm:ss. author ist customer oder staff.
Fehler und Grenzen
| HTTP | code |
Bedeutung |
|---|---|---|
| 400 | INVALID_JSON |
Der Anfragekörper ist kein gültiges JSON |
| 401 | UNAUTHENTICATED |
Schlüssel fehlt, ist falsch, deaktiviert oder von dieser IP nicht erlaubt |
| 403 | FORBIDDEN |
Dem Schlüssel fehlt das Recht für diese Aktion |
| 403 | BANNED, REJECTED |
Absender ist gesperrt oder eine Ticket-Regel hat das Ticket abgelehnt |
| 404 | NOT_FOUND |
Ticket nicht gefunden (oder falsche E-Mail-Adresse) |
| 405 | METHOD_NOT_ALLOWED |
Erlaubt sind nur GET und POST |
| 413 | TOO_LARGE |
Anfrage größer als 200 KB |
| 422 | INVALID_NAME, INVALID_EMAIL, INVALID_SUBJECT, INVALID_MESSAGE, INVALID_TOPIC, INVALID_PRIORITY, MISSING_PARAMS |
Eingaben ungültig oder unvollständig |
| 429 | RATE_LIMITED |
Mehr als 60 über die API angelegte Tickets pro Minute (gilt gemeinsam für alle Schlüssel) |
| 503 | NO_DEPARTMENT |
Es ist keine aktive Abteilung eingerichtet |
Beim Anlegen gibt es keine Wiederholungssicherung: Sendet ihr dieselbe Anfrage zweimal, entstehen zwei Tickets. Wiederholt nach einem Netzwerkfehler also nur, wenn ihr prüfen könnt, ob das erste Ticket angekommen ist.
Webhooks
Mit Webhooks meldet DeskHub Ereignisse sofort an eine Adresse eures Systems. Einrichten: Adminportal → Webhooks → Name, URL und die gewünschten Ereignisse wählen. Das Secret zum Prüfen der Signatur legt ihr selbst fest oder lasst es von DeskHub erzeugen. Es wird nur verschlüsselt gespeichert.
Ereignisse:
| Ereignis | Wann | Zusätzliche Felder |
|---|---|---|
ticket.created |
Neues Ticket (Portal, E-Mail, Chat, Mitarbeiter oder API) | – |
ticket.replied |
Antwort oder interne Notiz | author (staff oder customer); bei Mitarbeitern zusätzlich internal (true bei interner Notiz) |
ticket.status_changed |
Status hat sich geändert | previousStatus |
ticket.assigned |
Zuweisung hat sich geändert | – |
Anfrage: DeskHub sendet POST mit JSON (UTF-8) an eure URL, mit diesen Headern:
| Header | Inhalt |
|---|---|
Content-Type |
application/json |
User-Agent |
DeskHub-Webhook/1 |
X-DeskHub-Event |
Ereignisname, z. B. ticket.created |
X-DeskHub-Signature |
sha256= plus HMAC-SHA256 des rohen Anfragekörpers mit eurem Secret als Schlüssel (Hex) |
Beispiel für den Anfragekörper (ticket.status_changed):
{
"event": "ticket.status_changed",
"occurredAt": "2026-10-15T08:41:12+00:00",
"ticket": {
"number": "T-1042",
"subject": "Rechnung fehlt",
"status": "resolved",
"source": "web",
"priority": "Normal",
"department": "Buchhaltung",
"assignedTo": "Max Muster",
"requesterName": "Erika Muster",
"requesterEmail": "erika@example.de",
"createdAt": "2026-10-15 09:12:03",
"updatedAt": "2026-10-15 10:40:51"
},
"previousStatus": "answered"
}
occurredAt ist UTC im ISO-8601-Format, assignedTo ist null, wenn niemand zugewiesen ist. Es werden nur diese Angaben gesendet, nicht der Nachrichtentext.
Signatur prüfen (immer mit dem rohen Körper, vor dem JSON-Parsen, und mit einem zeitkonstanten Vergleich):
$body = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_DESKHUB_SIGNATURE'] ?? '')) {
http_response_code(401);
exit;
}
import hmac, hashlib
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, request.headers.get("X-DeskHub-Signature", ""))
Zustellung:
- Eure Adresse muss binnen 5 Sekunden mit einem Status
2xxantworten. Alles andere (anderer Status, Timeout, Verbindungsfehler) zählt als Fehler. Weiterleitungen werden nicht verfolgt. - Es gibt keine automatische Wiederholung. Antwortet euer System gerade nicht, geht dieses Ereignis verloren. Baut bei kritischen Abläufen einen Abgleich ein, etwa über die Ticket-API oder den Status in der Webhook-Liste.
- Die Zustellung läuft nach der Antwort an den Benutzer und bremst DeskHub nicht. Die Reihenfolge mehrerer Ereignisse ist nicht garantiert;
occurredAtundupdatedAthelfen beim Einordnen. - Nach 10 Fehlern in Folge wird der Webhook automatisch deaktiviert. Im Adminportal stehen letzter Status, Fehlertext und Zeitpunkt. Ein erfolgreicher Aufruf setzt den Fehlerzähler zurück. Nach dem Beheben aktiviert ihr den Webhook wieder.
- Erlaubt sind nur
http://undhttps://, und die Adresse darf nicht auf interne Ziele zeigen (localhost, private Netze). Nutzthttps://. - Das Webhook-Secret ist von den API-Schlüsseln unabhängig.
Sicherheit und Datenschutz
- Sperrliste: Einzelne E-Mail-Adressen oder ganze Domains blockieren. Mails von dort erzeugen kein Ticket mehr.
- Automatische Anonymisierung: Unter Einstellungen → Datenschutz legt ihr fest, nach wie vielen Monaten persönliche Daten (Name, E-Mail) in geschlossenen Tickets anonymisiert werden. Der Ticketinhalt bleibt für Statistiken erhalten.
- Automatische Abmeldung: Die Zeit bis zur Abmeldung bei Inaktivität ist einstellbar.
- Passwörter und Zugangsdaten: SMTP-/IMAP-Passwörter und Tokens werden verschlüsselt gespeichert. API-Schlüssel werden nur als Prüfsumme abgelegt und sind nach dem Erstellen nicht mehr einsehbar.
- Updates und Plugins: Updates werden über eine geprüfte, verschlüsselte Verbindung geladen. Plugins sind Programmcode mit vollen Rechten, installiert deshalb nur vertrauenswürdige.
- Sicherheitsprüfung: Adminportal → Sicherheitsprüfung prüft die Einrichtung dieser Installation und ruft interne Adressen selbst ab, um zu sehen, ob Konfiguration, Datenbank, Backups oder Programmcode von außen erreichbar wären. Nach der Installation und nach jeder Änderung am Webserver einmal ausführen.
- Schutz vor HTML-Angriffen: Texte in Antworten und HTML-E-Mails werden vor der Anzeige durch einen strengen Filter geschickt. Skripte, Formulare, eingebettete Inhalte und riskante Formatierungen werden entfernt; auch kaputtes oder absichtlich verstümmeltes HTML wird als Text maskiert.
- Abteilungsgrenzen: Mitarbeiter sehen Tickets, Anhänge, Ausdrucke und Kundenprofile nur für ihre Abteilungen, auch über direkte Links.
Betrieb absichern (Checkliste)
-
HTTPS einrichten und die Website-URL (Einstellungen) auf
https://stellen. -
Interne Ordner sperren. Die mitgelieferte
.htaccesserledigt das auf Apache. Auf nginx und anderen Servern gibt es keine.htaccess: Tragt diese Regeln in denserver-Block ein (Pfad zu PHP-FPM anpassen):# Interne Ordner und Dateien nie ausliefern location ~ ^/(config|database|includes|cron|backups|tests|tools|docs|app_downloads|\.git|\.gitea|\.github)(/|$) { return 404; } location ~ ^/plugins/.+\.(php|sql|json|md|txt|log)$ { return 404; } location ~ ^/(version\.php|offen\.txt|install\.sh|install_windows\.bat)$ { return 404; } location ~* \.(sqlite3?|db|sql|log|bak|old|md|sh|bat|ps1|pem|key|env|ini|lock)$ { return 404; } # Hochgeladene Dateien dürfen nie als Programm laufen location ~* ^/uploads/.*\.(php\d?|phtml|phar|html?|xhtml|svgz?|xml|js)$ { return 403; } # Nach der Installation: Installationsassistent sperren location ^~ /install/ { return 404; } # In den PHP-Block (location ~ \.php$): Anmelde-Header der Apps an PHP weiterreichen # fastcgi_param HTTP_AUTHORIZATION $http_authorization;Diese Regeln müssen vor dem
location ~ \.php$-Block stehen, weil nginx den ersten passenden Regex-Block nimmt. Danach in der Sicherheitsprüfung kontrollieren, dass alles gesperrt ist. -
Reverse-Proxy (nginx, Traefik, Caddy, Cloudflare …): Tragt in
config/config.phpuntersitedie Adresse oder den Bereich des Proxys ein, damit DeskHub die echte Besucher-IP und HTTPS erkennt. Der Proxy mussX-Forwarded-ForundX-Forwarded-Protosetzen. Ohne diese Angabe sehen alle Besucher aus Sicht von DeskHub wie eine einzige IP aus, und die Anmelde-Sperre trifft alle gleichzeitig:'site' => [ // ... 'trusted_proxies' => ['127.0.0.1', '172.16.0.0/12'], ],Tragt nur Proxys ein, die ihr selbst betreibt. Wer in dieser Liste steht, kann die IP-Adresse der Besucher festlegen.
-
app_keyinconfig/config.phpsetzen (der Installer tut das) und nie ändern. Die Datei nach der Installation auf nur lesbar stellen (chmod 640). -
Ordner
install/löschen, PHP-Fehleranzeige abschalten (display_errors = Off), Zwei-Faktor-Anmeldung für alle Administratoren aktivieren (Profil → Sicherheit). -
Backups einrichten und prüfen (siehe Backup), den Ordner
backups/nie öffentlich machen. -
Eigenes Repository:
config/config.php, die Datenbank, Backups und Uploads gehören nie in ein Git-Repository. Die mitgelieferte.gitignoreschließt sie aus. War eineconfig/config.phpschon eingecheckt, entfernt sie aus dem Repository (git rm --cached config/config.php): Sonst landet eine fremde Konfiguration auf dem Server, und DeskHub arbeitet mit alten Daten statt mit denen aus dem Installer. Der Installer ersetzt eine vorhandene alteconfig.phpzwar, prüft die geschriebene Datei und meldet, wenn PHP noch eine ältere Version aus dem Zwischenspeicher liefert, besser ist aber, sie gar nicht erst auszuliefern. -
Updates installieren: Sicherheitsverbesserungen kommen mit neuen Versionen.
Backup
Adminportal → Backup:
- Manuell: Jederzeit ein Backup erstellen und herunterladen.
- Automatisch: Zeitplan (täglich, wöchentlich, monatlich), optional mit Upload per FTP auf einen zweiten Server und automatischer Rotation (alte Backups werden nach einer einstellbaren Anzahl gelöscht).
Außerdem erstellt DeskHub automatisch ein Backup vor jedem System-Update, jedem Datenbank-Update und jeder Plugin-Aktivierung.
Was im Backup steckt (und was nicht):
- Enthalten sind die Datenbank und alle Dateien der Installation. Nicht enthalten ist der Ordner
backups/mit den bisherigen Backups: Sonst enthielte jedes neue Backup alle älteren noch einmal und würde mit jedem Mal größer. Nur die.htaccessdieses Ordners kommt mit, damit er nach einer Wiederherstellung wieder geschützt ist. Das gilt für alle Wege (Seite „Backup“, Zeitplan, Updates, NAS-Plugin). - Bereits komprimierte Dateien (ZIP, Bilder, PDF, EXE, APK, JAR) werden nur abgelegt statt erneut gepackt. Das spart bei vielen Anhängen viel Rechenzeit.
- Der Ordner
app_downloads/gehört dazu. Seit die Apps über die Plugin-Webseite kommen, kann er leer bleiben; liegen dort große Dateien, dauert das Backup entsprechend länger.
Nur ein Backup gleichzeitig: Cronjob, eingebauter Hintergrunddienst, der Knopf „Backup erstellen“ und das NAS-Plugin teilen sich eine Sperre. Läuft schon eines, überspringen die anderen ihren Lauf; der Knopf meldet „Es läuft bereits ein Backup“. Eine Sperre, die nach 3 Stunden noch steht (abgestürzter Lauf), gilt als frei. Ohne diese Sperre konnten sich zwei Läufe überlappen, weil „letztes Backup“ erst nach dem Erstellen eingetragen wird.
Lange Backups hinter Cloudflare: Cloudflare beendet eine Anfrage nach 100 Sekunden mit der Fehlerseite „524“. Ein manuelles Backup läuft auf dem Server trotzdem zu Ende. Prüft dann die Liste, statt noch einmal zu klicken. Zuverlässiger sind der Zeitplan mit echtem Cronjob oder das Backup in kleineren Teilen (nur wichtige Dateien).
Prüfen und Wiederherstellen:
- Automatische Prüfung: Jedes neue Backup wird sofort nach dem Erstellen geprüft (manuell, per Zeitplan, vor Updates, vor Plugin-Aktivierungen). Noch nie geprüfte Backups und solche, deren letzte Prüfung über 7 Tage her ist, werden im Hintergrund nachgeprüft, damit auch spätere Beschädigungen auffallen. Das Ergebnis steht bei jeder Sicherung in der Liste („✔ geprüft“ / „✖ defekt“). Ein defektes Backup meldet DeskHub zusätzlich per E-Mail an die Admin-Adresse. Von Hand prüfen musst du nichts; „Prüfen“ gibt es weiter für den Fall, dass du sofort nachsehen willst.
- Jedes Backup enthält einen konsistenten Datenbank-Schnappschuss (SQLite) bzw. einen SQL-Dump (MySQL) und eine Inhaltsliste mit Prüfsummen.
- ✔️ Prüfen kontrolliert ein Backup, ohne etwas zu verändern. Nach jedem manuellen und automatischen Backup passiert das von selbst; schlägt es fehl, erscheint im Adminportal eine Störungsmeldung („Backup defekt“).
- ♻️ Wiederherstellen spielt Datenbank und (wählbar) Uploads, Plugins und App-Downloads zurück. Davor wird automatisch ein Sicherheits-Backup des aktuellen Stands erstellt. Zur Bestätigung gebt ihr
WIEDERHERSTELLENein. Programmcode undconfig.phpwerden nie überschrieben. Ein Backup einer anderen Datenbankart (SQLite ↔ MySQL) wird abgelehnt.
Automatische Tests (CI)
Im Ordner DeskHub-Webseite/ führt php tests/run_all.php alle PHP-Tests nacheinander aus (Exit-Code 1 bei Fehlern); mit Argument nur passende Tests, z. B. php tests/run_all.php plugin. Die Tests für Plugin-Webseite und Plugin-Quellen suchen ihre Ordner neben DeskHub-Webseite/ (plugin-webseite/, Plugins/); abweichende Orte lassen sich mit DESKHUB_WEBSITE_DIR und DESKHUB_PLUGIN_SRC angeben, fehlt ein Ordner, werden diese Tests übersprungen. Die Workflow-Datei .gitea/workflows/tests.yml im Projektordner startet bei jedem Push, jeder Pull-Request und nachts um 03:17 UTC: PHP 8.2 (Syntax und alle Tests), PHP 8.4 (nur Warnung), Windows-App-Oberflächentests (npm test unter xvfb), Android-Tests (./gradlew testDebugUnitTest) und der Bau des Docker-Images der Plugin-Webseite samt Zugangsschutz-Prüfung. Für GitHub die Datei nach .github/workflows/ kopieren (die Pfade im Workflow gelten für diese Ordnerstruktur). Der Runner braucht für den Docker-Job Docker, für den Android-Job das Android-SDK.
Demo-Video neu erzeugen
Video und Bilder mit Beispieldaten entstehen aus einer eigenen Demo-Installation (SQLite, alles erfunden, keine Kundendaten). Nötig sind PHP 8.2, Node mit Electron (liegt in desktop/node_modules) und ffmpeg. Alle Befehle im Ordner DeskHub-Webseite:
php tools/demo-video/seed_demo.php /pfad/zur/demo # Demo-Installation mit Beispieldaten anlegen
php -S 127.0.0.1:8097 -t /pfad/zur/demo & # Demo starten (Zugang: lena@demo.example / Demo-Passwort-1234)
../desktop/node_modules/.bin/electron tools/demo-video/record.js /pfad/raw.mp4 # Bewegte Aufnahme (Browser und Windows-Programm), dauert etwa 4 Minuten (Video: knapp 4 Minuten)
bash tools/demo-video/compose.sh /pfad/raw.mp4 docs/video # Full-HD-Video mit Hintergrund, Rahmen und Musik, dazu GIF-Vorschau
Die Szenen, Texte und Wartezeiten stehen in record.js, das Aussehen (Hintergrund, Fenster, Schatten, Musiklautstärke) in compose.sh, die Musik in make_music.js. Die Standbilder im Abschnitt „Einblicke“ entstehen mit capture.js (Browser) und capture_app.js (Windows-Programm): electron tools/demo-video/capture.js <Bilderordner>.
Hilfe, etwas funktioniert nicht
- Admin-Protokoll (Adminportal → Admin-Protokoll): Änderungen und fehlgeschlagene automatische E-Mails mit genauer Fehlermeldung.
- E-Mail-Abruf: Adminportal → Postfächer (Abruf) → beim betroffenen Postfach „Testen“. Das zeigt die Fehlermeldung des Mail-Servers.
- E-Mail-Versand: Einstellungen → E-Mail → „Test-Mail senden“, oder bei E-Mail-Adressen die einzelne Adresse testen.
- Rotes oder gelbes Banner oben: Das ist eine Störungsmeldung der Überwachung, siehe Überwachung und Störungsmeldungen.
- „Datenbank veraltet“: Unter System-Update auf „Datenbank aktualisieren“ klicken.
- Ein Plugin macht Probleme: Unter Plugins deaktivieren. Lässt sich die Seite nicht mehr öffnen, hilft die Datei
plugins/.disabled. - Die App meldet „Ein gültiges Bearer-Token ist erforderlich“: Der Webserver reicht den Anmelde-Header der App nicht an PHP weiter (typisch bei Apache mit PHP-FPM/FastCGI, z. B. Plesk). Anmelden funktioniert noch, jede weitere Anfrage scheitert. Die mitgelieferte
.htaccessenthält die nötigen Regeln (neue Dateien hochladen). Auf nginx gehört in den PHP-Blockfastcgi_param HTTP_AUTHORIZATION $http_authorization;. Zusätzlich senden die Apps (ab dieser Version) den Wert alsX-DeskHub-Authorization, der auf jedem Hoster ankommt. Prüfen lässt sich das mit einem Unsinns-Token: Antwortet/api/staff/v1/dashboard.phpmit „Die Anmeldung ist abgelaufen“, kommt der Header an; antwortet sie mit „Ein gültiges Bearer-Token ist erforderlich“, nicht. - Die App zeigt „Keine Verbindung“: Erreichbarkeit der Seite im Browser prüfen. Sobald der Server wieder antwortet, verschwindet das Banner von selbst.









