laravel-hetzner-storagebox maintained by ghostcompiler
Description
Production-ready Laravel SDK for the Hetzner Storage Box API
Author
Last update
2026/06/18 08:43
(dev-main)
License
Downloads
1 947
Features
- 100% Endpoint Coverage: Complete implementation of all storage boxes, subaccounts, snapshots, actions, and locations.
- Fail-Safe Retries & Backoff: Robust exponential backoff and rate-limit parsing handling
RateLimit-Resetresponse headers automatically. - Concurrently Pooled Processing: Execute calls asynchronously or concurrently in batches.
- Dynamic Filter Builder: Fluent query-building for filtering, page indexing, and sorting.
- Type-Safe DTOs: Automated data hydration into standard PHP DTO structures.
- Custom Exceptions: Specialized mapping of API status codes.
Installation
Install the package via Composer:
composer require ghostcompiler/laravel-hetzner-storagebox
Publish the configuration file using our simplified command installer:
php artisan ghost:storagebox install
Add your Hetzner Storage Box Console API Token to your .env file:
HETZNER_STORAGEBOX_TOKEN=your_api_token_here
HETZNER_STORAGEBOX_TIMEOUT=30
HETZNER_STORAGEBOX_RETRIES=3
HETZNER_STORAGEBOX_RETRY_BACKOFF=100
HETZNER_STORAGEBOX_LOGGING_ENABLED=true
Usage Examples
You can access the SDK in three ways:
- Facade (Recommended for Laravel environments)
use GhostCompiler\Hetzner\StorageBox\Facades\HetznerStorageBox;
$boxes = HetznerStorageBox::storageBoxes()->get();
- Global Helper (Convenience function)
$boxes = HetznerStorageBox()->storageBoxes()->get();
- Dynamic Token Authentication (For multi-tenant or multi-account systems)
$boxes = HetznerStorageBox('your_dynamic_token_here')->storageBoxes()->get();
Storage Boxes
Listing and Filtering Storage Boxes
use GhostCompiler\Hetzner\StorageBox\Facades\HetznerStorageBox;
// List the first 50 storage boxes matching a name
$boxes = HetznerStorageBox::storageBoxes()
->filter(['name' => 'box-01'])
->perPage(50)
->page(1)
->get();
foreach ($boxes as $box) {
echo $box->name . ': ' . $box->status . "\n";
}
Paginated Results
$paginated = HetznerStorageBox::storageBoxes()->paginate(25, 2);
$boxes = $paginated->items; // StorageBoxCollection
$meta = $paginated->pagination; // PaginationMeta DTO
echo "Page: " . $meta->page . " of " . $meta->lastPage;
Creating and Deleting a Storage Box
// Create a new storage box
$response = HetznerStorageBox::storageBoxes()->create([
'name' => 'backups-prod',
'storage_box_type' => 'bx11',
'location' => 'fsn1',
'password' => 'secure_password_here'
]);
$box = $response->storageBox;
$action = $response->action;
echo "Provisioned Storage Box ID: " . $box->id . "\n";
// Delete the storage box
$deleteAction = HetznerStorageBox::storageBoxes()->delete($box->id);
if ($deleteAction) {
echo "Deletion status: " . $deleteAction->status;
}
Triggering Storage Box Actions
// Reset Storage Box password
$action = HetznerStorageBox::storageBoxes()->resetPassword($boxId, 'new_secure_password_123');
echo "Action status: " . $action->status; // running / success
// Change delete protection
HetznerStorageBox::storageBoxes()->changeProtection($boxId, true);
Listing Storage Box Folders
$folders = HetznerStorageBox::storageBoxes()->folders($boxId, '/backups');
foreach ($folders['folders'] as $folder) {
echo "Folder: " . $folder . "\n";
}
Subaccounts
Manage directories and access protocols for subaccounts.
$subaccountsManager = HetznerStorageBox::storageBoxes()->subaccounts($boxId);
// List subaccounts
$subaccounts = $subaccountsManager->all();
// Create a subaccount
$sub = $subaccountsManager->create([
'name' => 'upload-sub',
'description' => 'Subaccount for uploads',
'home_directory' => '/uploads',
'access_settings' => [
'samba_enabled' => false,
'ssh_enabled' => true,
'webdav_enabled' => true,
'read_only' => false
]
]);
// Reset subaccount password
$subaccountsManager->resetPassword($sub->id, 'SecurePassword123!');
Snapshots
Manage point-in-time filesystem snapshots.
$snapshotsManager = HetznerStorageBox::storageBoxes()->snapshots($boxId);
// List snapshots
$snapshots = $snapshotsManager->all();
// Create a snapshot
$snapshot = $snapshotsManager->create([
'description' => 'Daily backup snapshot',
'labels' => [
'env' => 'production'
]
]);
// Delete a snapshot
$snapshotsManager->delete($snapshot->id);
Asynchronous Requests
// Return a Guzzle Promise immediately
$promise = HetznerStorageBox::storageBoxes()->async()->all();
// Resolve promise when ready
$boxes = $promise->wait();
Batch Concurrent Operations
// Execute multiple queries concurrently
$results = HetznerStorageBox::batch([
fn () => HetznerStorageBox::storageBoxes()->find(1),
fn () => HetznerStorageBox::storageBoxes()->find(2),
fn () => HetznerStorageBox::storageBoxTypes()->find(4),
]);
$box1 = $results[0];
$box2 = $results[1];
$type = $results[2];
Exception Handling
All exceptions inherit from GhostCompiler\Hetzner\StorageBox\Exceptions\HetznerException.
use GhostCompiler\Hetzner\StorageBox\Exceptions\AuthenticationException;
use GhostCompiler\Hetzner\StorageBox\Exceptions\ValidationException;
use GhostCompiler\Hetzner\StorageBox\Exceptions\RateLimitException;
use GhostCompiler\Hetzner\StorageBox\Exceptions\HetznerException;
try {
HetznerStorageBox::storageBoxes()->create(['name' => '']);
} catch (AuthenticationException $e) {
// 401 Unauthorized
} catch (ValidationException $e) {
// 422 Unprocessable Entity
$errors = $e->getErrors(); // Get field-specific validation errors
} catch (RateLimitException $e) {
// 429 Rate Limit Exceeded
$secondsToWait = $e->getSecondsUntilReset();
} catch (HetznerException $e) {
// Base exception handler
}
Static Analysis & Linting
Run PHPStan static analysis:
vendor/bin/phpstan analyse
Run Psalm static analysis:
vendor/bin/psalm
Format code with Pint:
vendor/bin/pint
Development Environment
Built using ServBay
- Mac M4 Tested
- macOS Apple Silicon
- Powered by ServBay