feat(install): fixed default admin e-mail admin@clusev.local
Default the first-admin login e-mail to a predictable admin@clusev.local when no --email / CLUSEV_ADMIN_EMAIL is given, instead of a host-derived admin@<host> address the operator would have to guess. Combined with the default password 'clusev' (forced change on first login), a fresh install now has a fully predictable initial login. Override at install time or change it later under Settings -> Profile. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>feat/v1-foundation
parent
9215a5b908
commit
b1fb0e766a
16
README.md
16
README.md
|
|
@ -44,8 +44,9 @@ The installer is idempotent (safe to re-run) and, in one pass:
|
|||
1. Installs **Docker** (Debian/Ubuntu, from Docker's official repository) if it isn't already present.
|
||||
2. Creates a dedicated **`clusev`** system user — in the `docker` group, owning and running the stack —
|
||||
with a random password.
|
||||
3. Asks for a **domain** (leave empty for IP access) and an **admin e-mail**, or reads `CLUSEV_DOMAIN`
|
||||
/ `CLUSEV_ADMIN_EMAIL` from the environment for an unattended install. If you give a domain it
|
||||
3. Asks for a **domain** (leave empty for IP access) and an **admin e-mail** (leave empty for the
|
||||
default **`admin@clusev.local`**), or reads `CLUSEV_DOMAIN` / `CLUSEV_ADMIN_EMAIL` from the
|
||||
environment for an unattended install. If you give a domain it
|
||||
checks whether DNS already points here: if so a certificate is obtained automatically; if not, it
|
||||
warns you and lets you take the domain anyway (HTTP until DNS is correct) or continue on the IP.
|
||||
4. Generates all secrets (once — never regenerated on re-run), builds the image, starts the stack,
|
||||
|
|
@ -54,12 +55,13 @@ The installer is idempotent (safe to re-run) and, in one pass:
|
|||
5. Installs a themed host login banner (MOTD) showing the dashboard address and live stack status.
|
||||
|
||||
When it finishes, the terminal prints a single summary: the **dashboard URL**, the **admin login**
|
||||
(your e-mail + the default password **`clusev`**), and the **`clusev` host user** + its random
|
||||
password (shown **only once** — note it down).
|
||||
(your e-mail — `admin@clusev.local` if you left it empty — plus the default password **`clusev`**),
|
||||
and the **`clusev` host user** + its random password (shown **only once** — note it down).
|
||||
|
||||
Log in with your admin e-mail and the password **`clusev`** — the panel then **forces you to set a
|
||||
new password immediately**. Do this right away: `clusev` is a known default, so the account is only
|
||||
safe once you've changed it. 2FA is **optional but recommended** — enable TOTP and/or a security key
|
||||
Log in with your admin e-mail (default **`admin@clusev.local`**) and the password **`clusev`** — the
|
||||
panel then **forces you to set a new password immediately**. Do this right away: `clusev` is a known
|
||||
default, so the account is only safe once you've changed it. You can change the login e-mail later
|
||||
under **Settings → Profile**. 2FA is **optional but recommended** — enable TOTP and/or a security key
|
||||
from **Settings → Security** whenever you like.
|
||||
|
||||
## Access, domain & TLS
|
||||
|
|
|
|||
|
|
@ -20,6 +20,14 @@ class Install extends Command
|
|||
/** Standard default admin password — forced to change on first login (must_change_password). */
|
||||
private const DEFAULT_PASSWORD = 'clusev';
|
||||
|
||||
/**
|
||||
* Standard default admin e-mail (login + Let's-Encrypt contact) when none is given. A fixed,
|
||||
* predictable value so a fresh, unattended install always logs in at admin@clusev.local —
|
||||
* not a host-derived address the operator would have to guess. Override with --email /
|
||||
* CLUSEV_ADMIN_EMAIL, or change it later under Settings → Profile.
|
||||
*/
|
||||
private const DEFAULT_EMAIL = 'admin@clusev.local';
|
||||
|
||||
protected $signature = "clusev:install
|
||||
{--email= : Admin-Login + Let's-Encrypt-E-Mail}
|
||||
{--name=Administrator : Anzeigename des Admins}";
|
||||
|
|
@ -34,8 +42,7 @@ class Install extends Command
|
|||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$host = parse_url((string) config('app.url'), PHP_URL_HOST) ?: 'localhost';
|
||||
$email = (string) ($this->option('email') ?: "admin@{$host}");
|
||||
$email = (string) ($this->option('email') ?: self::DEFAULT_EMAIL);
|
||||
|
||||
if (! filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$this->error("Ungueltige Admin-E-Mail: {$email}");
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ if [ -t 0 ]; then
|
|||
printf '%s' "HTTP-Port (Standard 80): "; read -r in_port || true
|
||||
[ -n "${in_port:-}" ] && HTTP_PORT="$in_port"
|
||||
fi
|
||||
printf '%s' "Admin E-Mail (Login + Let's Encrypt): "; read -r in_email || true
|
||||
printf '%s' "Admin E-Mail (leer = admin@clusev.local): "; read -r in_email || true
|
||||
[ -n "${in_email:-}" ] && ADMIN_EMAIL="$in_email"
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,16 @@ class InstallCommandTest extends TestCase
|
|||
$this->assertTrue((bool) $user->must_change_password, 'first login must be forced to change it');
|
||||
}
|
||||
|
||||
public function test_uses_the_fixed_default_email_when_none_is_given(): void
|
||||
{
|
||||
$this->artisan('clusev:install')->assertSuccessful();
|
||||
|
||||
$user = User::sole();
|
||||
$this->assertSame('admin@clusev.local', $user->email, 'a fresh install must default to the predictable admin@clusev.local');
|
||||
$this->assertTrue(Hash::check('clusev', $user->password));
|
||||
$this->assertTrue((bool) $user->must_change_password);
|
||||
}
|
||||
|
||||
public function test_is_a_noop_when_an_admin_already_exists(): void
|
||||
{
|
||||
User::factory()->create();
|
||||
|
|
|
|||
Loading…
Reference in New Issue