From 75fca1f46fe8a15fe4085ca32952157581f1ee69 Mon Sep 17 00:00:00 2001 From: Konrad Michalik Date: Wed, 18 Feb 2026 16:59:25 +0100 Subject: [PATCH 1/2] fix: resolve database hostname to IP before .env template rendering --- src/Database/Manager/MittwaldApi.php | 43 ++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/Database/Manager/MittwaldApi.php b/src/Database/Manager/MittwaldApi.php index 9fd951c..0e2e2fd 100644 --- a/src/Database/Manager/MittwaldApi.php +++ b/src/Database/Manager/MittwaldApi.php @@ -83,8 +83,8 @@ public function create(): void // Additionally, even after the user is "ready", the DNS entry for the database host // (e.g. mysql-xyz.pg-s-xxx.db.project.host) may not be resolvable yet and can flap // intermittently for several minutes. The TCP connectivity check below catches the - // initial delay; the DNS-to-IP resolution in feature_sync.php::resolveDatabaseHostToIp() - // handles the ongoing flapping by eliminating DNS dependency entirely. + // initial delay, and the immediate hostname-to-IP resolution eliminates DNS dependency + // for all subsequent operations (template rendering, db_sync_tool, TYPO3 CLI, etc.). $ready = $this->checkForDatabaseReadyStatus( $responseBody->getUserId(), (int) get('mittwald_database_wait', 30), @@ -108,9 +108,15 @@ public function create(): void ); } + // Resolve hostname to IP immediately while DNS is known to be working. + // Mittwald DNS entries flap intermittently for several minutes after database creation. + // By resolving now, the .env template will contain the IP address, eliminating DNS + // dependency for db_sync_tool, TYPO3 CLI, and all subsequent remote commands. + $databaseHost = $this->resolveHostnameToIp($database->getHostName()); + $user = $this->getDatabaseUser($responseBody->getUserId()); - $this->initDatabaseConfiguration($database, $user); + $this->initDatabaseConfiguration($database, $user, $databaseHost); } /** @@ -229,14 +235,41 @@ private function getDatabaseUser(string $id): MysqlUser return $response->getBody(); } - private function initDatabaseConfiguration(MySqlDatabase $database, MySqlUser $user): void + private function initDatabaseConfiguration(MySqlDatabase $database, MySqlUser $user, string $databaseHost): void { set('database_user', $user->getName()); set('database_name', $database->getName()); - set('database_host', $database->getHostName()); + set('database_host', $databaseHost); set('database_password', VarUtility::getDatabasePassword()); } + /** + * Resolves a database hostname to its IP address on the remote server. + * + * This is called immediately after the TCP connectivity check passes, when DNS is + * known to be working. The resolved IP is used in the .env template instead of the + * hostname, bypassing Mittwald's intermittent DNS flapping for all subsequent commands. + * + * Falls back to the original hostname if resolution fails. + */ + private function resolveHostnameToIp(string $hostname): string + { + try { + $resolveCmd = sprintf('echo gethostbyname("%s");', addslashes($hostname)); + $ip = trim(run("php -r " . escapeshellarg($resolveCmd))); + + if ($ip !== $hostname && filter_var($ip, FILTER_VALIDATE_IP)) { + info("Resolved database host {$hostname} to {$ip}"); + return $ip; + } + } catch (\Throwable $e) { + debug("Could not resolve {$hostname} to IP: " . $e->getMessage()); + } + + debug("Could not resolve {$hostname} to IP, using hostname as fallback."); + return $hostname; + } + private function checkDatabaseHostReachable(string $hostname, int $waitingTime, int $maxRetries): bool { $port = (int) get('database_port', 3306); From cb451dedb26118f4e5052491be4da45fd9fd7772 Mon Sep 17 00:00:00 2001 From: Konrad Michalik Date: Wed, 18 Feb 2026 17:02:58 +0100 Subject: [PATCH 2/2] fix: remove filter_var usage to avoid ext-filter dependency --- src/Database/Manager/MittwaldApi.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Manager/MittwaldApi.php b/src/Database/Manager/MittwaldApi.php index 0e2e2fd..f6da906 100644 --- a/src/Database/Manager/MittwaldApi.php +++ b/src/Database/Manager/MittwaldApi.php @@ -258,7 +258,7 @@ private function resolveHostnameToIp(string $hostname): string $resolveCmd = sprintf('echo gethostbyname("%s");', addslashes($hostname)); $ip = trim(run("php -r " . escapeshellarg($resolveCmd))); - if ($ip !== $hostname && filter_var($ip, FILTER_VALIDATE_IP)) { + if ($ip !== $hostname) { info("Resolved database host {$hostname} to {$ip}"); return $ip; }