instance($run); $node = (string) $run->context('node'); $vmid = (int) $run->context('vmid'); $pve = $this->pve->forHost($instance->host); // Deploy once (guarded); the generated DB password is transient. if (! $run->context('stack_deployed')) { $dbPassword = Str::random(28); $run->mergeContext(['db_password' => $dbPassword]); $this->guest($pve, $run, 'install -d /opt/nextcloud && printf %s '.escapeshellarg('MYSQL_PASSWORD='.$dbPassword."\n"). ' > /opt/nextcloud/.env'); $this->guest($pve, $run, 'cd /opt/nextcloud && docker compose up -d'); $run->mergeContext(['stack_deployed' => true]); } // Poll until Nextcloud answers (poll doesn't consume the retry budget). $health = $pve->guestExec($node, $vmid, 'curl -sf http://localhost/status.php >/dev/null 2>&1 && echo ok || echo wait'); if (trim($health['out-data'] ?? '') !== 'ok') { return StepResult::poll(15, 'waiting for application stack'); } $run->forgetContext('db_password'); // scrub the secret once the stack is up return StepResult::advance(); } }