# Add object storage

Connect an application to elastic S3-compatible storage and choose whether objects are externally reachable.

Canonical: https://docs.deliberate.space/data/object-storage/

Use object storage for uploads, attachments, generated assets, and other data
that should be accessed through an S3-compatible API rather than a mounted
filesystem. Capacity is elastic and billed by usage; there is no size or storage
tier to choose.

## Create and connect a bucket

Declare the bucket and map its outputs into the variable names expected by your
S3 client:

```yaml
resource: bucket
name: assets

---
resource: component
name: app
image: registry.deliberate.cloud/acme/app:1.4.2
env:
  S3_ENDPOINT: "${{ assets.endpoint }}"
  S3_BUCKET: "${{ assets.bucket }}"
  S3_ACCESS_KEY: "${{ assets.access_key }}"
  S3_SECRET_KEY: "${{ assets.secret_key }}"
needs:
  buckets:
    - assets
```

`needs.buckets` grants access to the bucket. The expressions supply its endpoint,
served bucket name, and generated credentials without writing those credentials
into YAML. Cross-Project bucket consumption is not currently available.

## Keep objects internal or expose an endpoint

The default bucket is reachable only from authorized workloads. Set `expose` if
external clients need authenticated or presigned access:

```yaml
resource: bucket
name: uploads
expose: true
anonymousRead: false
```

`expose: true` creates an externally reachable S3-compatible endpoint. It does
not make objects public: normal requests still require credentials, and SDK
presigned GET and PUT URLs can be used for bounded browser downloads or uploads.

Set `anonymousRead: true` only for deliberately public assets. It implies
`expose: true` and grants anonymous reads; anonymous writes are never enabled.
Application uploads remain authenticated or presigned.

## Choose what previews receive

Buckets are copied into a derived Environment by default. Use an empty bucket
for previews that do not need production objects:

```yaml
resource: bucket
name: assets
seedWith: copy
overrides:
  preview-*:
    seedWith: empty
    expose: false
```

A copied bucket is isolated from its source: changes in the preview do not
modify production. It is still another copy of the data, so consider access,
privacy, and cost before copying customer objects into disposable Environments.

## Durability and recovery boundary

Bucket data is stored in EU object storage with encryption at rest. The bucket
resource does not currently expose versioning, lifecycle rules, a selectable
backup policy, or a customer restore workflow. Application deletion of an
object must therefore not be assumed recoverable through the platform.

Keep independent exports or an application-level retention strategy when the
objects are irreplaceable or subject to business or regulatory retention. Use a
[volume](/data/volumes/) when software requires filesystem semantics, and a
[database](/data/databases/) when it needs transactions or point-in-time
recovery.

## Next steps

- [Connect other application dependencies](/build/configuration/)
- [Protect data in previews](/deploy/environments/)
- [Review the platform's data-protection boundary](/data/protection/)
