⚡️ Hetzner Laravel is a supercharged community-maintained Laravel SDK that allows you to interact with the Hetzner Cloud API. Inspired by Nuno Maduro's excellent OpenAI PHP client.
- 🚀 Modern Architecture: Clean, organized, and maintainable code structure
- 🧪 Testing Ready: Includes
ClientFakefor easy testing and mocking - 📊 Meta Information: Access rate limits and request details
- 🛡️ Type Safe: Full type safety with PHP 8.2+
- 🎯 Resource Based: Clean, organized API resources
- 🔧 Laravel Integration: Seamless Laravel service provider and facade
- 🌐 Complete API Coverage: All Hetzner Cloud API endpoints implemented
You can install the package via composer:
composer require boci/hetzner-laravelPublish the configuration file:
php artisan vendor:publish --provider="Boci\HetznerLaravel\HetznerLaravelServiceProvider" --tag="config"Add your Hetzner API token to your .env file:
HETZNER_TOKEN=your-hetzner-api-token-hereuse Boci\HetznerLaravel\Client;
$client = Client::factory()
->withApiKey('your-api-token')
->make();
// Create a server
$response = $client->servers()->create([
'name' => 'my-server',
'server_type' => 'cpx11',
'image' => 'ubuntu-24.04',
'location' => 'nbg1',
]);
$server = $response->server();
$action = $response->action();
$rootPassword = $response->rootPassword();
echo "Server ID: " . $server->id();
echo "Server Name: " . $server->name();
echo "Status: " . $server->status();
echo "Root Password: " . $rootPassword;use Boci\HetznerLaravel\Facades\HetznerLaravel;
// List all servers
$servers = HetznerLaravel::servers()->list();
foreach ($servers->servers() as $server) {
echo "Server: " . $server->name() . " - " . $server->status() . "\n";
}
// Get server details
$server = HetznerLaravel::servers()->retrieve('12345');
echo "Server IP: " . $server->server()->publicNet()['ipv4']['ip'];
// Delete a server
$action = HetznerLaravel::servers()->delete('12345');
echo "Delete action status: " . $action->action()->status();use Boci\HetznerLaravel\Facades\HetznerLaravel;
// List available images
$images = HetznerLaravel::images()->list();
foreach ($images->images() as $image) {
echo "Image: " . $image->name() . " - " . $image->osFlavor() . "\n";
}
// Get specific image details
$image = HetznerLaravel::images()->retrieve('12345');
echo "Image size: " . $image->image()->imageSize() . " GB";use Boci\HetznerLaravel\Facades\HetznerLaravel;
// List available locations
$locations = HetznerLaravel::locations()->list();
foreach ($locations->locations() as $location) {
echo "Location: " . $location->name() . " - " . $location->city() . ", " . $location->country() . "\n";
}use Boci\HetznerLaravel\Facades\HetznerLaravel;
// List available server types
$serverTypes = HetznerLaravel::serverTypes()->list();
foreach ($serverTypes->serverTypes() as $serverType) {
echo "Server Type: " . $serverType->name() . " - " . $serverType->cores() . " cores, " . $serverType->memory() . " GB RAM\n";
}use Boci\HetznerLaravel\Facades\HetznerLaravel;
// List all networks
$networks = HetznerLaravel::networks()->list();
foreach ($networks->networks() as $network) {
echo "Network: " . $network->name() . " - " . $network->ipRange() . "\n";
}
// Create a new network
$response = HetznerLaravel::networks()->create([
'name' => 'my-network',
'ip_range' => '10.0.0.0/16',
]);
$network = $response->network();
echo "Created network: " . $network->name();use Boci\HetznerLaravel\Facades\HetznerLaravel;
// List all load balancers
$loadBalancers = HetznerLaravel::loadBalancers()->list();
foreach ($loadBalancers->loadBalancers() as $lb) {
echo "Load Balancer: " . $lb->name() . " - " . $lb->loadBalancerType()->name() . "\n";
}
// Create a load balancer
$response = HetznerLaravel::loadBalancers()->create([
'name' => 'my-lb',
'load_balancer_type' => 'lb11',
'location' => 'nbg1',
]);
$loadBalancer = $response->loadBalancer();
echo "Created load balancer: " . $loadBalancer->name();use Boci\HetznerLaravel\Facades\HetznerLaravel;
// List DNS zones
$zones = HetznerLaravel::dnsZones()->list();
foreach ($zones->zones() as $zone) {
echo "Zone: " . $zone->name() . " - " . $zone->status() . "\n";
}
// Create a DNS zone
$response = HetznerLaravel::dnsZones()->create([
'name' => 'example.com',
'mode' => 'primary',
'ttl' => 3600,
]);
$zone = $response->zone();
echo "Created zone: " . $zone->name();
// List DNS records for a zone
$rrsets = HetznerLaravel::dnsZones()->rrsets()->list('example.com');
foreach ($rrsets->rrsets() as $rrset) {
echo "Record: " . $rrset->name() . " " . $rrset->type() . " " . $rrset->ttl() . "\n";
}
// Create a DNS record
$response = HetznerLaravel::dnsZones()->rrsets()->create('example.com', [
'name' => 'www',
'type' => 'A',
'ttl' => 3600,
'records' => [
[
'value' => '192.168.1.1',
'comment' => 'Web server',
],
],
]);
$rrset = $response->rrset();
echo "Created record: " . $rrset->name() . " " . $rrset->type();
// Export zone file
$exportResponse = HetznerLaravel::dnsZones()->export('example.com');
echo "Zone file: " . $exportResponse->zoneFile();
// Change zone nameservers
$actionResponse = HetznerLaravel::dnsZones()->actions()->changeNameservers('example.com', [
'nameservers' => ['ns1.example.com', 'ns2.example.com'],
]);
echo "Action status: " . $actionResponse->action()->status();Access rate limits and request details:
$response = $client->servers()->list();
$meta = $response->meta();
echo "Request ID: " . $meta->requestId;
echo "Rate Limit: " . $meta->rateLimitLimit;
echo "Remaining: " . $meta->rateLimitRemaining;
echo "Reset Time: " . $meta->rateLimitReset;The package provides a fake implementation for testing:
use Boci\HetznerLaravel\Testing\ClientFake;
use Boci\HetznerLaravel\Responses\Servers\CreateResponse;
$client = new ClientFake([
CreateResponse::fake([
'name' => 'test-server',
'server_type' => 'cpx11',
]),
]);
$response = $client->servers()->create([
'name' => 'test-server',
'server_type' => 'cpx11',
'image' => 'ubuntu-24.04',
'location' => 'nbg1',
]);
expect($response->server()->name())->toBe('test-server');
// Assert that requests were sent
$client->assertSent(\Boci\HetznerLaravel\Resources\Servers::class, function (string $method, array $parameters): bool {
return $method === 'create' && $parameters['name'] === 'test-server';
});use Boci\HetznerLaravel\Testing\ClientFake;
use Boci\HetznerLaravel\Exceptions\ErrorException;
$client = new ClientFake([
new ErrorException([
'message' => 'Server not found',
'code' => 'server_not_found',
], 404)
]);
// This will throw the ErrorException
$client->servers()->retrieve('non-existent');use Boci\HetznerLaravel\Client;
use GuzzleHttp\Client as GuzzleClient;
$client = Client::factory()
->withApiKey('your-api-token')
->withHttpClient(new GuzzleClient([
'timeout' => 60,
'verify' => false, // Only for development
]))
->make();use Boci\HetznerLaravel\Client;
class ServerController
{
public function __construct(
private Client $hetznerClient
) {}
public function createServer()
{
$response = $this->hetznerClient->servers()->create([
'name' => 'my-server',
'server_type' => 'cpx11',
'image' => 'ubuntu-24.04',
'location' => 'nbg1',
]);
return response()->json($response->toArray());
}
}The package is organized into resources that correspond to Hetzner Cloud API endpoints:
- Actions: Get multiple actions, get an action
- Billing: Get all prices
- Certificates: List, create, get, update, delete certificates
- DNS Zones: List, create, get, update, delete DNS zones + actions + RRSets
- Firewalls: List, create, get, update, delete firewalls + actions
- Floating IPs: List, create, get, update, delete floating IPs + actions
- Images: List, get, update, delete images + actions
- ISOs: List, get ISOs
- Load Balancers: List, create, get, update, delete load balancers + actions
- Load Balancer Types: List, get load balancer types
- Locations: List, get locations
- Networks: List, create, get, update, delete networks + actions
- Placement Groups: List, create, get, update, delete placement groups
- Primary IPs: List, create, get, update, delete primary IPs + actions
- Servers: List, create, get, update, delete servers + actions
- Server Types: List, get server types
- SSH Keys: List, create, get, update, delete SSH keys
- Volumes: List, create, get, update, delete volumes + actions
The package provides custom exceptions for better error handling:
use Boci\HetznerLaravel\Exceptions\ErrorException;
use Boci\HetznerLaravel\Exceptions\TransporterException;
try {
$response = $client->servers()->create($parameters);
} catch (ErrorException $e) {
// Handle API errors
echo "API Error: " . $e->getMessage();
echo "Error Code: " . $e->getCode();
} catch (TransporterException $e) {
// Handle network/transport errors
echo "Network Error: " . $e->getMessage();
}For more information about the Hetzner Cloud API, please refer to the following resources:
Please see CONTRIBUTING for details.
If you discover any security related issues, please email amar8eka@gmail.com instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.
list()- Get multiple actionsretrieve(string $actionId)- Get an action
list()- List certificatescreate(array $parameters)- Create a certificateretrieve(string $certificateId)- Get a certificateupdate(string $certificateId, array $parameters)- Update a certificatedelete(string $certificateId)- Delete a certificate
list()- List SSH keyscreate(array $parameters)- Create an SSH keyretrieve(string $sshKeyId)- Get an SSH keyupdate(string $sshKeyId, array $parameters)- Update an SSH keydelete(string $sshKeyId)- Delete an SSH key
list()- List DNS zonescreate(array $parameters)- Create a DNS zoneretrieve(string $zoneIdOrName)- Get a DNS zoneupdate(string $zoneIdOrName, array $parameters)- Update a DNS zonedelete(string $zoneIdOrName)- Delete a DNS zoneexport(string $zoneIdOrName)- Export zone fileimport(array $parameters)- Import zone fileactions()- Access zone actionsrrsets()- Access DNS records
list()- List locationsretrieve(string $locationId)- Get a location
list()- List firewallscreate(array $parameters)- Create a firewallretrieve(string $firewallId)- Get a firewallupdate(string $firewallId, array $parameters)- Update a firewalldelete(string $firewallId)- Delete a firewallactions()- Access firewall actions
list()- List floating IPscreate(array $parameters)- Create a floating IPretrieve(string $floatingIpId)- Get a floating IPupdate(string $floatingIpId, array $parameters)- Update a floating IPdelete(string $floatingIpId)- Delete a floating IPactions()- Access floating IP actions
list()- List serverscreate(array $parameters)- Create a serverretrieve(string $serverId)- Get a serverupdate(string $serverId, array $parameters)- Update a serverdelete(string $serverId)- Delete a servermetrics(string $serverId, array $parameters)- Get server metricsactions()- Access server actions
list()- List imagesretrieve(string $imageId)- Get an imageupdate(string $imageId, array $parameters)- Update an imagedelete(string $imageId)- Delete an imageactions()- Access image actions
list()- List ISOsretrieve(string $isoId)- Get an ISO
list()- List placement groupscreate(array $parameters)- Create a placement groupretrieve(string $placementGroupId)- Get a placement groupupdate(string $placementGroupId, array $parameters)- Update a placement groupdelete(string $placementGroupId)- Delete a placement group
list()- List primary IPscreate(array $parameters)- Create a primary IPretrieve(string $primaryIpId)- Get a primary IPupdate(string $primaryIpId, array $parameters)- Update a primary IPdelete(string $primaryIpId)- Delete a primary IPactions()- Access primary IP actions
list()- List server typesretrieve(string $serverTypeId)- Get a server type
list()- List load balancerscreate(array $parameters)- Create a load balancerretrieve(string $loadBalancerId)- Get a load balancerupdate(string $loadBalancerId, array $parameters)- Update a load balancerdelete(string $loadBalancerId)- Delete a load balancermetrics(string $loadBalancerId, array $parameters)- Get load balancer metricsactions()- Access load balancer actions
list()- List load balancer typesretrieve(string $loadBalancerTypeId)- Get a load balancer type
list()- List networkscreate(array $parameters)- Create a networkretrieve(string $networkId)- Get a networkupdate(string $networkId, array $parameters)- Update a networkdelete(string $networkId)- Delete a networkactions()- Access network actions
listPricing()- Get all prices
list()- List volumescreate(array $parameters)- Create a volumeretrieve(string $volumeId)- Get a volumeupdate(string $volumeId, array $parameters)- Update a volumedelete(string $volumeId)- Delete a volumeactions()- Access volume actions
This package provides complete coverage of the Hetzner Cloud API, ensuring you can manage all your cloud resources programmatically with ease.