I just want to run this idea by some smarter people to make sure I'm not overlooking something obvious:

I want to backup my Linux server to S3 using one of the many backup scripts that allow automatic pruning of backups. So my S3 IAM policy will obviously have to give that user GET, PUT, and DELETE permissions. But since the DELETE permission will be there, I need to plan against the worst-case scenario of a hacker getting root access to my server and deleting the backups on S3 using the stored credentials. To eliminate this possibility, I was thinking about the following configuration:

  • Versioning enabled on the bucket (hacker can delete the files but they are only tagged as deleted on S3 and recoverable by me)
  • Lifecycle policy enabled on the bucket to automatically delete old versions (eventually eliminating all versions of the file to minimize storage costs)

Then, the only user that would have bucket-deletion or version-deletion permissions would be my main Amazon account user, which I would configure with MFA.

Am I missing anything obvious here?

I did find this claiming that...

You can use the Object Expiration feature on [...] You cannot, however, use it in conjunction with S3 Versioning

...I assume that's obsolete information? In my quick informal experimentation it appears to be possible to use versioning with Object Expiration.

Thanks a lot!

  • Or, maybe, you could do the deletion from elsewhere, with different credentials. – Fox Jul 19 '15 at 16:02

Yes, the blog post you linked (from 2011) appears to contain obsolete information. From the docs:

If the bucket is versioning-enabled (or versioning is suspended), the Expiration action logically deletes the current version by adding a delete maker as the new current version. The NoncurrentVersionExpiration action permanently removes the noncurrent versions.


The only problem with your plan is that a lifecycle policy to remove deleted objects (to save storage) is somewhat at odds with disaster recovery protection against maliciously deleted content. You'd have to discover the breach quickly, or the lifecycle policy would purge your apparently-deleted-but-actually-hidden objects.

That isn't to say that your strategy isn't theoretically good -- I would suggest that it is, as I use something similar -- but the purge of no longer needed objects may need to be more sophisticated than lifecycle policies can provide, and may require custom logic that runs on a schedule and has additional rules.

| improve this answer | |
  • Thanks a lot Michael for the reply. I think the most probable scenario would be a hacker defacing or otherwise taking down my webserver, which I would notice quickly, and then he would possibly proceed to try to destroy my backups. I was thinking about something along the lines of making deleted files be quickly archived into Glacier after a day or so to reduce costs, and then keep them around in Glacier for a month or so. – rahim123 Jul 19 '15 at 15:43
  • I wish there was a way to do better custom logic from S3, but in lieu of that I guess I'll probably use a backup solution that creates a local copy of the data with a pruning policy of N daily, weekly, and monthly backups, and then back up the whole repository to S3. – rahim123 Jul 19 '15 at 15:44
  • > then back up the whole repository to S3 < Actually I meant that the backup script would act on a locally mounted S3 filesystem. – rahim123 Jul 19 '15 at 15:59
  • If your server is EC2, then EBS snapshots are probably a better solution, since they are automatically incremental, storing only data not already in an earlier snapshot, and you can purge intermediate snapshots at any time, with the increments from the purged snapshots rolling forward automatically into the first non-purged snapshot that still needs them. – Michael - sqlbot Jul 19 '15 at 18:12

Assuming that you can use a lifecycle policy to delete and/or archive the old versions in a way that works for you, there's no need to give your script delete permissions at all. This approach works great for me in conjunction with the AWS CLI tools.

Here's what my bucket policy looks like:

    "Version": "2012-10-17",
    "Id": "IDHERE",
    "Statement": [
            "Sid": "ToSendBackups",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::IAMUSERHERE"
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::BUCKETHERE/*"
            "Sid": "BucketOps",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::IAMUSERHERE"
            "Action": [
            "Resource": "arn:aws:s3:::BUCKETHERE"

Also, note that if you are going to archive to Glacier, you'll want to keep the archived files for at least 90 days, since "there is a pro-rated charge of $0.03 per gigabyte for items deleted prior to 90 days" (http://aws.amazon.com/glacier/pricing/), so using Glacier won't save you anything if you delete them earlier.

| improve this answer | |
  • Thanks @szarca for the suggestion. I'm actually using a similar bucket policy now, but the problem is that I want to switch to a smarter backup tool with better de-duplication and more flexible daily, weekly, monthly, and yearly pruning capabilities. So mainly for the pruning aspect I need to be able to delete stuff on the bucket – rahim123 Jul 21 '15 at 15:16
  • Sounds like you need to open up permissions to the backup user, then. Perhaps you could add a policy that copies backups from the backup bucket to another bucket, but then expire quickly in the second bucket? Otherwise, I guess I'd look at a different strategy, such as spinning up an EC2 instance each night & backing up to that. – szarka Jul 22 '15 at 16:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.