frostmoln_instance (Resource)
Manages a compute instance in the Frostmoln platform.
Example Usage
resource "frostmoln_instance" "example" {
name = "web-server-01"
flavor_id = data.frostmoln_flavor.medium.id
image_id = data.frostmoln_image.ubuntu.id
zone = "falkenberg"
vpc_id = frostmoln_vpc.example.id
subnet_id = frostmoln_subnet.example.id
security_groups = [frostmoln_security_group.web.id]
ssh_key_names = [frostmoln_ssh_key.example.name]
# Password for the default OS user, usable only at the VNC console (SSH stays key-only).
console_password = "change-me-at-the-console" # pragma: allowlist secret
# Install the Frostmoln in-guest agent at first boot for `fm ssh` terminal access.
instance_access = true
# Cloud-init as PLAIN TEXT. Base64 is accepted by the API, but do not use it here:
# this instance also sets ssh_key_names, console_password and instance_access, so the
# platform merges its own cloud-config into the document — and that merge dispatches
# on the literal #cloud-config prefix. A base64 blob does not carry it, so the blob
# would be treated as a shell script and the document below would never run. The
# apply still succeeds and the plan stays clean; the only evidence is in the guest's
# cloud-init log.
#
# Changing user_data REPLACES the instance, and the change-detection hash is taken
# over the value as written — so moving a live instance off base64encode(file(...))
# plans a replacement even though the document itself is unchanged.
#
# cloud-init.yaml, alongside this configuration:
#
# #cloud-config
# package_update: true
# packages:
# - nginx
# write_files:
# - path: /var/www/html/index.html
# content: |
# <h1>web-server-01</h1>
# runcmd:
# - [systemctl, enable, --now, nginx]
#
# That package step needs the VPC to have an outbound path. A VPC with no
# frostmoln_gateway has no internet and no platform DNS, and cloud-init fails on
# first boot with nothing in the Terraform plan to explain it.
user_data = file("${path.module}/cloud-init.yaml")
tags = {
role = "web"
environment = "production"
}
}Schema
Required
flavor_id(String) The flavor ID for the instance. Changing this triggers a resize workflow (stop, resize, start).image_id(String) The image ID to use for the instance.name(String) The name of the instance.
Optional
console_password(String, Sensitive) Password for the default OS user, usable only at the VNC console; SSH stays key-only. Changing forces replacement.instance_access(Boolean) Install the Frostmoln in-guest agent at first boot to enablefm sshterminal andfm forwardaccess to the instance (using a session also requires the tenant'sinstance-accessentitlement). Create-time only; the API does not return it, andterraform importleaves it unset — atrueconfig on an imported instance plans a replacement. Enabling or disabling the agent forces replacement; unset andfalseboth mean no agent, and switching between them does not.security_groups(Set of String) The security group IDs attached to the instance. Updated in place (replace semantics): changing the set replaces the instance's security groups across all its ports. Setting it to [] or removing the attribute clears ALL security groups (the instance falls back to default-drop — typically no inbound access). Out-of-band changes (made via the portal, CLI, or another client) are detected as drift on refresh when every port shares the same set; if ports hold differing sets, the configured value is preserved and a warning is emitted (edit per port instead).ssh_key_names(Set of String) The SSH key names to inject into the instance.subnet_id(String) The subnet ID for the instance.tags(Map of String) Key-value tags for the instance.user_data(String, Sensitive) User data to provide to the instance at launch — typically a cloud-init document. This is write-only; the API does not return it. A SHA256 hash is stored in state for change detection.
Write the document as plain text — file("cloud-init.yaml"), not base64encode(file(...)). Base64 is accepted by the API, but it must NOT be used on an instance that also sets ssh_key_names, console_password or instance_access. In those cases the platform merges its own cloud-config into the document, and the merge dispatches on the literal #cloud-config prefix: a base64 blob does not carry it, so the blob is treated as a shell script and combined alongside the platform's cloud-config instead of into it. The apply succeeds and the plan stays clean, but the document never runs as cloud-config and the only evidence is in the guest's cloud-init log. Plain text is correct in both directions: a #cloud-config document is merged in place, and a #! script is combined as intended. See the example below.
The hash is taken over the value AS WRITTEN in the configuration, and any change to user_data forces the instance to be REPLACED — so moving a live instance off base64encode(file(...)) onto file(...) plans a replacement even though the document itself is unchanged. Worth doing, but do it deliberately.
A cloud-init step that installs packages or calls an external endpoint also needs the instance's VPC to have an outbound path: declare a frostmoln_gateway for the VPC, or the step fails on first boot with no internet and no name resolution.
vpc_id(String) The VPC ID for the instance.zone(String) The availability zone for the instance. If omitted, the platform selects one and records it in state.
Read-Only
created_at(String) The timestamp when the instance was created.flavor_name(String) The name of the instance flavor.id(String) The unique identifier of the instance.image_name(String) The name of the image used to create the instance.private_ip(String) The private IP address of the instance.public_ip(String) The public IP address of the instance, if assigned.status(String) The current status of the instance.user_data_hash(String) SHA256 hash of the user data, used for change detection.