diff --git a/app/Livewire/Help/Index.php b/app/Livewire/Help/Index.php
new file mode 100644
index 0000000..04ae037
--- /dev/null
+++ b/app/Livewire/Help/Index.php
@@ -0,0 +1,55 @@
+.blade.php.
+ */
+#[Layout('layouts.app')]
+class Index extends Component
+{
+ /** Help topics in display order. */
+ private const TOPICS = [
+ 'overview', 'domain-tls', 'security', 'updates',
+ 'servers', 'sessions', 'email', 'audit', 'recovery',
+ ];
+
+ public string $topic = 'overview';
+
+ public function mount(?string $topic = null): void
+ {
+ if ($topic !== null) {
+ $this->topic = $topic; // clamped to a known topic in render()
+ }
+ }
+
+ public function render()
+ {
+ // Authoritative guard: any unknown topic (deep link, tampered property) → overview, so
+ // the view never @includes a missing content partial.
+ if (! in_array($this->topic, self::TOPICS, true)) {
+ $this->topic = 'overview';
+ }
+
+ $labels = [
+ 'overview' => __('help.topic_overview'),
+ 'domain-tls' => __('help.topic_domain_tls'),
+ 'security' => __('help.topic_security'),
+ 'updates' => __('help.topic_updates'),
+ 'servers' => __('help.topic_servers'),
+ 'sessions' => __('help.topic_sessions'),
+ 'email' => __('help.topic_email'),
+ 'audit' => __('help.topic_audit'),
+ 'recovery' => __('help.topic_recovery'),
+ ];
+
+ $topics = array_map(fn (string $key): array => ['key' => $key, 'label' => $labels[$key]], self::TOPICS);
+
+ return view('livewire.help.index', ['topics' => $topics])->title(__('help.title'));
+ }
+}
diff --git a/lang/de/help.php b/lang/de/help.php
new file mode 100644
index 0000000..e0c7ba2
--- /dev/null
+++ b/lang/de/help.php
@@ -0,0 +1,18 @@
+ 'Hilfe — Clusev',
+ 'eyebrow' => 'Hilfe',
+ 'heading' => 'Hilfe & Dokumentation',
+ 'subtitle' => 'Einstellungen und Abläufe erklärt.',
+
+ 'topic_overview' => 'Überblick',
+ 'topic_domain_tls' => 'Domain, TLS & Reverse-Proxy',
+ 'topic_security' => 'Sicherheit & 2FA',
+ 'topic_updates' => 'Updates & Versionen',
+ 'topic_servers' => 'Server & SSH',
+ 'topic_sessions' => 'Sitzungen & Benutzer',
+ 'topic_email' => 'E-Mail (SMTP)',
+ 'topic_audit' => 'Audit-Log',
+ 'topic_recovery' => 'Konto-Wiederherstellung',
+];
diff --git a/lang/de/shell.php b/lang/de/shell.php
index 5f32f0f..f32255d 100644
--- a/lang/de/shell.php
+++ b/lang/de/shell.php
@@ -21,6 +21,7 @@ return [
'nav_settings' => 'Einstellungen',
'nav_system' => 'System',
'nav_versions' => 'Version',
+ 'nav_help' => 'Hilfe',
// Sidebar — user / 2FA badge
'twofa_on' => '2FA aktiv',
diff --git a/lang/en/help.php b/lang/en/help.php
new file mode 100644
index 0000000..2616940
--- /dev/null
+++ b/lang/en/help.php
@@ -0,0 +1,18 @@
+ 'Help — Clusev',
+ 'eyebrow' => 'Help',
+ 'heading' => 'Help & documentation',
+ 'subtitle' => 'Settings and procedures explained.',
+
+ 'topic_overview' => 'Overview',
+ 'topic_domain_tls' => 'Domain, TLS & reverse proxy',
+ 'topic_security' => 'Security & 2FA',
+ 'topic_updates' => 'Updates & versions',
+ 'topic_servers' => 'Servers & SSH',
+ 'topic_sessions' => 'Sessions & users',
+ 'topic_email' => 'Email (SMTP)',
+ 'topic_audit' => 'Audit log',
+ 'topic_recovery' => 'Account recovery',
+];
diff --git a/lang/en/shell.php b/lang/en/shell.php
index 02f33ad..7855de9 100644
--- a/lang/en/shell.php
+++ b/lang/en/shell.php
@@ -21,6 +21,7 @@ return [
'nav_settings' => 'Settings',
'nav_system' => 'System',
'nav_versions' => 'Version',
+ 'nav_help' => 'Help',
// Sidebar — user / 2FA badge
'twofa_on' => '2FA on',
diff --git a/resources/js/app.js b/resources/js/app.js
index 3b7ad81..1a4f8ce 100644
--- a/resources/js/app.js
+++ b/resources/js/app.js
@@ -253,7 +253,7 @@ document.addEventListener('alpine:init', () => {
// translated via __()), so the palette stays in sync with the active locale.
// CMDK_GO maps leader-key mnemonics to routes (i=dIenste, l=Log,
// e=Einstellungen, y=sYstem — d/s already taken) and stays in JS.
- const CMDK_GO = { d: '/', s: '/servers', i: '/services', f: '/files', l: '/audit', e: '/settings', y: '/system', v: '/versions' };
+ const CMDK_GO = { d: '/', s: '/servers', i: '/services', f: '/files', l: '/audit', e: '/settings', y: '/system', v: '/versions', h: '/help' };
window.Alpine.data('cmdk', (nav = [], actions = [], servers = [], failMsg = '') => ({
nav,
diff --git a/resources/views/components/command-palette.blade.php b/resources/views/components/command-palette.blade.php
index b54f511..6185b51 100644
--- a/resources/views/components/command-palette.blade.php
+++ b/resources/views/components/command-palette.blade.php
@@ -16,6 +16,7 @@
['g e', __('shell.nav_settings')],
['g y', __('shell.nav_system')],
['g v', __('shell.nav_versions')],
+ ['g h', __('shell.nav_help')],
];
$nav = [
@@ -27,6 +28,7 @@
['label' => __('shell.nav_settings'), 'href' => '/settings', 'hint' => 'g e'],
['label' => __('shell.nav_system'), 'href' => '/system', 'hint' => 'g y'],
['label' => __('shell.nav_versions'), 'href' => '/versions', 'hint' => 'g v'],
+ ['label' => __('shell.nav_help'), 'href' => '/help', 'hint' => 'g h'],
];
$actions = [
diff --git a/resources/views/components/icon.blade.php b/resources/views/components/icon.blade.php
index 2bb8c17..32038a6 100644
--- a/resources/views/components/icon.blade.php
+++ b/resources/views/components/icon.blade.php
@@ -5,6 +5,7 @@
'menu' => '
Clusev ist ein selbst-gehostetes Control-Panel, um eine Flotte von Linux-Servern aus einem + Dashboard zu verwalten — agentenlos über SSH. Es installiert nichts auf den Zielservern, sondern steuert sie + direkt (Befehle + Dateien über SSH). Die ganze Oberfläche ist sicherheitsorientiert: 2FA, verschlüsselter + SSH-Zugangsdaten-Tresor und ein vollständiges Audit-Log.
+Nach der Installation meldest du dich mit der Admin-E-Mail und dem Standard-Passwort
+ clusev an (die Standard-E-Mail ist admin@clusev.local,
+ sofern beim Installieren keine andere gesetzt wurde). Das Panel erzwingt sofort einen
+ Passwortwechsel — `clusev` ist ein bekanntes Standard-Passwort und nur bis zur Änderung gültig. Ändere es
+ gleich beim ersten Login.
http://<Server-IP> per Klartext-HTTP. Diese Adresse bleibt immer als
+ Wiederherstellungsweg erreichbar, auch wenn später eine Domain eingerichtet wird.Tipp: Strg/⌘ K öffnet die Befehls-Suche; mit g + Buchstabe springst du direkt (z. B. g h = Hilfe).
Clusev is a self-hosted control panel for managing a fleet of Linux servers from one dashboard — + agentless, over SSH. It installs nothing on the target servers; it drives them directly (commands + files over + SSH). The whole interface is security-first: 2FA, an encrypted SSH-credential vault and a complete audit log.
+After installation, sign in with the admin e-mail and the default password
+ clusev (the default e-mail is admin@clusev.local
+ unless another was set at install time). The panel forces a password change immediately —
+ `clusev` is a known default and only valid until you change it. Change it right away on first login.
http://<server-ip> over plain HTTP. This address always stays reachable
+ as a recovery path, even after a domain is configured.Tip: Ctrl/⌘ K opens the command search; g + a letter jumps directly (e.g. g h = Help).
{{ __('help.eyebrow') }}
+{{ __('help.subtitle') }}
+