purpose) { ContaboInfrastructureProvision::PURPOSE_HOSTING_NODE => $this->buildHostingNode($provision), ContaboInfrastructureProvision::PURPOSE_EMAIL_PRIMARY => $this->buildMailPrimary($provision), ContaboInfrastructureProvision::PURPOSE_EMAIL_EXTENSION => $this->buildMailExtension($provision), default => throw new \InvalidArgumentException("Unknown provision purpose: {$provision->purpose}"), }; } private function buildHostingNode(ContaboInfrastructureProvision $provision): string { $helperScript = File::get(base_path('deploy/bin/ladill-hosting-admin')); $sudoers = "www-data ALL=(root) NOPASSWD: /usr/local/bin/ladill-hosting-admin *\n"; $completionUrl = $provision->completionUrl(); return $this->contaboProvider->generateCloudInit([ 'packages' => ['curl', 'wget', 'git', 'unzip', 'nginx', 'php-fpm', 'mysql-client', 'quota'], 'ssh_keys' => array_filter([$provision->ssh_public_key]), 'write_files' => [ [ 'path' => '/opt/ladill/ladill-hosting-admin', 'permissions' => '0755', 'owner' => 'root:root', 'content' => $helperScript, ], [ 'path' => '/opt/ladill/ladill-hosting.sudoers', 'permissions' => '0440', 'owner' => 'root:root', 'content' => $sudoers, ], ], 'run_commands' => [ 'install -Dm755 /opt/ladill/ladill-hosting-admin /usr/local/bin/ladill-hosting-admin', 'install -Dm440 /opt/ladill/ladill-hosting.sudoers /etc/sudoers.d/ladill-hosting', 'visudo -cf /etc/sudoers.d/ladill-hosting', $this->completionCurlCommand($completionUrl, ['bootstrap' => 'hosting']), ], ]); } private function buildMailPrimary(ContaboInfrastructureProvision $provision): string { $payload = (array) ($provision->payload ?? []); $mailHost = (string) ($payload['mail_host'] ?? config('mailinfra.mail_host', 'mail.ladill.com')); $dbName = config('infrastructure.mail_stack.db_database', 'mail'); $dbUser = config('infrastructure.mail_stack.db_username', 'mailuser'); $dbPassword = (string) ($provision->generated_mail_db_password ?? ''); $vmailRoot = config('infrastructure.mail_stack.vmail_root', '/var/vmail'); $vmailUid = (string) config('infrastructure.mail_stack.vmail_uid', 5000); $vmailGid = (string) config('infrastructure.mail_stack.vmail_gid', 5000); $exportClients = (string) ($payload['export_client_ips'] ?? ''); $bootstrapScript = str_replace( [ '__MAIL_HOST__', '__DB_PASSWORD__', '__DB_NAME__', '__DB_USER__', '__COMPLETION_URL__', '__VMAIL_ROOT__', '__VMAIL_UID__', '__VMAIL_GID__', '__EXPORT_CLIENTS__', ], [ $mailHost, $dbPassword, $dbName, $dbUser, $provision->completionUrl(), $vmailRoot, $vmailUid, $vmailGid, $exportClients, ], File::get(resource_path('infrastructure/scripts/mail-primary-bootstrap.sh')) ); $writeFiles = [ $this->scriptFile('/opt/ladill/nfs-primary-setup.sh', 'infrastructure/scripts/nfs-primary-setup.sh'), $this->scriptFile('/opt/ladill/vmail-usage-scan.sh', 'infrastructure/scripts/vmail-usage-scan.sh'), [ 'path' => '/opt/ladill/mail-primary-bootstrap.sh', 'permissions' => '0755', 'owner' => 'root:root', 'encoding' => 'b64', 'content' => base64_encode($bootstrapScript), ], ]; return $this->contaboProvider->generateCloudInit([ 'packages' => ['curl', 'wget', 'jq', 'ca-certificates', 'sudo'], 'ssh_keys' => array_filter([$provision->ssh_public_key]), 'write_files' => $writeFiles, 'run_commands' => [ 'bash /opt/ladill/mail-primary-bootstrap.sh', ], ]); } private function buildMailExtension(ContaboInfrastructureProvision $provision): string { $payload = (array) ($provision->payload ?? []); $mailHost = (string) ($payload['mail_host'] ?? config('mailinfra.mail_host', 'mail.ladill.com')); $primaryIp = (string) ($payload['primary_ip'] ?? ''); $vmailRoot = config('infrastructure.mail_stack.vmail_root', '/var/vmail'); $mountOpts = config('infrastructure.mail_stack.nfs_mount_options', 'nfsvers=4.1,rw,hard,timeo=600,retrans=2,_netdev'); if ($primaryIp === '' && ! empty($payload['primary_email_server_id'])) { $primary = EmailServer::find($payload['primary_email_server_id']); $primaryIp = $primary?->ip_address ?? ''; $vmailRoot = $primary?->pool_vmail_root ?: $vmailRoot; } $bootstrapScript = str_replace( [ '__MAIL_HOST__', '__PRIMARY_IP__', '__COMPLETION_URL__', '__VMAIL_ROOT__', '__MOUNT_OPTS__', ], [ $mailHost, $primaryIp, $provision->completionUrl(), $vmailRoot, $mountOpts, ], File::get(resource_path('infrastructure/scripts/mail-extension-bootstrap.sh')) ); $writeFiles = [ $this->scriptFile('/opt/ladill/nfs-extension-setup.sh', 'infrastructure/scripts/nfs-extension-setup.sh'), $this->scriptFile('/opt/ladill/vmail-usage-scan.sh', 'infrastructure/scripts/vmail-usage-scan.sh'), [ 'path' => '/opt/ladill/mail-extension-bootstrap.sh', 'permissions' => '0755', 'owner' => 'root:root', 'encoding' => 'b64', 'content' => base64_encode($bootstrapScript), ], ]; return $this->contaboProvider->generateCloudInit([ 'packages' => ['curl', 'wget', 'jq', 'ca-certificates', 'sudo'], 'ssh_keys' => array_filter([$provision->ssh_public_key]), 'write_files' => $writeFiles, 'run_commands' => [ 'bash /opt/ladill/mail-extension-bootstrap.sh', ], ]); } /** * @return array */ private function scriptFile(string $remotePath, string $localRelativePath): array { return [ 'path' => $remotePath, 'permissions' => '0755', 'owner' => 'root:root', 'encoding' => 'b64', 'content' => base64_encode(File::get(resource_path($localRelativePath))), ]; } /** * @param array $extra */ private function completionCurlCommand(string $url, array $extra = []): string { $payload = json_encode(array_merge(['status' => 'ok'], $extra), JSON_UNESCAPED_SLASHES); return "curl -fsS -X POST ".escapeshellarg($url)." -H 'Content-Type: application/json' -d ".escapeshellarg($payload)." || true"; } }