From 673ca564541455fe7093cfb801fda54dcbf2eabe Mon Sep 17 00:00:00 2001 From: likehopper Date: Mon, 1 Jun 2026 01:41:38 +0200 Subject: [PATCH 1/2] fix: inject HTTP proxy env vars into node subprocess calls When Nextcloud is configured with a proxy (config.php 'proxy' key), node subprocesses spawned via exec() do not inherit proxy settings, causing ETIMEDOUT errors when downloading libtensorflow and ffmpeg binaries on installations behind an HTTP proxy. Fix: read the proxy setting from Nextcloud system config via IConfig and prepend HTTPS_PROXY/HTTP_PROXY env vars to the exec() commands in runTfjsInstall(), runTfjsGpuInstall() and runFfmpegInstall(). Signed-off-by: likehopper --- lib/Migration/InstallDeps.php | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/Migration/InstallDeps.php b/lib/Migration/InstallDeps.php index ed8ed084e..0fd6ec280 100644 --- a/lib/Migration/InstallDeps.php +++ b/lib/Migration/InstallDeps.php @@ -27,6 +27,7 @@ use OCA\Recognize\Helper\TAR; use OCP\AppFramework\Services\IAppConfig; +use OCP\IConfig; use OCP\Http\Client\IClientService; use OCP\IBinaryFinder; use OCP\Migration\IOutput; @@ -39,6 +40,7 @@ final class InstallDeps implements IRepairStep { public const NODE_SERVER_UNOFFICIAL = 'https://unofficial-builds.nodejs.org/download/release/'; protected IAppConfig $config; + private IConfig $systemConfig; private string $binaryDir; private string $preGypBinaryDir; private string $ffmpegDir; @@ -52,8 +54,9 @@ final class InstallDeps implements IRepairStep { private IBinaryFinder $binaryFinder; private string $nodeModulesDir; - public function __construct(IAppConfig $config, IClientService $clientService, LoggerInterface $logger, IBinaryFinder $binaryFinder) { + public function __construct(IAppConfig $config, IConfig $systemConfig, IClientService $clientService, LoggerInterface $logger, IBinaryFinder $binaryFinder) { $this->config = $config; + $this->systemConfig = $systemConfig; $this->binaryDir = dirname(__DIR__, 2) . '/bin/'; $this->nodeModulesDir = dirname(__DIR__, 2) . '/node_modules/'; $this->preGypBinaryDir = dirname(__DIR__, 2) . '/node_modules/@mapbox/node-pre-gyp/bin/'; @@ -185,10 +188,25 @@ protected function testBinary(string $binaryPath): ?string { return trim(implode("\n", $output)); } + + /** + * Build proxy environment variable prefix from Nextcloud system config. + * + * @return string Empty string or "HTTPS_PROXY=... HTTP_PROXY=... " prefix + */ + protected function getProxyEnv() : string { + $proxy = $this->systemConfig->getSystemValueString('proxy', ''); + if ($proxy === '') { + return ''; + } + return 'HTTPS_PROXY=' . escapeshellarg($proxy) . ' ' + . 'HTTP_PROXY=' . escapeshellarg($proxy) . ' '; + } + protected function runTfjsInstall(string $nodeBinary) : void { $oriCwd = getcwd(); chdir($this->tfjsPath); - $cmd = 'PATH='.escapeshellcmd($this->preGypBinaryDir).':'.escapeshellcmd($this->binaryDir).':$PATH ' . escapeshellcmd($nodeBinary) . ' ' . escapeshellarg($this->tfjsInstallScript) . ' cpu ' . escapeshellarg('download'); + $cmd = $this->getProxyEnv() . 'PATH='.escapeshellcmd($this->preGypBinaryDir).':'.escapeshellcmd($this->binaryDir).':$PATH ' . escapeshellcmd($nodeBinary) . ' ' . escapeshellarg($this->tfjsInstallScript) . ' cpu ' . escapeshellarg('download'); try { exec($cmd . ' 2>&1', $output, $returnCode); // Appending 2>&1 to avoid leaking sterr } catch (\Throwable $e) { @@ -205,7 +223,7 @@ protected function runTfjsInstall(string $nodeBinary) : void { protected function runTfjsGpuInstall(string $nodeBinary) : void { $oriCwd = getcwd(); chdir($this->tfjsGPUPath); - $cmd = 'PATH='.escapeshellcmd($this->preGypBinaryDir).':'.escapeshellcmd($this->binaryDir).':$PATH ' . escapeshellcmd($nodeBinary) . ' ' . escapeshellarg($this->tfjsGpuInstallScript) . ' gpu ' . escapeshellarg('download'); + $cmd = $this->getProxyEnv() . 'PATH='.escapeshellcmd($this->preGypBinaryDir).':'.escapeshellcmd($this->binaryDir).':$PATH ' . escapeshellcmd($nodeBinary) . ' ' . escapeshellarg($this->tfjsGpuInstallScript) . ' gpu ' . escapeshellarg('download'); try { exec($cmd . ' 2>&1', $output, $returnCode); // Appending 2>&1 to avoid leaking sterr } catch (\Throwable $e) { @@ -222,7 +240,7 @@ protected function runTfjsGpuInstall(string $nodeBinary) : void { protected function runFfmpegInstall(string $nodeBinary): void { $oriCwd = getcwd(); chdir($this->ffmpegDir); - $cmd = escapeshellcmd($nodeBinary) . ' ' . escapeshellarg($this->ffmpegInstallScript); + $cmd = $this->getProxyEnv() . escapeshellcmd($nodeBinary) . ' ' . escapeshellarg($this->ffmpegInstallScript); try { exec($cmd . ' 2>&1', $output, $returnCode); // Appending 2>&1 to avoid leaking sterr } catch (\Throwable $e) { From 7d7b6ad2ba4225df00dbc017321080a2bef7e0c3 Mon Sep 17 00:00:00 2001 From: likehopper Date: Fri, 12 Jun 2026 12:56:11 +0200 Subject: [PATCH 2/2] fix: apply coding standards (cs:fix) --- lib/Migration/InstallDeps.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Migration/InstallDeps.php b/lib/Migration/InstallDeps.php index 0fd6ec280..9b3d34db6 100644 --- a/lib/Migration/InstallDeps.php +++ b/lib/Migration/InstallDeps.php @@ -27,9 +27,9 @@ use OCA\Recognize\Helper\TAR; use OCP\AppFramework\Services\IAppConfig; -use OCP\IConfig; use OCP\Http\Client\IClientService; use OCP\IBinaryFinder; +use OCP\IConfig; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; use Psr\Log\LoggerInterface;