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.
The bucket
Section titled “The bucket”- 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. - Leave Block all public access on. Plune’s check warns when a bucket is public, because anyone with its address could read the files.
- 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.
The policy
Section titled “The policy”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.
- In IAM open Policies and create a policy with the JSON below. Replace
<bucket>with your bucket’s name. - In IAM open Users, create a user with no console access and attach the policy to it.
- Open the user, go to Security credentials, and under Access keys choose Create access key. For the use case pick Other.
- 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:DeleteObjectVersiononly for deleting a specific version. Plune never names a version, so it does not need it.
Encryption with your own KMS key
Section titled “Encryption with your own KMS key”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.
Fill in Settings → Storage
Section titled “Fill in Settings → Storage”In Settings → Storage choose Connect a bucket, set Provider to AWS S3, and fill:
| Field | Value |
|---|---|
| Region | the bucket’s region, such as eu-central-1 — on its Properties page in the AWS console |
| Bucket | the bucket’s name |
| Folder | plune, or the folder you wrote in the policy |
| Access key ID | the key’s ID |
| Secret access key | the 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.
Lifecycle
Section titled “Lifecycle”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.
What it costs you
Section titled “What it costs you”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.