sshhostkeycache
sshhostkeycache captures a host's SSH key during terraform apply and reuses the cached result during later terraform plan runs.
This avoids doing network-dependent SSH key discovery at plan time, which can make plans noisy or flaky. Especially if the vm employs anti-recon protections like fail2ban.
Requires OpenSSH client tools (ssh, ssh-keyscan) available in PATH on the machine running Terraform.
How it works
sshhostkeycache_entry scans the target host:
- on resource create
- when
refresh_key changes
It does not rescan during normal Read or plan behavior. Instead, it reuses the previously captured result.
Use refresh_key as the signal that the machine should be treated as new. Good choices include:
- instance ID
- VM replacement trigger
- image or build version
- a manually bumped value
Example
terraform {
required_providers {
sshhostkeycache = {
source = "linode/sshhostkeycache"
version = ">= 0.1.9"
}
linode = {
source = "linode/linode"
}
}
}
variable "linode_root_pass" {
type = string
sensitive = true
}
resource "linode_instance" "vm" {
label = "example-vm"
region = "us-east"
type = "g6-standard-1"
image = "linode/ubuntu24.04"
root_pass = var.linode_root_pass
}
resource "sshhostkeycache_entry" "vm" {
host = linode_instance.vm.ip_address
port = 22
types = "ed25519,ecdsa,rsa"
refresh_key = tostring(linode_instance.vm.id)
}
output "host_key" {
value = sshhostkeycache_entry.vm.host_key
}
output "known_hosts_line" {
value = sshhostkeycache_entry.vm.known_hosts_line
}
Choosing key types
types is a comma-separated preference list, for example:
types = "ed25519,ecdsa,rsa"
The provider selects the first available matching key type from the cached scan result.
Changing types does not force a new scan by itself. It only changes which cached key is selected.
If you need a fresh probe of the host, change refresh_key.
Argument Reference
Required
host (String) — Target host to scan.
refresh_key (String) — Controls when a new scan happens. Changing this forces replacement and a fresh scan.
Optional
port (Number) — SSH port. Defaults to 22.
types (String) — Comma-separated preferred key types. Defaults to "ecdsa".
retries (Number) — Number of scan attempts before giving up. Defaults to 60.
sleep_secs (Number) — Delay between retries in seconds. Defaults to 5.
timeout_secs (Number) — Per-attempt timeout for ssh-keyscan. Defaults to 5.
Optional bastion block
Use this when the target is only reachable through a bastion host.
host (String) — Bastion hostname or IP.
port (Number) — Bastion SSH port. Defaults to 22.
user (String) — SSH username for the bastion.
private_key (String, Sensitive) — Private key used to connect to the bastion.
known_host (String) — Optional bastion known_hosts line. If omitted, bastion host key checking is disabled.
Attribute Reference
id (String) — Resource ID in host:port form.
host_key (String) — Selected host key in keytype base64 form.
known_hosts_line (String) — Full selected known_hosts line.
Behavior
- A scan happens on:
- create
- replacement caused by changing
refresh_key
- A scan does not happen on:
- If
types changes and cached scan results are available, the provider reselects from the cached keys without rescanning.
- If
types changes and no cache is available, update fails and you must change refresh_key to force a new scan.
Key Type Selection
types is a comma-separated preference list, for example:
types = "ed25519,ecdsa,rsa"
The provider selects the first available matching key from the cached scan result.
Aliases supported in types include:
ecdsa → matches available ECDSA variants
ed25519 → matches ssh-ed25519
rsa → matches ssh-rsa
dsa → matches ssh-dss