What you’ll set up
- A new S3 bucket just for Beacon, with public access blocked, ACLs disabled, HTTPS required, default encryption (SSE-S3, or SSE-KMS with your key), and versioning. The module always creates its own bucket and does not manage existing ones.
beacon-endpoint-writer, an IAM user that can upload objects below your Beacon prefix and can’t read or delete them.
terraform/aws-s3.
Before you start
1. Add the module
Pick a root prefix such asbeacon-prod. Beacon adds runtime/ and inventory/ below it, so don’t put either in the prefix.
Create a main.tf in a new directory, or add these blocks to your existing configuration. Change the region, bucket name, and prefix:
main.tf
ref pins the module to a Beacon release. The module first shipped in v1.3.38, and any later release tag works too.
2. Create the bucket and writer
yes. It’s working when the apply ends with:
3. Create the writer’s access key
The module doesn’t create access keys by default, because Terraform would store the secret in its state file. Create the key with the AWS CLI:AccessKeyId and SecretAccessKey in your password manager or MDM secret store. The key starts with AKIA and doesn’t expire, so the forwarder keeps uploading without anyone renewing a credential.
4. Give the values to your rollout
Then continue with your rollout:
5. Confirm delivery
After the forwarder is running on a Mac, write a test event there:Options
Set any of these in themodule "beacon_s3" block and run terraform apply again. Every input is described in variables.tf.
Encrypt with your own KMS key
Encrypt with your own KMS key
kms:GenerateDataKey on the key. The key’s own policy must allow IAM policies in your account to grant access, which the default key policy does.Delete old objects
Delete old objects
noncurrent_version_expiration_days (default 30). Set versioning_enabled = false to turn versioning off.Create the access key with Terraform
Create the access key with Terraform
terraform output -raw writer_secret_access_key after adding a matching output block. The secret is stored in Terraform state, so use this only when your state is encrypted and access is restricted.Match your organization's IAM rules
Match your organization's IAM rules
writer_user_namerenames the writer.iam_pathputs it under a path such as/beacon/.permissions_boundary_arnattaches a permissions boundary to it.tagstags every resource the module creates.
Drop the health-check permission
Drop the health-check permission
s3:ListBucket, which the forwarder’s startup check needs. Without it, uploads still work, but the forwarder logs a health-check error each time it starts. s3:ListBucket lets the writer see object names, never their contents.Outputs
Rotate the writer key
Rotation happens outside Terraform. IAM allows two keys per user, so the old key keeps working while you roll out the new one.- Create a second key:
aws iam create-access-key --user-name "$BEACON_S3_WRITER". - Give the new key to your rollout and rerun its forwarder setup on every Mac. In Fleet, update the two secret variables and rerun
beacon-configure-s3-forwarding.sh. - When every Mac has the new key, delete the old one:
aws iam delete-access-key --user-name "$BEACON_S3_WRITER" --access-key-id <old key id>.
Remove
- Remove the forwarder from your Macs. Uninstalling Beacon removes it.
-
Delete the access keys you created with the AWS CLI. IAM refuses to delete a user that still has keys:
-
Run
terraform destroy. It stops at a bucket that still holds objects. To delete the telemetry too, setforce_destroy = true, runterraform apply, and then destroy.
Troubleshooting
BucketAlreadyExists
BucketAlreadyExists
Someone else, in any AWS account, already has a bucket with that name. Choose another
bucket_name.DeleteConflict: Cannot delete entity, must delete access keys first
DeleteConflict: Cannot delete entity, must delete access keys first
terraform destroy or a rename is trying to delete an IAM user that still has a key you created with the AWS CLI. Delete the key first. See Remove.Uploads fail with AccessDenied
Uploads fail with AccessDenied
Check that the forwarder’s bucket, region, and prefix match the Terraform outputs exactly. The writer can only upload below
<prefix>/.Related
Beacon with Fleet and S3
Roll out Beacon with Fleet and forward to S3.
Claude with Jamf and S3
Roll out Beacon with Jamf Pro and forward to S3.
Google Cloud Storage with Terraform
The same setup for a Cloud Storage bucket.