State Management
Carina uses a state file to track which resources it manages and their current attributes. This guide covers how to configure state storage, manipulate state entries, and share state between projects.
How state works
When you run carina apply, Carina records each managed resource and its attributes in a state file. On subsequent runs, it compares the desired state (your .crn files) with the recorded state to determine what needs to change.
By default, state is stored locally as carina.state.json. For team usage, configure a remote S3 backend.
Configuring the S3 backend
Add a backend block to your .crn file:
backend s3 { bucket = 'my-carina-state' key = 'production/carina.state.json' region = 'ap-northeast-1'}
provider awscc { region = awscc.Region.ap_northeast_1}
awscc.ec2.vpc { cidr_block = '10.0.0.0/16'
tags = { Name = 'my-vpc' }}The S3 backend stores state in the specified bucket and key. It also supports state locking to prevent concurrent modifications.
Automatic bucket creation
By default, carina apply automatically creates the S3 bucket if it doesn’t exist. This lets you get started without any manual setup:
backend s3 { bucket = 'my-carina-state' key = 'production/carina.state.json' region = 'ap-northeast-1' auto_create = true # This is the default; can be omitted}When the bucket is auto-created, Carina:
- Creates the S3 bucket with versioning enabled and public access blocked
- Appends an
aws.s3.bucketresource definition to your.crnfile - Registers the bucket as a protected resource in state, preventing it from being accidentally modified or destroyed
carina plan shows the upcoming bucket creation as a bootstrap plan before the main resource plan.
To disable auto-creation and require the bucket to exist beforehand, set auto_create = false. If the bucket is missing, carina plan and carina apply will fail with an error.
To delete an auto-created state bucket, use:
carina state bucket-delete <bucket-name> --forceThis is a destructive operation that removes the bucket and all state history.
Importing existing resources
To bring an existing cloud resource under Carina management, use the import block:
import { to = awscc.ec2.vpc 'my-vpc' id = 'vpc-0abc123def456'}
awscc.ec2.vpc { cidr_block = '10.0.0.0/16'
tags = { Name = 'my-vpc' }}tospecifies the resource type and the name Carina will use in stateidis the cloud provider’s identifier for the existing resource
Run carina plan to verify the import matches the resource definition, then carina apply to record it in state.
Moving resources in state
When you rename a resource or reorganize your code, use the moved block to update the state without destroying and recreating the resource:
moved { from = awscc.ec2.vpc 'vpc' to = awscc.ec2.vpc 'main_vpc'}
awscc.ec2.vpc { cidr_block = '10.0.0.0/16'
tags = { Name = 'my-vpc' }}After the move is applied, you can remove the moved block from your code.
Removing resources from state
To stop managing a resource without destroying it in the cloud, use the removed block:
removed { from = awscc.ec2.vpc 'main_vpc'}This removes the resource from Carina’s state but leaves the actual cloud resource untouched. This is useful when transferring ownership of a resource to another tool or project.
Referencing remote state
To read outputs from another Carina project’s state, use remote_state:
let network = remote_state { path = 'network.state.json'}
awscc.ec2.security_group { group_description = 'Web security group' vpc_id = network.vpc.vpc_id
tags = { Name = 'web-sg' }}The remote_state block loads another project’s state file and makes its resource attributes available through the binding. In this example, network.vpc.vpc_id references the vpc_id attribute of the vpc resource from the network project’s state.
You can also specify the backend type explicitly:
let network = remote_state 's3' { bucket = 'carina-state' key = 'network/carina.state.json' region = 'ap-northeast-1'}State CLI commands
Carina provides several CLI commands for inspecting and managing state:
# List all managed resourcescarina state list
# Show all resources with full attributescarina state show
# Look up a specific resource or attributecarina state lookup vpccarina state lookup vpc.vpc_id
# Refresh state from cloud providerscarina state refresh
# Force unlock a stuck state lockcarina force-unlock <lock-id>
# Delete a state bucket (destructive)carina state bucket-delete <bucket-name> --forceState locking
When using the S3 backend, Carina automatically locks state during apply and destroy operations to prevent concurrent modifications. If a lock gets stuck (for example, after a crash), use carina force-unlock to release it.
You can disable locking with the --lock=false flag:
carina apply --lock=false