Effortless Backups with Powershell and AWS

I am not an operations guy but often my Sitecore backups needs are not sky high either. Maybe you are running a QA environment that your client starts using to play with content population. While that content is not exactly real they would prefer that the content doesn’t vanish overnight. Or maybe there’s a very simple brochure-like production site that doesn’t need all bells and whistles of advanced monitoring, hourly incremental backups, and automatic restore procedures but it would hurt (even if a little) if you lost your master database or your WFFM form submissions.

Here’s my go-to recipe.

AWS

We run everything in Amazon EC2. All our integration and QA environments are there. So are staging environments that we sometimes host for our clients. Our own production sites are hosted there as well. Our on-premise infrastructure is a set of all kinds of Apple devices and big screen monitors but not a single server.

SQL

I set up a maintenance plan that will back up the master database(s) every night. Usually midnight. Dump it to a folder on the file system. No fancy tapes or anything. The wizard usually takes only a few minutes to go through.

Mongo

The only thing I really need form that Mongo as far as backup goes is WFFM data. Your needs may vary and you may need your tracking data and whatnot. Either way, I am backing up the whole thing as my starting point. If the size grows too much too fast you can always do a by-collection backup. Here’s my script. The actual backup procedure is one line, everything else is ceremony and packaging as a single zip:

function ZipFiles( $zipfilename, $sourcedir )
{
    [Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem")
    $compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
    [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcedir, $zipfilename, $compressionLevel, $False)
}

$date = Get-Date -UFormat %Y-%m-%d;
$base = "D:backupMongo"

$destination = Join-Path $base $date

if (!(Test-Path -Path $destination))
{
    New-Item -ItemType directory -Path $destination

    # dump all local databases
    (D:mongodbbinmongodump.exe --out $destination)

    # zip up the backup
    Add-Type -Path 'C:WindowsMicrosoft.NETFramework64v4.0.30319System.IO.Compression.FileSystem.dll'
    ZipFiles "$destination.zip" $destination | Out-Null

    # clean up     
    Remove-Item $destination -Recurse -Force
}

Offload

Storing backups on the file system is not much of a protection. I push my backups to S3 automatically and this is probably why I am writing this blog post. EC2 has a concept of roles and policies – aka IAM roles. When you start your instance, you can assign a role to it that would enable access to certain AWS service endpoints. Here’s a policy with full access to S3:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    }
  ]
}

AWS SDKs will use the role assigned to an instance to authenticate with the service endpoints. Really slick. No credentials hanging around. No authentication handshakes. Just this:

$files = Get-ChildItem .* -Recurse -Include "*.zip", "*.bak"

foreach ($file in $files)
{
    Write-S3Object -BucketName brainjocksbackup -File "$($file.FullName)" -Key "production/$($file.Name)"

    Remove-Item -Path $file
}

It’s using AWS Tools for Powershell that I don’t even remember installing into my AMIs. It’s probably just there.

SQL runs at midnight via the maintenance plan. Mongo also runs a midnight via Task Scheduler. And the S3 push follows shortly after.

Enjoy!

Pavel Veller

Add a Comment

Your email address will not be published. Required fields are marked *

Or request call back