lmrc-hetzner
Part of the LMRC Stack - Infrastructure-as-Code toolkit for building production-ready Rust applications
A comprehensive, production-ready async Hetzner Cloud API client with builders, validation, state management, and extensive error handling. Perfect for Infrastructure-as-Code (IaC) applications.
Features
Core Functionality
- 🔒 Type-safe builders with compile-time validation
- 📝 Comprehensive error handling with detailed error contexts
- ⚡ Async/await support with Tokio runtime
- ✅ Input validation for IP addresses, ports, names, and more
- 🎯 Zero unsafe code - completely safe Rust
Infrastructure-as-Code Features
- 📦 Full resource coverage - Servers, Networks, Firewalls, Load Balancers, SSH Keys, Volumes, Floating IPs
- 🔄 State persistence - Save and restore infrastructure state with JSON serialization
- 📊 Infrastructure diffing - Deep comparison of desired vs actual state
- 🔁 Automatic rollback - Automatically clean up on provisioning failures
- ♻️ Retry logic - Exponential backoff with configurable retry policies
- 🔧 Update operations - In-place updates for server resizing and firewall rule changes
- 🏗️ Hexagonal architecture - Clean separation of domain logic and infrastructure
Production Ready
- 🚀 Battle-tested - 57 comprehensive tests (36 unit + 21 doc tests)
- 📚 Extensive documentation - Detailed API docs and examples
- 🔐 Security-focused - Proper error handling and input validation
- ⚡ Performance-optimized - Async I/O with connection pooling
Installation
Add this to your Cargo.toml:
[]
= "0.1"
= { = "1.0", = ["full"] }
Quick Start
use ;
async
Examples
Creating a Server with Validation
use ServerSpec;
let server_spec = builder
.name
.server_type
.image
.location
.label
.ssh_key
.build?;
Creating a Network
use NetworkConfig;
let network = builder
.name
.ip_range
.zone
.build?;
Creating Firewall Rules
use ;
let rule = builder
.direction
.protocol
.port
.source_ip
.description
.build?;
let firewall = builder
.name
.rule
.build?;
Creating a Load Balancer
use ;
let service = builder
.protocol
.listen_port
.destination_port
.build?;
let lb = builder
.name
.lb_type
.health_check_protocol
.health_check_port
.health_check_path
.service
.build?;
Error Handling
use ;
match client..await
Validation
All builders perform validation before construction:
- Names: 1-63 characters, lowercase letters, numbers, hyphens, underscores
- IP addresses: Valid IPv4 addresses and CIDR notation
- Ports: Valid port numbers (1-65535) and port ranges
- Protocols: Valid network protocols (tcp, udp, icmp, esp, gre)
- Directions: Valid firewall directions (in, out)
Error Types
Comprehensive error handling with detailed contexts:
| Error | Description |
|---|---|
Http |
Network or connection issues |
Api |
Hetzner API error response |
NotFound |
Resource not found (404) |
AlreadyExists |
Resource already exists (409) |
InvalidParameter |
Invalid input parameter |
Validation |
Validation failed |
Timeout |
Operation timeout |
Unauthorized |
Authentication failed (401) |
Forbidden |
Permission denied (403) |
RateLimited |
Rate limit exceeded (429) |
ServerError |
Server error (5xx) |
InvalidToken |
Invalid API token format |
BuilderError |
Builder configuration error |
Builder Pattern
All configuration structs use the builder pattern:
// All builders have:
- .build // Validates and builds
- Default values where appropriate
- Fluent interface for chaining
API Coverage
- ✅ Servers (create, list, get, delete, resize, power on/off, attach to networks)
- ✅ Networks (create, list, get, delete, subnets)
- ✅ Firewalls (create, list, get, delete, update rules, apply to servers)
- ✅ Load Balancers (create, list, get, delete, services, targets, health checks)
- ✅ SSH Keys (create, list, get, delete)
- ✅ Volumes (create, list, get, delete, attach/detach, resize)
- ✅ Floating IPs (create, list, get, delete, assign/unassign, update)
- ✅ Actions (wait for completion with timeout)
Advanced Features
State Management
use StateManager;
// Save infrastructure state
let state_manager = new;
state_manager.save_state.await?;
// Load infrastructure state
let state = state_manager.load_state.await?;
// List all saved states
let states = state_manager.list_states.await?;
Infrastructure Diffing
use HetznerDiffer;
let differ = new;
let diff = differ.diff.await?;
// Check for changes
if diff.has_changes
Retry with Exponential Backoff
use ;
let config = new
.with_max_attempts
.with_initial_delay
.with_max_delay;
let result = retry_with_backoff.await?;
Infrastructure Provisioning with Rollback
use HetznerProvisioner;
use InfrastructureProvisioner;
let provisioner = new?;
// Provision infrastructure - automatically rolls back on failure
match provisioner.provision.await
Requirements
- Rust 1.70 or later
- Tokio runtime
License
Part of the LMRC Stack project. Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Disclaimer
This is an unofficial client for the Hetzner Cloud API and is not affiliated with or endorsed by Hetzner Online GmbH.