Skip to content

AWS S3

You need an AWS account, an S3 bucket that is private, and an IAM user whose key can touch one folder of that bucket. Read Files in your own bucket first if you have not.

  1. In the S3 console open General purpose buckets and create a bucket. Note its name and its region (such as eu-central-1): the form needs both, and the region must be the bucket’s own — the region code of the bucket, not the one you are signed in to.
  2. Leave Block all public access on. Plune’s check warns when a bucket is public, because anyone with its address could read the files.
  3. Leave the rest at its defaults. New buckets encrypt every upload with SSE-S3 and have ACLs turned off; Plune sends neither an encryption header nor an ACL, so nothing is needed on either.

A bucket name with a dot in it works: Plune then addresses the bucket by path (s3.<region>.amazonaws.com/<bucket>/…) instead of by host name, because AWS’s certificate does not cover dotted names in the host.

Give Plune a key that can reach this one bucket — not the account, not other buckets — and write, read and delete only inside its plune/ folder.

  1. In IAM open Policies and create a policy with the JSON below. Replace <bucket> with your bucket’s name.
  2. In IAM open Users, create a user with no console access and attach the policy to it.
  3. Open the user, go to Security credentials, and under Access keys choose Create access key. For the use case pick Other.
  4. Copy the Access key ID and the Secret access key. AWS shows the secret once; it cannot be recovered later, only replaced by a new key.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PluneFiles",
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::<bucket>/plune/*"
},
{
"Sid": "PluneFolderListing",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::<bucket>"
}
]
}

The first statement is what Plune needs: write, read and delete inside plune/. If you gave the Folder in Plune another name, use that name in Resource instead of plune.

The second statement is a recommendation, and it is about errors, not about working at all. When Plune confirms that a file arrived, it asks the bucket for the object. For an object that is not there, AWS answers 404 only to a key that is allowed s3:ListBucket; to any other key it answers 403, so that nobody can learn what exists. With the listing right, a file that never arrived gets a precise answer (422 file_missing). Without it Plune cannot tell the file is missing from you may not read it and answers 503 bucket_unreachable, “try again” — so the client retries a request that cannot succeed, until a nightly cleanup removes the unfinished line (it removes lines more than an hour old). The price: a key with this right can list the file names of the whole bucket, so use a bucket kept for Plune, or a key that is valid for this bucket only.

Two more things about the policy:

  • One bucket only. The key is useless for any other bucket, and that is the point.
  • A versioned bucket needs s3:DeleteObjectVersion only for deleting a specific version. Plune never names a version, so it does not need it.

The default SSE-S3 needs nothing from you. If the bucket encrypts with SSE-KMS, give the same user kms:GenerateDataKey (to write) and kms:Decrypt (to read) on that KMS key. This follows the usual S3 rule for KMS and has not been run with Plune.

In Settings → Storage choose Connect a bucket, set Provider to AWS S3, and fill:

FieldValue
Regionthe bucket’s region, such as eu-central-1 — on its Properties page in the AWS console
Bucketthe bucket’s name
Folderplune, or the folder you wrote in the policy
Access key IDthe key’s ID
Secret access keythe key’s secret — stored encrypted, never shown again

Then Check and connect. Nothing is saved until the checks pass. If one fails, its words and a How to fix link are beside it; every cause is on When something is wrong.

Screenshots and videos open without it. Traces and text need one rule on the bucket, and so does a file a person adds in the dashboard: GET and PUT from the dashboard’s address. In the S3 console open the bucket, then Permissions → Cross-origin resource sharing (CORS) → Edit, paste this and Save changes:

[
{
"AllowedOrigins": ["https://app.plune.ai"],
"AllowedMethods": ["GET", "PUT"],
"AllowedHeaders": ["content-type"],
"MaxAgeSeconds": 3600
}
]

On the beta, write https://beta.plune.ai. The console takes CORS as JSON; the API takes XML. CORS explains the rule and how to check it.

To let objects expire on your side, open the bucket, then Management → Create lifecycle rule. Scope it to the prefix plune/ and choose Expire current versions of objects after the number of days you want. In a versioned bucket also choose to delete noncurrent versions, or deleted files go on taking space. Expiry is not instant: S3 removes objects after the day passes, not at the minute.

A rule on plune/ of about 200 days is a suggestion; see Two clocks for what happens when it is shorter or longer than Plune’s own history. A bucket policy cannot stop a lifecycle rule from deleting.

Storage, requests, and data going out of AWS are all billed by AWS; reading a trace or a video in the dashboard downloads it from your bucket. The region you pick decides the price.