n8n workflow - cPanel aanmaken en WordPress installeren via webhook
In deze handleiding leggen we uit hoe je vanuit n8n een cPanel account kunt aanmaken binnen je reseller omgeving, en hier direct een WordPress installatie op kunt klaarzetten.
Download de volledige workflow hier

Benodigdheden
- Een n8n personal server of hoger (zie https://www.hoasted.com/hosting/n8n-vps/)
- Een reseller account bij Hoasted, en een WHM API key (zie ook onze handleiding)
- Optioneel: Een Slack API key met rechten om te posten in een channel (zie handleiding)
Configuratie
Allereerst is het belangrijk om enkele zaken te configureren. Om een connectie op te zetten met het reseller account is het eerst noodzakelijk om een WHM API key aan te vragen, en deze vervolgens in de credentials van n8n te plaatsen. Deze kun je als 'Header Auth' toevoegen, met de name 'Authorization'. De token is vervolgens een combinatie van de WHM username en de WHM API key, welke je kunt toevoegen als 'whm username:whmapikey' (zonder quotes).

Zodra deze credentials zijn aangemaakt dienen deze verwerkt te worden in de 'Create cPanel account' en 'Create cPanel session' nodes.

Na het koppelen van deze credentials hoeft enkel nog de servernaam aangepast te worden in de 'Set input' node op regel 2. Gebruik hier het format 'sXXXX' voor, of 'vXXXX' bij gebruik van een VPS.
Trigger toevoegen
Om de workflow aan te roepen is een trigger nodig. In het voorbeeld hebben we hier een n8n formulier voor ingezet, en een optie om een webhook te gebruiken. Op basis van de webhook kun je nagenoeg alle systemen hier aan koppelen. De manual trigger is in dit geval toegevoegd om te laten zien welke input de 'Set input' node verwacht.
Set input node
Binnen deze node normaliseren we de data die binnenkomt, en genereren de username en wachtwoord voor zowel de cPanel als WordPress installaties. Hierbij is het zaak om de data aan te leveren in onderstaande formaat. Mocht je een webhook gebruiken kun je de code node hiervoor (format webhook data) gebruiken om de data te normaliseren.
[
{
"Domein": "jouwdomeinhier.nl",
"Kies het account type": "R-1X-PERSONAL-20GBDISK",
"Contact email": "jouw@emailhier.nl",
"WordPress installeren?": [
"Ja"
]
}
]
Installatie
Wanneer de data correct is aangeleverd aan de 'Set input' node zal de workflow vervolgens het cPanel account klaarzetten, en optioneel de WordPress installatie uitvoeren via Installatron. Het resultaat hiervan zal afhankelijk van foutmeldingen worden verwerkt in enkele code nodes waarbij de output gefinetuned kan worden. Dit gaat vervolgens naar een 'wait' node om alles combineren.
Output
Na de 'wait' node kun je je gewenste output toevoegen. Standaard zal de output in HTML gegeven worden. Mocht je een output willen koppelen die geen HTML ondersteund (in het voorbeeld is dit de Slack terugkoppeling) kun je deze via de 'Format voor Slack' node normaliseren naar de juiste output.
In ons voorbeeld zijn opties voor terugkoppeling aan Slack, E-mail, een n8n formulier en een webhook response toegevoegd. Indien gewenst kun je hier zelf nog extra opties aan toevoegen door deze na de 'wait' node te plaatsen.
Webhook formulier
Wanneer je deze workflow wilt laten aanroepen vanuit een PHP bestand zal hierbij de webhook URL doorgegeven moeten worden welke je kunt vinden in de 'Webhook trigger' node. Vervolgens kun je deze verwerken in onderstaande voorbeeld PHP bestand, en uploaden naar je server.
<?php
declare(strict_types=1);
session_start();
$N8N_WEBHOOK_URL = "https://jouwdomeinhier.n8p1.hostingsecure.com/webhook-test/f0d92372-6894-22d5-8be1-ad9a3ccb9401";
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$submitted = ($_SERVER['REQUEST_METHOD'] === 'POST');
$errors = [];
$successMsg = null;
$responseInfo = null;
if ($submitted) {
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
$errors[] = "Ongeldige sessie. Vernieuw de pagina en probeer opnieuw.";
}
$domein = trim((string)($_POST['domein'] ?? ''));
$accountType = trim((string)($_POST['account_type'] ?? ''));
$contactEmail = trim((string)($_POST['contact_email'] ?? ''));
$wpInstall = isset($_POST['wp_install']) && $_POST['wp_install'] === 'Ja';
if ($domein === '') {
$errors[] = "Vul een domeinnaam in.";
} else {
if (!preg_match('/^(?=^.{1,253}$)(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z]{2,})+$/', $domein)) {
$errors[] = "Ongeldige domeinnaam";
}
}
if ($accountType === '') {
$errors[] = "Kies een account type.";
}
if ($contactEmail === '' || !filter_var($contactEmail, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Vul een geldig e-mailadres in.";
}
if (!$errors) {
$payload = [
[
"Domein" => $domein,
"Kies het account type" => $accountType,
"Contact email" => $contactEmail,
"WordPress installeren?" => $wpInstall ? ["Ja"] : ["Nee"],
]
];
$ch = curl_init($N8N_WEBHOOK_URL);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Accept: application/json",
],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
CURLOPT_CONNECTTIMEOUT => 300,
CURLOPT_TIMEOUT => 300,
]);
$responseBody = curl_exec($ch);
$curlErr = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($curlErr) {
$errors[] = "Verzenden naar n8n mislukt: " . htmlspecialchars($curlErr, ENT_QUOTES, 'UTF-8');
} elseif ($httpCode < 200 || $httpCode >= 300) {
$errors[] = "n8n antwoordde met HTTP $httpCode. Antwoord: " . htmlspecialchars((string)$responseBody, ENT_QUOTES, 'UTF-8');
} else {
$successMsg = "Aanvraag verzonden! n8n heeft de data ontvangen.";
$responseInfo = $responseBody;
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
$domein = $accountType = $contactEmail = "";
$wpInstall = false;
}
}
}
?>
<!doctype html>
<html lang="nl">
<head>
<meta charset="utf-8">
<title>Aanvraagformulier Hosting</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<?php if ($errors): ?>
<div class="alert error">
<strong>Foutmeldingen:</strong>
<ul>
<?php foreach ($errors as $e): ?>
<li><?= $e ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php elseif ($successMsg): ?>
<div class="alert success"><?= htmlspecialchars($successMsg, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<form method="post" action="">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8') ?>">
<label for="domein">Domein</label>
<input type="text" id="domein" name="domein" placeholder="jouwdomeinhier.nl"
value="<?= isset($domein) ? htmlspecialchars($domein, ENT_QUOTES, 'UTF-8') : '' ?>" required>
<label for="account_type">Kies het account type</label>
<select id="account_type" name="account_type" required>
<?php
$plans = [
"R-1X-PERSONAL-20GBDISK" => "R-1X-PERSONAL-20GBDISK",
"R-2X-PROFESSIONAL-20GBDISK" => "R-2X-PROFESSIONAL-20GBDISK",
"R-4X-BUSINESS-20GBDISK" => "R-4X-BUSINESS-20GBDISK",
"R-8X-ENTERPRISE-20GBDISK" => "R-8X-ENTERPRISE-20GBDISK",
];
$selected = $accountType ?? "R-1X-PERSONAL-20GBDISK";
foreach ($plans as $val => $label) {
$isSel = ($selected === $val) ? 'selected' : '';
echo "<option value=\"" . htmlspecialchars($val, ENT_QUOTES, 'UTF-8') . "\" $isSel>" . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . "</option>";
}
?>
</select>
<label for="contact_email">Contact email</label>
<input type="email" id="contact_email" name="contact_email" placeholder="test@test.nl"
value="<?= isset($contactEmail) ? htmlspecialchars($contactEmail, ENT_QUOTES, 'UTF-8') : '' ?>" required>
<label>WordPress installeren?</label>
<div class="checkbox">
<input type="checkbox" id="wp_install" name="wp_install" value="Ja" <?= !empty($wpInstall) ? 'checked' : '' ?>>
<label for="wp_install" style="font-weight: 400;">Ja, installeer WordPress</label>
</div>
<button type="submit">Verzenden</button>
</form>
<?php if ($responseInfo): ?>
<h2>Antwoord van n8n</h2>
<pre><?= htmlspecialchars($responseInfo, ENT_QUOTES, 'UTF-8') ?></pre>
<?php endif; ?>
</body>
</html>