S3 Permissions & IAM Best Practices
The exact IAM policy Rilavek needs to operate. Nothing more.
Quick Reference
Rilavek operates on a write-only, least-privilege model. We never need to read your files back. The permission groups below are ranked by priority.
s3:PutObjects3:CreateMultipartUploads3:UploadParts3:CompleteMultipartUploads3:AbortMultipartUploads3:ListMultipartUploadParts
Core write + multipart. Without these, nothing works.
s3:ListBucket
Enables directory listings and empty-folder checks for FTP/SFTP clients. Not strictly required for HTTP/TUS uploads.
s3:GetObjects3:DeleteObject
GetObject: Keep disabled. A write-only policy means your bucket contents stay private by design, not by luck.
DeleteObject: Only add if you need FTP/SFTP clients to delete files.
IAM Policy
Replace YOUR-BUCKET-NAME with your actual bucket name.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RilavekBucketLevel",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME"
},
{
"Sid": "RilavekObjectLevel",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
],
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
}
]
}s3:PutObject does not implicitly cover multipart actions. Switch to the Expanded policy if uploads fail.Why these actions?
s3:PutObject
The fundamental write operation. Every file Rilavek delivers to your bucket goes through PutObject. On AWS, this implicitly covers CreateMultipartUpload, UploadPart, and CompleteMultipartUpload, which is why the minimal policy is shorter.
s3:AbortMultipartUpload
Used to clean up incomplete uploads when a transfer is cancelled or an UploadId becomes stale. Without this, incomplete parts accumulate in your bucket and incur S3 storage costs.
s3:ListMultipartUploadParts
Before resuming an interrupted upload, Rilavek verifies the UploadId is still valid. This requires ListMultipartUploadParts. Without it, a resume attempt against an expired upload would fail silently with corrupted state rather than cleanly restarting.
s3:ListBucket
Applied at the bucket level, not object level. Used by FTP/SFTP clients to browse directory contents and to verify a folder is empty before deletion. Not required for HTTP/TUS pipelines.
Security Recommendation: Write-Only by Default
The safest configuration is write-only with no read access. With this posture, any access to your ingest credentials can only result in new data being written. Existing data remains inaccessible by design. Rilavek treats your bucket as a drop box, not a full filesystem.
Provider-Specific Notes
| Provider | Notes |
|---|---|
| AWS S3 | s3:PutObject implicitly covers multipart sub-actions. The minimal policy works as-is. |
| Cloudflare R2 | Uses API tokens, not IAM policies. Grant Object Read & Write scoped to the specific bucket. |
| Wasabi | Requires explicit multipart actions in the policy. Use the expanded variant if uploads fail with AccessDenied. |
| Backblaze B2 | Create an Application Key scoped to a single bucket with Write Only capability. B2's S3 compatibility layer maps these automatically. |
| MinIO | Requires explicit multipart actions. Use the expanded policy, or assign the built-in writeonly MinIO policy. |
| iDrive E2 | No IAM policies. Permissions are set per access key in the E2 console — select Write Only when creating the key and scope it to the target bucket. Key permissions cannot be changed after creation; delete and regenerate if you need to adjust them. |
Troubleshooting
AccessDenied on multipart upload
Your provider requires explicit multipart actions. Switch to the expanded policy.
NoSuchBucket
The bucket name in your data store config does not match an existing bucket. Double-check for typos and confirm the region.
InvalidAccessKeyId / SignatureDoesNotMatch
Credentials are incorrect. Regenerate the access key and secret from your provider console.
Empty directory listing via FTP/SFTP
Your IAM policy is missing s3:ListBucket. Add it to the bucket-level statement.
Resumed upload fails after provider lifecycle cleanup
The multipart upload was expired by a lifecycle rule. Rilavek will detect this and restart, but needs s3:ListMultipartUploadParts to verify the UploadId is still valid before resuming.