> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackshift.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage S2 buckets with Terraform

> Declare an S2 bucket, handle its one-time credentials, import existing buckets, and control destructive cleanup.

<Warning>
  **Live with caveats.** This area is real and usable, but the docs intentionally call out operational or UX limits that still matter.
</Warning>

## Goal

Manage the bucket lifecycle declaratively without exposing credentials or accidentally deleting stored objects.

## Prerequisites

* The StackShift Terraform provider installed
* Encrypted Terraform state with restricted access
* A StackShift API token configured for the provider

## Workflow

<Steps>
  <Step>
    Declare `stackshift_bucket` with a stable name and signing region.
  </Step>

  <Step>
    Keep `force_destroy` false for production unless object deletion is explicitly intended.
  </Step>

  <Step>
    Select `encryption_mode`; use `sse-kms` when the bucket requires platform-managed KMS envelope encryption.
  </Step>

  <Step>
    Apply once and move the sensitive secret output into the workload secret manager.
  </Step>

  <Step>
    Use the computed endpoint and access key ID when configuring the S3 client.
  </Step>

  <Step>
    Import existing buckets by control-plane UUID when Terraform did not create them.
  </Step>
</Steps>

## Bucket resource

```hcl theme={null}
resource "stackshift_bucket" "uploads" {
  name             = "example-customer-uploads"
  region           = "global"
  visibility       = "private"
  access_key_label = "terraform-production"
  force_destroy    = false

  versioning_enabled     = true
  default_retention_days = 30
  encryption_mode        = "sse-kms"
}

output "s2_endpoint" {
  value = stackshift_bucket.uploads.endpoint
}

output "s2_secret_access_key" {
  value     = stackshift_bucket.uploads.secret_access_key
  sensitive = true
}
```

## Lifecycle behavior

* `name`, `region`, `visibility`, `project_id`, and `access_key_label` replace the bucket when changed.
* `force_destroy` is a Terraform-side deletion choice and can change without replacing the bucket.
* `versioning_enabled`, quotas, retention, tiering, website settings, `encryption_mode`, and `custom_domain_id` update in place.
* `kms_key_id` is computed. For `sse-kms`, StackShift returns the platform-managed key identifier after the settings update.
* If platform KMS is unavailable, enabling `sse-kms` fails closed instead of silently falling back to another mode.
* Destroy refuses a non-empty bucket by default. Enabling force destroy asks S2 to remove contained objects before deleting the bucket.
* Read refreshes object count, size, endpoint, and timestamps without trying to read the one-time secret again.

## Import

Run `terraform plan` after import and supply the bucket configuration in HCL. Imported state cannot contain a secret the API no longer returns.

```bash theme={null}
terraform import stackshift_bucket.uploads <bucket_id>
```

## Expected result

<Check>
  Terraform owns the bucket configuration and deletion policy while secret material remains protected as sensitive state.
</Check>

## Common failures

<Warning>
  * Publishing state files or plan artifacts. Sensitive values are redacted in normal output but still exist in state.
  * Expecting import to recover an existing secret access key. Create a new bucket key after import when credentials are needed.
  * Changing name, region, visibility, project, or initial key label without reviewing the planned replacement.
  * Supplying AWS credentials or a KMS ARN. Terraform selects `sse-kms`; StackShift owns and returns the platform key identifier.
  * Setting `force_destroy = true` without accepting that destroy will remove every object in the bucket.
</Warning>

## Related guides

<CardGroup cols={2}>
  <Card title="Terraform and OpenTofu provider" href="/infrastructure-as-code/terraform-provider">
    Use the StackShift provider implementation to declare StackShift resources and run explicit StackShift actions from Terraform or OpenTofu.
  </Card>

  <Card title="Provider resources and imports" href="/infrastructure-as-code/resources-and-imports">
    Implementation reference for StackShift provider resources, import IDs, action semantics, and caveats.
  </Card>

  <Card title="Access keys, encryption, isolation, and quotas" href="/object-storage/access-and-security">
    Operate S2 credentials, encryption, visibility, tenant isolation, request limits, and customer-plan quotas safely.
  </Card>
</CardGroup>
