> **Page index:** https://km.oslo.systems/llms.txt lists every page on this site, with a link to its Markdown version.

# S3 bucket

Reference for provisioning an S3 bucket with recommended defaults using the public [`terraform-aws-modules/s3-bucket`](<https://registry.terraform.io/modules/terraform-aws-modules/s3-bucket/aws/latest>) module.

## Configuration

The recommended location for this is in a `-data` directory such as `my-app-data`, as per Golden Path conventions.

my-app-data/my-s3-bucket.tf

```
module "bucket" {
  source  = "terraform-aws-modules/s3-bucket/aws"
  version = "~> 4.0"

  bucket = "my-bucket" # (1)!

  versioning = {
    enabled = true
  }

  server_side_encryption_configuration = {
    rule = {
      apply_server_side_encryption_by_default = {
        sse_algorithm = "AES256"
      }
    }
  }

  control_object_ownership = true

  attach_deny_insecure_transport_policy = true

  lifecycle_rule = [{
    id     = "expire-noncurrent-versions"
    status = "Enabled"
    noncurrent_version_expiration = {
      noncurrent_days = 90
    }
  }]
}
```

1. Include your team or environment in the name to avoid collisions, since S3 bucket names are globally unique across all AWS accounts.

## Settings

| Setting | Value | Effect |
| --- | --- | --- |
| `versioning.enabled` | `true` | Keeps previous object versions, so overwritten and deleted objects can be recovered. |
| `server_side_encryption_configuration` | `AES256` | Encrypts objects at rest with S3-managed keys. |
| `control_object_ownership` | `true` | The bucket owner owns all objects; ACLs are disabled. |
| `attach_deny_insecure_transport_policy` | `true` | Rejects requests that do not use TLS. |
| `lifecycle_rule` (`expire-noncurrent-versions`) | `noncurrent_days = 90` | Expires noncurrent object versions 90 days after they become noncurrent. |

## Let the CI/CD roles read the bucket

The IAM roles that run Terraform plans and deployments can't read this bucket by default. To give them read access, see [Allow read access to S3](<https://km.oslo.systems/terraform-automation/allow-read-access-to-s3/index.md>).

## Outputs

The module exposes the underlying bucket attributes as outputs, referenced through `module.bucket`. Commonly used outputs:

| Output | Description |
| --- | --- |
| `s3_bucket_id` | The bucket name. |
| `s3_bucket_arn` | The bucket ARN. |
| `s3_bucket_bucket_regional_domain_name` | The bucket's region-specific domain name, such as `my-bucket.s3.eu-west-1.amazonaws.com`. |

To re-expose an output from your stack:

```
output "regional_domain_name" {
  value = module.bucket.s3_bucket_bucket_regional_domain_name
}
```
