frostmoln_gateway (Resource)
Manages a VPC's outbound internet path. A VPC has at most one gateway; a VPC without one is an isolated network with no inbound and no outbound connectivity. Removing this gateway, or changing its mode, takes the VPC's outbound internet path down — and with it platform DNS resolution and managed-service connectivity, which are reached over routes that exist only while the gateway does. Instances in the VPC lose name resolution, not just internet access.
Example Usage
# A VPC's outbound internet path. A VPC has at most one gateway; without
# one it is an isolated network — no inbound, no outbound, and (because they are
# reached over the same path) no platform DNS resolution and no managed-service
# connectivity either. That is how "no connectivity" is expressed: this resource
# simply not declared. There is no "none" mode.
#
# "public_ip" is the only mode a configuration can set. The VPC gets its own
# outbound gateway, and instances in it can still have public IPs of their own.
#
# Note the spelling: Terraform takes the wire value "public_ip". The fm CLI also
# accepts the hyphenated "public-ip", so a value copied from a CLI command has
# to be rewritten with the underscore here.
#
# With no public_ip_id the platform draws the gateway an address itself. That
# address is NOT a public IP of yours — it has no id, it is not in your public
# IP list, it draws on none of your public IP quota, and nothing pins it, so it
# may change if the gateway is rebuilt. It is the right default when nothing
# outside the VPC needs to know what its traffic comes from.
resource "frostmoln_gateway" "example" {
vpc_id = frostmoln_vpc.example.id
mode = "public_ip"
}
resource "frostmoln_public_ip" "egress" {
lifecycle {
prevent_destroy = true
}
}
resource "frostmoln_gateway" "chosen_address" {
vpc_id = frostmoln_vpc.dns_published.id
mode = "public_ip"
public_ip_id = frostmoln_public_ip.egress.id
}
# Terraform derives the ordering from that reference: the address is allocated
# before the gateway that egresses from it, and on teardown the gateway is
# changed or destroyed BEFORE the address is released.
#
# That ordering is correct AND it is why the address needs its own guard. Once
# the gateway is gone the platform has already handed the address back as an
# ordinary unattached address, so the release that follows looks — to the
# platform — like the release of something idle, and it succeeds. The provider
# refuses it from the recorded attachment instead, and asks for
# `acknowledge_address_loss = true` on the frostmoln_public_ip before it will
# give a VPC's outbound source address up.
#
# Look up an address that already exists — one already published in DNS, or
# already sitting in a partner's allow-list — instead of allocating a new one:
#
# data "frostmoln_public_ip" "published" {
# address = "203.0.113.10"
# }
#
# resource "frostmoln_gateway" "reuse" {
# vpc_id = frostmoln_vpc.dns_published.id
# mode = "public_ip"
# public_ip_id = data.frostmoln_public_ip.published.id
# }
# Removing this gateway, or changing its mode, takes the VPC's internet, DNS and
# managed-service connectivity down, so both are refused unless the intent is
# stated in the configuration:
#
# acknowledge_connectivity_loss = true
#
# Add that line, `terraform apply` it, and only then destroy the resource or
# change its mode — then REMOVE THE LINE AGAIN. It is ordinary configuration, so
# leaving it in place keeps the resource permanently disarmed for the rest of
# its life: a later `terraform destroy -target`, a module removal, or a `vpc_id`
# change that forces replacement would then disconnect the VPC with nothing in
# the plan beyond an ordinary "will be destroyed" line.
# An ATTACHED public IP cannot exist without a gateway, so put the dependency on
# the resource that makes the ATTACHMENT, pointing at the gateway. Terraform then
# creates the gateway first and destroys the attachments first (the gateway
# cannot be removed while they still depend on it — GATEWAY_IN_USE).
#
# The create order matters as much as the destroy order: attaching an address
# into a VPC with no gateway makes the platform attach one itself, after which an
# explicit gateway that pins a public_ip_id collides with it (GATEWAY_EXISTS) and
# one that pins none does NOT fail — it silently adopts the platform's gateway,
# and the VPC egresses from an address nobody chose.
#
# Below is the frostmoln_public_ip itself, because its own instance_id is what
# attaches the address. Wherever something ELSE attaches it, the depends_on goes
# on that resource instead: a frostmoln_public_ip_association, a public-scheme
# frostmoln_load_balancer, a frostmoln_kubernetes_cluster whose API endpoint
# takes a public address, a frostmoln_nginx_instance or
# frostmoln_apache_instance with public = true.
# The attachment is what depends on the gateway, not the allocation — and the
# address does not have to be one you named, since the platform allocates its own
# for most of those and it holds the gateway open just the same.
# Never put it on frostmoln_public_ip.egress above: the gateway already refers to
# that address, so a dependency back the other way is a plan-time Cycle error.
resource "frostmoln_public_ip" "example" {
instance_id = frostmoln_instance.example.id
depends_on = [frostmoln_gateway.example]
}
# The address outbound traffic appears to come from. Null while the gateway is
# detached or the address is not yet known. This is the value to give a partner
# for their allow-list.
output "egress_source_address" {
value = frostmoln_gateway.chosen_address.source_address
}Schema
Required
mode(String) How outbound traffic is addressed."public_ip"is the only value a configuration can set: the VPC gets its own outbound gateway as its outbound path. Leavepublic_ip_idout and the platform draws the gateway an address of its own — not a public IP of yours, and not pinned; name one and the VPC egresses from an address of your own, which is what a partner allow-list entry or a DNS record needs.
There is no default and no third value. A VPC with NO gateway — this resource simply not declared — is an isolated network, and that is how "no connectivity" is expressed: connectivity is a stated choice, never one a VPC acquires because a field was omitted.
Terraform uses the wire spelling public_ip. The fm CLI additionally accepts the hyphenated public-ip and normalises it, so a value copied from a CLI command has to be written with the underscore here.
Changing the mode is applied IN PLACE, never as a destroy/create — a replacement would drop the recorded source address and leave the VPC with no internet, no DNS and no managed-service connectivity in between. It still re-addresses the VPC's outbound path and drops in-flight connections, so it requires acknowledge_connectivity_loss = true, and source_address is planned as "(known after apply)" because the platform re-records it.
vpc_id(String) The VPC this gateway serves. Changing it replaces the resource — and the replacement destroys this gateway first, which is refused unlessacknowledge_connectivity_loss = trueis already in the configuration. Set it, apply, and only then changevpc_id.
Optional
acknowledge_connectivity_loss(Boolean) Set to true to allow this gateway to be removed, or itsmodeorpublic_ip_idto be changed. Removing this gateway, or changing its mode, takes the VPC's outbound internet path down — and with it platform DNS resolution and managed-service connectivity, which are reached over routes that exist only while the gateway does. Instances in the VPC lose name resolution, not just internet access.
The API refuses the removal and the mode change without the acknowledgement, so this provider refuses them too — before any request is sent — rather than supplying the flag on the practitioner's behalf. It applies the same rule to a public_ip_id change, which re-addresses the VPC's outbound path just as visibly. Set it to true and apply, then destroy or change the mode. Leaving it unset (the default) makes terraform destroy fail on this resource instead of silently disconnecting the VPC.
Remove it from the configuration again once the removal or mode change is done, and do not leave it set on a steady-state resource. It is ordinary configuration, so a true left behind stays in state for the life of the resource and permanently disarms this control: a later terraform destroy -target, a module removal, or a vpc_id change that forces replacement then disconnects the VPC with nothing in the plan beyond an ordinary "will be destroyed" line.
public_ip_id(String) Undermode = "public_ip", the public IP (frostmoln_public_ip) this VPC's outbound traffic leaves from. Naming one is what makes the address STABLE: it is a resource of your tenant's, so it survives this gateway being rebuilt, the VPC being recreated, and the address being handed to a partner to allow-list or published in DNS.
Omit it and the platform draws the gateway an address itself. That address is NOT a public IP of yours: it has no id, it does not appear in your public IP list, it draws on none of your public IP quota, and nothing pins it — it may change if the gateway is rebuilt. It is the right default for a VPC whose source address nobody outside it needs to know, and this attribute stays null there because there is no public IP for the platform to name.
Naming an address is the option you take when something outside the VPC DOES need to know it. The address is then a resource of your tenant's — listed, and counted against your public IP quota like any other — and it is pinned as this gateway's source address.
Changing it is applied IN PLACE, never as a destroy/create: the platform re-addresses the existing gateway rather than tearing the VPC's only outbound path down and building a new one. It still changes the address the VPC's traffic arrives from, so it requires acknowledge_connectivity_loss = true exactly as a mode change does.
REMOVING this attribute from the configuration does not release the address, and does not hand the gateway back to a platform-drawn one. The attribute is Computed as well as Optional, so an absent value resolves to the id already in state: there is no diff, no request is sent, and the gateway goes on egressing from the address you named. The API reads an absent publicIpId the same way — as "keep the address this gateway has" — so there is no way back to a platform-drawn address once one is named. To move the gateway to a different address, name the different address.
The public IP must belong to this tenant and must not be attached to anything else. A public IP that is in use by an instance is refused, and so is one already serving another VPC's outbound path.
Read-Only
id(String) The gateway's identifier. It survives a mode change, so it is stable for the life of the gateway. For a gateway with no stored record (origin= "legacy") the API answers under the VPC's id instead.origin(String) Who asked for the gateway: "explicit" (a client created it directly), "explicit_public_ip" (a client created it and named the public IP it egresses from, viapublic_ip_id), "implicit_public_ip" (the platform attached it because a public IP was associated, which requires a gateway), "vpc_create" (it came with the VPC because a mode was chosen at VPC create), or "legacy" — which means NO STORED RECORD EXISTS, so the provenance is UNKNOWN. "legacy" usually means the VPC predates this resource, but the record write is deliberately non-fatal, so a gateway created minutes ago can report it too. Read it as "unknown", never as "old".source_address(String) The public IPv4 address outbound traffic appears to come from. Null while the gateway is detached or the address is not yet known. It is dedicated to this VPC — no other VPC egresses from it — but dedicated is not the same as STABLE. Wherepublic_ip_idnames an address, this IS that address and it is pinned. Where it does not, this is the address the platform drew for the gateway: nothing pins it, so it may change if the gateway is rebuilt, and it is not an address to publish or hand a partner to allow-list. Amodeorpublic_ip_idchange re-records it, so it plans as "(known after apply)" then and keeps its recorded value otherwise.status(String) Observed state of the gateway, read from the cloud rather than from stored desired state: "active" or "detached". It is not configurable — Terraform records whatever the platform reports and produces no plan of its own from it. "detached" is not on its own a verdict that something is broken or that an operator is needed: what the platform observes depends on how the mode is realised. Read it as a prompt to check the VPC's outbound path, not as proof that the platform and the cloud disagree.
Import
Import is supported using the following syntax:
The terraform import command can be used, for example:
# Import an existing gateway. The resource is one-to-one with a VPC, so
# either identifier works: the gateway's own id, or the id of the VPC it serves.
# (A gateway with no stored record — origin "legacy" — is only addressable by
# its VPC id.)
terraform import frostmoln_gateway.example vpc-abc123
# After importing, set acknowledge_connectivity_loss = true in the configuration
# before you can change the gateway's mode or destroy it: an imported gateway is
# never pre-acknowledged.