boci / hetzner-laravel
A Laravel SDK for interacting with the Hetzner Cloud API - inspired by Nuno Maduro's OpenAI PHP client
Installs: 487
Dependents: 0
Suggesters: 0
Security: 0
Stars: 84
Watchers: 1
Forks: 1
Open Issues: 0
pkg:composer/boci/hetzner-laravel
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.10
- illuminate/support: ^12.0
- psr/http-client: ^1.0
- psr/http-message: ^2.0
Requires (Dev)
- laravel/pint: ^1.25
- orchestra/testbench: ^10.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0
README
โก๏ธ 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.
Features
- ๐ 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
Installation
You can install the package via composer:
composer require boci/hetzner-laravel
Configuration
Publish 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-here
Usage
Basic Usage
use 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;
Using the Facade
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();
Working with Images
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";
Working with Locations
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"; }
Working with Server Types
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"; }
Working with Networks
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();
Working with Load Balancers
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();
Working with DNS
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();
Meta Information
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;
Testing
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'; });
Testing with Exceptions
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');
Advanced Usage
Custom HTTP Client
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();
Dependency Injection
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()); } }
API Resources
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
Error Handling
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(); }
Documentation
For more information about the Hetzner Cloud API, please refer to the following resources:
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security related issues, please email amar8eka@gmail.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.
Quick Reference
๐ Actions
list()- Get multiple actionsretrieve(string $actionId)- Get an action
๐ Security
Certificates
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
SSH Keys
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
๐ DNS Zones
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
๐ Locations
list()- List locationsretrieve(string $locationId)- Get a location
๐ฅ Firewalls
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
๐ Floating IPs
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
๐ฅ๏ธ Servers
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
๐ผ๏ธ Images
list()- List imagesretrieve(string $imageId)- Get an imageupdate(string $imageId, array $parameters)- Update an imagedelete(string $imageId)- Delete an imageactions()- Access image actions
๐ฟ ISOs
list()- List ISOsretrieve(string $isoId)- Get an ISO
๐ฆ Placement Groups
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
๐ Primary IPs
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
โ๏ธ Server Types
list()- List server typesretrieve(string $serverTypeId)- Get a server type
โ๏ธ Load Balancers
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
โ๏ธ Load Balancer Types
list()- List load balancer typesretrieve(string $loadBalancerTypeId)- Get a load balancer type
๐ Networks
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
๐ฐ Billing
listPricing()- Get all prices
๐พ Volumes
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.