Backup Diagnostics
The six endpoints that hold the backup settings and measure what the server can back up.
Overview
These six endpoints answer two questions. Two of them hold the settings: is the system on, and what stays out of a backup. The other four measure: can this server take a backup, is there room, and how much space each folder and table takes.
The four that measure are read-only and change nothing. They also feed the exclusion screen in the panel: an operator walks the tree, sees the tables by size, and decides.
The diagnostics are the real question to ask before taking a backup. They show today what would otherwise surface on the night of the run: a critical gap makes a backup impossible, while a warning leaves one weaker.
Reference
Reading the Backup Settings
Returns the backup system's main switch and what it leaves out.
curl 'https://panel.example.com/api/v1/admin/settings/backup/settings' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/settings/backup/settings', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/backup/settings');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// With the main switch OFF the schedules stop and taking one by hand is refused.
$live = Api::Settings()->GetBackupSettings()['data']['status'] === 1;Writing the Backup Settings
Switches the system on and writes the paths and tables to leave out.
curl -X PUT 'https://panel.example.com/api/v1/admin/settings/backup/settings' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"status":1,"excluded_tables":"api_logs,mail_logs"}'const res = await fetch('https://panel.example.com/api/v1/admin/settings/backup/settings', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
status: 1,
excluded_tables: 'api_logs,mail_logs',
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/backup/settings');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'status' => 1,
'excluded_tables' => 'api_logs,mail_logs',
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The list is REPLACED, not added to: read the old one first or the earlier entries go.
$cur = Api::Settings()->GetBackupSettings()['data']['excluded_tables'];
Api::Settings()->UpdateBackupSettings([
'excluded_tables' => $cur . ',mail_logs',
]);Reading the Diagnostics
Tells you whether the server can actually take a backup.
phar for archiving, zlib for compression, spl for walking directories.disk-monitor for space measuring, exec for child processes, streaming-pipe for streaming.mysqldump-cli, the external dump tool.curl 'https://panel.example.com/api/v1/admin/settings/backup/diagnostics' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/settings/backup/diagnostics', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/backup/diagnostics');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// A full critical list means NO backup can run; the warning list only weakens one.
$d = Api::Settings()->GetBackupDiagnostics()['data'];
if ($d['critical']) throw new Exception('Backups cannot run on this server.');Reading the Disk Information
Returns how much room is left on the disk the installation sits on.
curl 'https://panel.example.com/api/v1/admin/settings/backup/disk' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/settings/backup/disk', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const { data } = await res.json();
if (data.total === undefined) console.warn('disk measurement unavailable');$ch = curl_init('https://panel.example.com/api/v1/admin/settings/backup/disk');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// When the server allows no measurement the fields DO NOT arrive, so check before reading.
$disk = Api::Settings()->GetBackupDisk()['data'];
$free = $disk['free'] ?? null;Walking the Directory Tree
Returns the files and folders under the installation root.
curl 'https://panel.example.com/api/v1/admin/settings/backup/directory-listing?path=templates' \
-H "Authorization: Bearer $API_KEY"const url = new URL('https://panel.example.com/api/v1/admin/settings/backup/directory-listing');
url.searchParams.set('path', 'templates');
const res = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/backup/directory-listing?' . http_build_query(['path' => 'templates']));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The tree cannot leave the root; a path climbing upward comes back as a 422.
$tree = Api::Settings()->GetBackupDirectoryListing([], ['path' => 'templates'])['data'];Measuring the Tables
Returns the database tables with their row counts and sizes.
curl 'https://panel.example.com/api/v1/admin/settings/backup/tables' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/settings/backup/tables', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/settings/backup/tables');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Feeding the exclusion screen with the fattest tables: size is NOT the archive size.
$tables = Api::Settings()->GetBackupTables()['data'];
usort($tables, fn ($a, $b) => $b['size'] <=> $a['size']);Pitfalls
While the backup system is off, schedules do not run and the take-by-hand call is refused. The schedules stay in the list, the targets stay put, and none of them raises an error. When no backup appears on an installation, look at this field before you go hunting through the schedules.
The path and table lists are strings, and what you send replaces what was there. Sending only the one table you meant to add drops every earlier line. Read the current value first and append to it.
When the server allows no space measurement this endpoint returns an empty object and raises nothing. Check the fields exist before reading them, or an absent value reads as zero and you warn that the disk is full. The same gap also shows in the diagnostics warning list.
Whatever is excluded by default is filtered out of the tree and never appears in the listing. The backup folder itself is one of those, and it keeps being filtered even after an operator renames it. That is deliberate: were the backups themselves included, every run would carry the one before it.
A table's row count is the engine's estimate. It can be tens of percent off, so keep it out of billing and reporting figures. The size adds data and index together, while a compressed dump comes out far smaller. Both are good enough for deciding what to exclude and no more than that.
Related Articles
Vielen Dank für Ihre Rückmeldung!
Unser Support-Team ist rund um die Uhr für Sie da, wenn Sie oben nicht fündig werden.