- OpenTofu Settings
 - Backends
 - s3
 
Backend Type: s3
Stores the state as a given key in a given bucket on
Amazon S3.
This backend also supports state locking and consistency checking via
Dynamo DB, which can be enabled by setting
the dynamodb_table field to an existing DynamoDB table name.
A single DynamoDB table can be used to lock multiple remote state files. OpenTofu generates key names that include the values of the bucket and key variables.
It is highly recommended that you enable Bucket Versioning on the S3 bucket to allow for state recovery in the case of accidental deletions and human error.
Example Configuration
terraform {
  backend "s3" {
    bucket = "mybucket"
    key    = "path/to/my/key"
    region = "us-east-1"
  }
}
This assumes we have a bucket created called mybucket. The
OpenTofu state is written to the key path/to/my/key.
Note that for the access credentials we recommend using a partial configuration.
S3 Bucket Permissions
OpenTofu will need the following AWS IAM permissions on the target backend bucket:
s3:ListBucketonarn:aws:s3:::mybuckets3:GetObjectonarn:aws:s3:::mybucket/path/to/my/keys3:PutObjectonarn:aws:s3:::mybucket/path/to/my/keys3:DeleteObjectonarn:aws:s3:::mybucket/path/to/my/key
This is seen in the following AWS IAM Statement:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::mybucket"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": "arn:aws:s3:::mybucket/path/to/my/key"
    }
  ]
}
AWS can control access to S3 buckets with either IAM policies
attached to users/groups/roles (like the example above) or resource policies
attached to bucket objects (which look similar but also require a Principal to
indicate which entity has those permissions). For more details, see Amazon's
documentation about
S3 access control.
DynamoDB Table Permissions
If you are using state locking, OpenTofu will need the following AWS IAM
permissions on the DynamoDB table (arn:aws:dynamodb:::table/mytable):
dynamodb:DescribeTabledynamodb:GetItemdynamodb:PutItemdynamodb:DeleteItem
This is seen in the following AWS IAM Statement:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:DescribeTable",
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:DeleteItem"
      ],
      "Resource": "arn:aws:dynamodb:*:*:table/mytable"
    }
  ]
}
Data Source Configuration
To make use of the S3 remote state in another configuration, use the
terraform_remote_state data source.
data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "tofu-state-prod"
    key    = "network/terraform.tfstate"
    region = "us-east-1"
  }
}
The terraform_remote_state data source will return all of the root module
outputs defined in the referenced remote state (but not any outputs from
nested modules unless they are explicitly output again in the root). An
example output might look like:
data.terraform_remote_state.network:
  id = 2016-10-29 01:57:59.780010914 +0000 UTC
  addresses.# = 2
  addresses.0 = 52.207.220.222
  addresses.1 = 54.196.78.166
  backend = s3
  config.% = 3
  config.bucket = tofu-state-prod
  config.key = network/terraform.tfstate
  config.region = us-east-1
  elb_address = web-elb-790251200.us-east-1.elb.amazonaws.com
  public_subnet_id = subnet-1e05dd33
Configuration
This backend requires the configuration of the AWS Region and S3 state storage. Other configuration, such as enabling DynamoDB state locking, is optional.
Credentials and Shared Configuration
We recommend using environment variables to supply credentials and other sensitive data. If you use -backend-config or hardcode these values directly in your configuration, OpenTofu will include these values in both the .terraform subdirectory and in plan files. Refer to Credentials and Sensitive Data for details.
The following configuration is required:
region- (Required) AWS Region of the S3 Bucket and DynamoDB Table (if used). This can also be sourced from theAWS_DEFAULT_REGIONandAWS_REGIONenvironment variables.
The following configuration is optional:
access_key- (Optional) AWS access key. If configured, must also configuresecret_key. This can also be sourced from theAWS_ACCESS_KEY_IDenvironment variable, AWS shared credentials file (e.g.~/.aws/credentials), or AWS shared configuration file (e.g.~/.aws/config).secret_key- (Optional) AWS access key. If configured, must also configureaccess_key. This can also be sourced from theAWS_SECRET_ACCESS_KEYenvironment variable, AWS shared credentials file (e.g.~/.aws/credentials), or AWS shared configuration file (e.g.~/.aws/config).iam_endpoint- (Optional) Deprecated Custom endpoint for the AWS Identity and Access Management (IAM) API. This can also be sourced from theAWS_IAM_ENDPOINTenvironment variable.max_retries- (Optional) The maximum number of times an AWS API request is retried on retryable failure. Defaults to 5.retry_mode- (Optional) Specifies how retries are attempted. Valid values arestandardandadaptive. This can also be sourced from theAWS_RETRY_MODEenvironment variable.profile- (Optional) Name of AWS profile in AWS shared credentials file (e.g.~/.aws/credentials) or AWS shared configuration file (e.g.~/.aws/config) to use for credentials and/or configuration. This can also be sourced from theAWS_PROFILEenvironment variable.shared_credentials_file- (Optional) Deprecated Path to the AWS shared credentials file. Defaults to~/.aws/credentials.shared_credentials_files- (Optional) List of paths to AWS shared credentials files. Defaults to~/.aws/credentials. This can also be sourced from theAWS_SHARED_CREDENTIALS_FILEenvironment variable.shared_config_files- (Optional) List of paths to AWS shared configuration files. Defaults to~/.aws/config. This can also be sourced from theAWS_SHARED_CONFIG_FILEenvironment variable.skip_s3_checksum- (Optional) Do not include checksum in the input when uploading S3 Objects. Useful for non AWS S3 APIs which do not support checksum validation.skip_credentials_validation- (Optional) Skip credentials validation via the STS API.skip_region_validation- (Optional) Skip validation of provided region name.skip_metadata_api_check- (Optional) Skip usage of EC2 Metadata API.skip_requesting_account_id- (Optional) Skip requesting the account ID. Useful for AWS API implementations that do not have the IAM, STS API, or metadata API.sts_endpoint- (Optional) Deprecated Custom endpoint for the AWS Security Token Service (STS) API. This can also be sourced from theAWS_STS_ENDPOINTenvironment variable.sts_region- (Optional) AWS region for STS. If unset, AWS will use the same region for STS as other non-STS operations.token- (Optional) Multi-Factor Authentication (MFA) token. This can also be sourced from theAWS_SESSION_TOKENenvironment variable.allowed_account_ids(Optional): A list of permitted AWS account IDs to safeguard against accidental disruption of a live environment. This option conflicts withforbidden_account_ids.forbidden_account_ids(Optional): A list of prohibited AWS account IDs to prevent unintentional disruption of a live environment. This option conflicts withallowed_account_ids.use_legacy_workflow- (Optional) Deprecated Prefer environment variables for legacy authentication; default is 'false'. This method doesn't match AWS CLI or SDK authentication and will be removed in the future.custom_ca_bundle- File containing custom root and intermediate certificates. Can also be configured using theAWS_CA_BUNDLEenvironment variable.ec2_metadata_service_endpoint- Address of the EC2 metadata service (IMDS) endpoint to use. This can also be sourced from theAWS_EC2_METADATA_SERVICE_ENDPOINTenvironment variable.ec2_metadata_service_endpoint_mode- Mode to use in communicating with the metadata service. Valid values areIPv4andIPv6. This can also be sourced from theAWS_EC2_METADATA_SERVICE_ENDPOINT_MODEenvironment variable.http_proxy- (Optional) The address of an HTTP proxy to use when accessing the AWS API. This can also be sourced from theHTTP_PROXYenvironment variable.https_proxy- (Optional) The address of an HTTPS proxy to use when accessing the AWS API. This can also be sourced from theHTTPS_PROXYenvironment variable.no_proxy- (Optional) Comma-separated values which specify hosts that should be excluded from proxying when accessing the AWS API. This can also be sourced from theNO_PROXYenvironment variable. Find more details here.insecure- (Optional) Explicitly allow the backend to perform "insecure" SSL requests; default isfalse.use_dualstack_endpoint- (Optional) Resolve an endpoint with DualStack capability.use_fips_endpoint- (Optional) Resolve an endpoint with FIPS capability.
Customizing AWS API Endpoints
The optional endpoints argument contains the following options:
s3- (Optional) Use this to set a custom endpoint URL for the AWS S3 API. This can also be sourced from theAWS_ENDPOINT_URL_S3environment variable or the deprecated environment variableAWS_S3_ENDPOINT.iam- (Optional) Use this to set a custom endpoint URL for the AWS IAM API. This can also be sourced from theAWS_ENDPOINT_URL_IAMenvironment variable or the deprecated environment variableAWS_IAM_ENDPOINT.sts- (Optional) Use this to set a custom endpoint URL for the AWS STS API. This can also be sourced from theAWS_ENDPOINT_URL_STSenvironment variable or the deprecated environment variableAWS_STS_ENDPOINT.dynamodb- (Optional) Use this to set a custom endpoint URL for the AWS DynamoDB API. This can also be sourced from theAWS_ENDPOINT_URL_DYNAMODBenvironment variable or the deprecated environment variableAWS_DYNAMODB_ENDPOINT.
terraform {
  backend "s3" {
    endpoints {
      dynamodb = "http://localhost:4569"
      s3       = "http://localhost:4572"
    }
  }
}
Assume Role Configuration
Assuming an IAM Role is optional and can be configured in two ways.
The preferred way is to use the argument assume_role, as the other, the other method is deprecated.
The argument assume_role contains the following arguments:
role_arn- (Required) The Amazon Resource Name (ARN) of the IAM Role to be assumed.duration- (Optional) Specifies the validity period for individual credentials. These credentials are automatically renewed, with the maximum renewal defined by the AWS account. The duration should be specified in the format<hours>h<minutes>m<seconds>s, with each unit being optional. For example, an hour and a half can be represented as1h30mor simply90m. The duration must be within the range of 15 minutes (15m) to 12 hours (12h).external_id- (Optional) An external identifier to use when assuming the role.policy- (Optional) JSON representation of an IAM Policy that further restricts permissions for the IAM Role being assumed.policy_arns- (Optional) A set of Amazon Resource Names (ARNs) for IAM Policies that further limit permissions for the assumed IAM Role.session_name- (Optional) The session name to be used when assuming the role.tags- (Optional) A map of tags to be associated with the assumed role session.transitive_tag_keys- (Optional) A set of tag keys from the assumed role session to be passed to any subsequent sessions.
The following arguments on the top level are deprecated:
assume_role_duration_seconds- (Optional) Number of seconds to restrict the assume role session duration. Useassume_role.durationinstead.assume_role_policy- (Optional) IAM Policy JSON describing further restricting permissions for the IAM Role being assumed. Useassume_role.policyinstead.assume_role_policy_arns- (Optional) Set of Amazon Resource Names (ARNs) of IAM Policies describing further restricting permissions for the IAM Role being assumed. Useassume_role.policy_arnsinstead.assume_role_tags- (Optional) Map of assume role session tags. Useassume_role.tagsinstead.assume_role_transitive_tag_keys- (Optional) Set of assume role session tag keys to pass to any subsequent sessions. Useassume_role.transitive_tag_keysinstead.external_id- (Optional) External identifier to use when assuming the role. Useassume_role.external_idinstead.role_arn- (Optional) Amazon Resource Name (ARN) of the IAM Role to assume. Useassume_role.role_arninstead.session_name- (Optional) Session name to use when assuming the role. Useassume_role.session_nameinstead.
terraform {
  backend "s3" {
    bucket = "mybucket"
    key    = "my/key.tfstate"
    region = "us-east-1"
    assume_role = {
      role_arn = "arn:aws:iam::ACCOUNT-ID:role/Opentofu"
    }
  }
}