Dockhand Infrastructure
Manage infrastructure-as-code operations with Terraform for Hetzner Cloud resources. Enforces environment-based safety workflows.
Environment Safety Model
| Environment | Workflow | Direct Apply |
|---|---|---|
| prod | PR-first required | Blocked |
| test | Direct allowed | confirmed=true |
| global | PR-first required | Blocked |
Core Operations
Plan Changes
Preview infrastructure changes before applying:
code
terraform_plan environment="prod" → Shows diff of proposed changes → No state modification → Safe to run anytime
For all environments:
code
terraform_plan environment="global" terraform_plan environment="prod" terraform_plan environment="test"
Apply Changes
Test environment (direct allowed):
code
terraform_plan environment="test" → Review changes terraform_apply environment="test" confirmed=true → Applied directly
Production/Global (PR workflow):
- •Create feature branch
- •Make Terraform changes
- •Run
terraform_planto verify - •Create PR with plan output
- •Merge after review
- •Apply from main branch (CI/CD or manual)
View Current State
Inspect current Terraform state:
code
terraform_show environment="prod" → Current resource inventory → Useful for debugging drift
Collect Platform State
Capture full platform state for documentation:
code
collect_state environment="prod" → Docker services, containers, volumes → Outputs to state-snapshots/ → Commit to git for drift detection
Infrastructure Components
Global Resources (infra/terraform/global/)
- •Hetzner Cloud network (
platform-net) - •Subnets per environment
- •Firewalls (SSH, HTTP, HTTPS, internal)
- •Object storage buckets (backups, terraform state)
Per-Environment Resources (infra/terraform/envs/<env>/)
- •Server instances (CPX31, CCX13, etc.)
- •Volumes (data persistence)
- •Floating IPs (if configured)
- •Server-specific firewall attachments
Common Workflows
Add New Server
- •Create Terraform config in
infra/terraform/envs/new-server/ - •Define server, volume, network attachment
- •Run
terraform_plan environment="new-server" - •Create PR with plan
- •After merge,
terraform_apply environment="new-server" confirmed=true - •Bootstrap with
/dh:bootstrap
Resize Server
- •Update
server_typein Terraform - •Plan:
terraform_plan environment="<env>" - •Warning: May require server restart
- •Apply during maintenance window
Add Storage Volume
- •Add
hcloud_volumeresource - •Plan and review size/location
- •Apply
- •Mount on server via SSH
Bootstrap New Host
After Terraform provisions a server, bootstrap it:
code
/dh:bootstrap host=<new-host>
Bootstrap sequence:
- •SSH connectivity test
- •Install Docker
- •Join Docker Swarm (manager or worker)
- •Install Tailscale
- •Configure monitoring agents
- •Verify health
State Management
Terraform State
- •Stored in Cloudflare R2 (S3-compatible)
- •Backend configured per environment
- •State locking via DynamoDB-compatible
Platform State Snapshots
- •Generated by
collect_state - •Stored in
state-snapshots/in git - •Compare for drift detection:
code
diff state-snapshots/prod/latest.json state-snapshots/prod/previous.json
Integration with dh-guardrails
The dh-guardrails skill enforces:
- •No
terraform destroywithout explicit confirmation - •PR-first for production changes
- •Backup verification before destructive operations
Error Handling
| Error | Resolution |
|---|---|
| State lock | Check for running applies, force unlock if stuck |
| Provider auth | Verify HCLOUD_TOKEN in environment |
| Resource conflict | Import existing resource or rename |
| Plan drift | Run plan, review changes, decide to apply or update config |