hasResource($run, 'nc_admin')) { return StepResult::advance(); } $instance = $this->instance($run); $pve = $this->pve->forHost($instance->host); $node = (string) $run->context('node'); $vmid = (int) $run->context('vmid'); $username = 'admin'; $password = Str::random(20); $occ = 'cd /opt/nextcloud && docker compose exec -T'; // Retry-safe: if a prior crashed attempt already created the user, reset // its password instead of re-running user:add (which Nextcloud rejects). $exists = (int) ($pve->guestExec($node, $vmid, $occ.' app php occ user:info '.escapeshellarg($username))['exitcode'] ?? 1) === 0; $action = $exists ? 'user:resetpassword --password-from-env '.escapeshellarg($username) : 'user:add --password-from-env --group=admin '.escapeshellarg($username); // Pass the password via env (OC_PASS), never on the argv/command line. $this->guest($pve, $run, 'OC_PASS='.escapeshellarg($password).' '.$occ.' -e OC_PASS app php occ '.$action); // Persist only the username (encrypted ref); hand the password to step 15 // encrypted-in-context for delivery, then it is scrubbed. Never plaintext. $instance->update(['nc_admin_ref' => $username]); $run->mergeContext(['admin_password' => Crypt::encryptString($password)]); $this->recordResource($run, $instance->host, 'nc_admin', $username); return StepResult::advance(); } }