frostmoln_launch_template (Resource)
Manages a launch template for compute instances in the Frostmoln platform.
Authoritative scope — who owns what on this resource, declared in internal/scopedecl and machine-checked against the schema.
Enacted and reconciled — every configurable attribute not listed below: the platform applies it, and a refresh reads the truth back.
Not enacted state — user_data_wo: write-only: sent, never stored or read back — the user_data_wo_version companion carries change detection.
Observed, not enacted — tags_all: keys set outside Terraform — in the portal, by the fm CLI, or stamped by the platform — appear only here and are kept on every apply, never removed.
Example Usage
resource "frostmoln_launch_template" "web" {
name = "web-server-template"
flavor_id = data.frostmoln_flavor.medium.id
image_id = data.frostmoln_image.ubuntu.id
vpc_id = frostmoln_vpc.example.id
ssh_key_ids = [frostmoln_ssh_key.deploy.id]
security_group_ids = [frostmoln_security_group.web.id]
# Cloud-init as PLAIN TEXT. Base64 is accepted by the API, but do not use it here:
# instances launched from this template get SSH keys, 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, with nothing surfacing in
# Terraform to say so.
#
# cloud-init.yaml, alongside this configuration:
#
# #cloud-config
# package_update: true
# packages:
# - nginx
# runcmd:
# - [systemctl, enable, --now, nginx]
#
# That package step needs the launched instance's 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.
#
# Editing this updates the template; instances already launched from it keep the
# user data they were created with. Prefer user_data_wo (see the second block
# below) when the document carries anything secret: user_data is written to
# Terraform state in plaintext.
user_data = file("${path.module}/cloud-init.yaml")
metadata = {
role = "web"
}
tags = {
environment = "production"
}
}
# Prefer the write-only form when the document carries anything you would not
# want in the state file. user_data_wo never reaches the plan or state; it needs
# Terraform 1.11 or later. Because Terraform cannot see a write-only value
# change, bumping user_data_wo_version is what sends the current document — and
# unlike frostmoln_instance, that is an in-place update of the template.
resource "frostmoln_launch_template" "bootstrap" {
name = "worker-template"
flavor_id = data.frostmoln_flavor.medium.id
image_id = data.frostmoln_image.ubuntu.id
vpc_id = frostmoln_vpc.example.id
# The document is rendered from a template with a secret injected into it.
# Neither var.bootstrap_token nor the rendered document reaches state — which
# is the point: where a value is CONSUMED decides whether it is stored, so
# passing a secret through a variable into user_data would store it in full.
user_data_wo = templatefile("${path.module}/cloud-init.yaml.tftpl", {
bootstrap_token = var.bootstrap_token
})
# Bumping this sends the current document and updates the template in place.
# Instances already launched from it keep the user data they were created
# with. Do not derive it from the document: it is not sensitive, so it is
# printed verbatim in plan output, CI logs and PR plan comments.
user_data_wo_version = "1"
}Schema
Required
flavor_id(String) The flavor ID for instances launched from this template.image_id(String) The image ID for instances launched from this template.name(String) The name of the launch template.vpc_id(String) The VPC ID for instances launched from this template.
Optional
NOTE: Write-only arguments are supported in Terraform 1.11 and later.
metadata(Map of String) Key-value metadata for the launch template.security_group_ids(Set of String) The security group IDs to attach to instances launched from this template.ssh_key_ids(Set of String) The SSH key IDs to inject into instances launched from this template.tags(Map of String) Key-value tags for the launch template. Merged with the provider'sdefault_tagson every write (a key set here wins). Holds only the keys this configuration sets; the full set is intags_all.user_data(String, Sensitive) User data to provide to instances at launch — typically a cloud-init document. The platform returns the stored document on every read, but the provider does not decode it, so the value you configure is preserved from state on refresh and a change made outside Terraform is not detected. The document is written to Terraform state in plaintext, so anything embedded in it — credentials, tokens, private keys — is readable by anyone who can read the state;sensitiveredacts CLI output, not the state file. See the Secrets in Terraform state guide. Preferuser_data_wo, which carries the same document but is never written to state; the two are mutually exclusive.Write the document as plain text —
file("cloud-init.yaml"), notbase64encode(file(...)). Base64 is accepted by the API, but it must NOT be used when instances launched from this template also get SSH keys, a console password orinstance_access. In those cases the platform merges its own cloud-config into the document, and the merge dispatches on the literal#cloud-configprefix: 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 launch succeeds and nothing surfaces in Terraform, but the document never runs as cloud-config. Plain text is correct in both directions: a#cloud-configdocument is merged in place, and a#!script is combined as intended. See the example below.Changing this updates the template in place; instances already launched from it keep the user data they were created with. A cloud-init step that installs packages or calls an external endpoint needs the launched instance's VPC to have an outbound path — declare a
frostmoln_gatewayfor the VPC, or the step fails on first boot with no internet and no name resolution.user_data_wo(String, Sensitive, Write-only) User data to provide to instances at launch, as a write-only argument: the document reaches the provider on apply and is never written to the plan or to state, so anything embedded in it stays out of the state file. Requires Terraform 1.11 or later. Mutually exclusive withuser_data, anduser_data_wo_versionis required whenever this one is set. Everythinguser_datasays about the document itself applies here unchanged: write it as plain text rather thanbase64encode(...), and give the launched instance's VPC an outbound path if cloud-init reaches the network. One rule does NOT carry over: unlikeuser_data, an empty document is rejected here — omit the attribute for no user data. Terraform cannot see a write-only value, so it cannot detect a change to this document in either direction: changinguser_data_wo_versionis what makes the next apply send the current document, and it updates the template in place. Editing the document without touching the version does nothing.user_data_wo_version(String) Change tracker foruser_data_wo, required whenever that attribute is set. Any change to this value makes the next apply send the currentuser_data_woto the platform, updating the template in place; leaving it alone leaves the stored document untouched however much the write-only value changes. Instances already launched from the template keep the user data they were created with either way. Its content is arbitrary — a counter or a date is typical — and unlike the document it is stored in state, so do not derive it from the document or from anything in it: a digest of the document is a digest of whatever the document carries, and it is printed verbatim interraform planoutput.terraform importleaves this unset, so the first apply against an imported template sends the configured document again as a normal in-place update.
Read-Only
created_at(String) The timestamp when the launch template was created.id(String) The unique identifier of the launch template.tags_all(Map of String) Every tag the platform holds on this resource: the provider'sdefault_tags, this resource's owntags(which win on a shared key), and any key set outside Terraform — in the portal, by the fm CLI, or stamped by the platform. Keys set outside Terraform appear only here and are kept on every apply, never removed.updated_at(String) The timestamp when the launch template was last updated.