Terraform module for managing SSH keys in Hetzner Cloud with optional automated key pair generation.
- Automated Key Generation: Creates ED25519, RSA, or ECDSA key pairs using Terraform's TLS provider
- Automatic Local Save: Optionally save generated keys to local files with intuitive naming
- Bring Your Own Key: Upload existing public keys to Hetzner Cloud
- Reuse Existing Keys: Reference keys already in Hetzner Cloud by ID or name
- Secure Outputs: Private keys are marked as sensitive
- Flexible Labels: Organize keys with custom labels
ED25519 is the recommended algorithm for new keys - it's fast, secure, and has small key sizes.
module "ssh_key_ed25519" { source = "danylomikula/ssh-key/hcloud" create_key = true name = "production-key" algorithm = "ED25519" # Automatically save keys to local files save_private_key_locally = true local_key_directory = "~/.ssh" # Saves as ~/.ssh/production-key.key and ~/.ssh/production-key.pub labels = { environment = "production" managed_by = "terraform" } } # Use the saved key immediately output "ssh_command" { value = "ssh -i ${module.ssh_key_ed25519.private_key_file_path} root@server-ip" }RSA keys offer wider compatibility with older systems.
module "ssh_key_rsa" { source = "danylomikula/ssh-key/hcloud" create_key = true name = "legacy-system-key" algorithm = "RSA" rsa_bits = 4096 # 4096 bits for enhanced security save_private_key_locally = true local_key_directory = "./keys" labels = { purpose = "legacy-systems" managed_by = "terraform" } }ECDSA provides a balance between security and performance.
module "ssh_key_ecdsa" { source = "danylomikula/ssh-key/hcloud" create_key = true name = "ecdsa-key" algorithm = "ECDSA" ecdsa_curve = "P384" # Options: P224, P256, P384, P521 save_private_key_locally = true local_key_directory = "./keys" labels = { algorithm = "ecdsa" managed_by = "terraform" } }If you already have SSH keys generated outside Terraform, you can upload just the public key.
module "ssh_key_existing" { source = "danylomikula/ssh-key/hcloud" create_key = true name = "my-existing-key" public_key = file("~/.ssh/id_ed25519.pub") labels = { source = "external" managed_by = "terraform" } }# Upload team member keys module "ssh_keys_team" { source = "danylomikula/ssh-key/hcloud" for_each = { alice = "~/.ssh/team/alice.pub" bob = "~/.ssh/team/bob.pub" carol = "~/.ssh/team/carol.pub" } create_key = true name = "team-${each.key}" public_key = file(each.value) labels = { team = "devops" member = each.key managed_by = "terraform" } }Use case: You already have SSH keys in Hetzner Cloud and want to reference them in Terraform without recreating.
Why use this:
- Keys created manually through Hetzner Console
- Keys shared across multiple Terraform projects
- Avoid recreating keys that are already in use on servers
- Integrate existing infrastructure into Terraform management
module "ssh_key_reference" { source = "danylomikula/ssh-key/hcloud" create_key = false existing_key_name = "my-existing-key" } # Use in server module module "server" { source = "danylomikula/server/hcloud" servers = { web = { server_type = "cx23" location = "nbg1" ssh_keys = [module.ssh_key_reference.ssh_key_id] } } }module "ssh_key_by_id" { source = "danylomikula/ssh-key/hcloud" create_key = false existing_key_id = 12345678 }module "ssh_key" { source = "danylomikula/ssh-key/hcloud" create_key = true name = "web-server-key" algorithm = "ED25519" save_private_key_locally = true local_key_directory = "./keys" } resource "hcloud_server" "web" { name = "web-server" server_type = "cx22" location = "nbg1" image = "ubuntu-24.04" ssh_keys = [module.ssh_key.ssh_key_name] } output "ssh_command" { value = "ssh -i ${module.ssh_key.private_key_file_path} root@${hcloud_server.web.ipv4_address}" }| Directory | Description |
|---|---|
| basic | Generate new ED25519 key pair with automatic local save |
| upload-existing | Upload an existing public key to Hetzner Cloud |
| reference-existing | Reference existing Hetzner Cloud keys by name or ID without recreating |
| multiple-algorithms | Generate and compare ED25519, RSA, and ECDSA keys |
| team-keys | Manage multiple team member SSH keys with for_each and labels |
| Algorithm | Security | Performance | Compatibility | Recommended Use |
|---|---|---|---|---|
| ED25519 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | Modern systems (default) |
| RSA 4096 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Legacy systems |
| ECDSA P384 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | Balanced approach |
Recommendation: Use ED25519 unless you need compatibility with older systems that don't support it.
- State Security: Private keys are marked as
sensitive = truein Terraform outputs - State Encryption: Always enable Terraform state encryption (S3 with KMS, Terraform Cloud, etc.)
- Secret Management: Consider external secret management solutions (HashiCorp Vault, AWS Secrets Manager)
- Key Rotation: Rotate SSH keys regularly according to your security policy
- File Permissions: Generated key files are created with 0600 permissions automatically
- Gitignore: Add
*.keyand*.pubto.gitignoreto prevent accidental commits - Backup: Securely backup private keys before destroying Terraform state
- Generate keys in Terraform rather than uploading for full lifecycle management
- Save keys locally during initial provisioning, then store securely in a vault
- Use labels to organize keys by environment, team, or purpose
- Reference existing keys when sharing across multiple projects
- Use ED25519 for new deployments unless compatibility is a concern
| Name | Version |
|---|---|
| terraform | >= 1.12.0 |
| hcloud | >= 1.45.0 |
| local | >= 2.4.0 |
| tls | >= 4.0.0 |
| Name | Version |
|---|---|
| hcloud | >= 1.45.0 |
| local | >= 2.4.0 |
| tls | >= 4.0.0 |
No modules.
| Name | Type |
|---|---|
| hcloud_ssh_key.this | resource |
| local_file.public_key | resource |
| local_sensitive_file.private_key | resource |
| tls_private_key.this | resource |
| hcloud_ssh_key.existing_by_id | data source |
| hcloud_ssh_key.existing_by_name | data source |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| algorithm | Algorithm for generated key. Used only when public_key is null. Options: RSA, ECDSA, ED25519. | string | "ED25519" | no |
| create_key | Whether to create a new SSH key or reference an existing one. | bool | true | no |
| ecdsa_curve | ECDSA curve for key generation. Options: P224, P256, P384, P521. | string | "P384" | no |
| existing_key_id | ID of an existing SSH key to reference when create_key is false. | number | null | no |
| existing_key_name | Name of an existing SSH key to reference when create_key is false. | string | null | no |
| labels | Labels to apply to the SSH key. | map(string) | {} | no |
| local_key_directory | Directory where to save the private key file. Files will be named {name}.key and {name}.pub. | string | "." | no |
| name | Name for the SSH key in Hetzner Cloud. | string | null | no |
| public_key | Public key content in OpenSSH format. If null and create_key is true, a new key pair will be generated. | string | null | no |
| rsa_bits | Number of bits for RSA key generation. Minimum 2048, recommended 4096. | number | 4096 | no |
| save_private_key_locally | Whether to save the generated private key to a local file. Only works when create_key is true and public_key is null. | bool | false | no |
| Name | Description |
|---|---|
| private_key_file_path | Path to the saved private key file. Only available when save_private_key_locally is true. |
| private_key_openssh | Private key in OpenSSH format. Only available when key was generated by this module. |
| private_key_pem | Private key in PEM format. Only available when key was generated by this module. |
| public_key_file_path | Path to the saved public key file. Only available when save_private_key_locally is true. |
| public_key_openssh | Public key in OpenSSH format. |
| ssh_key_fingerprint | Fingerprint of the SSH key. |
| ssh_key_id | ID of the Hetzner Cloud SSH key. |
| ssh_key_labels | Labels applied to the SSH key. |
| ssh_key_name | Name of the SSH key. |
| Module | Description | GitHub | Terraform Registry |
|---|---|---|---|
| terraform-hcloud-network | Manage Hetzner Cloud networks and subnets | GitHub | Registry |
| terraform-hcloud-firewall | Manage Hetzner Cloud firewalls | GitHub | Registry |
| terraform-hcloud-server | Manage Hetzner Cloud servers | GitHub | Registry |
Module managed by Danylo Mikula.
Contributions are welcome! Please read the Contributing Guide for details on the process and commit conventions.
Apache 2.0 Licensed. See LICENSE for full details.