Matthew Hipkin

Automatically backing up your web server files to GoogleDrive with PHP

Download: https://github.com/hippy2094/backuptogoogledrive

Google has recently upped the amount of free storage they offer on GoogleDrive to 15Gb. This is good news, but what to use it for? I figured it would be great to make weekly backups of my websites and databases. The Google API makes this very easy to do!

Throughout this article I will include snippets of code however a link to a full example is at the bottom.

To make this happen, your hosting will need PHP5 and you must have the ability to execute commands using the shell_exec() function. Being able to setup a crontab is also needed to automate the process.

Requirements
You will need the Google API PHP Client.

Some settings
Firstly, we'll need to setup some variables for use throughout.

  // User home directory (absolute)
  $homedir = trim(shell_exec("cd ~ && pwd"))."/"; // If this doesn't work, you can provide the full path yourself
  // Site directory (relative)
  $sitedir = "www/"; 
  // Base filename for backup file
  $fprefix = "sitebackup-";
  // Base filename for database file
  $dprefix = "dbbackup-";
  // MySQL username
  $dbuser = "root";
  // MySQL password
  $dbpass = "root";
  // MySQL database
  $dbname = "test";
  // Google Drive Client ID
  $clientId = ""; // Get this from the Google APIs Console https://code.google.com/apis/console/
  // Google Drive Client Secret
  $clientSecret = ""; // Get this from the Google APIs Console https://code.google.com/apis/console/
  // Google Drive authentication code
  $authCode = ""; // Needs to be set using getauthcode.php first!    

Pre-authenticating with Google
Due to the nature of this application, we will need to authenticate it using a separate script and then save the response in a configuration file. The first thing you'll need to do is visit the Google APIs Console and register an application, Google has already given instructions on this so I won't repeat those here. You MUST remember to setup the $clientId and $clientSecret variables at this point.

This simple script is enough to get the authentication URL which you will need to visit in your browser. Once you have the authentication code, you will need to paste it into the $authCode variable within your settings.

  require_once("google-api-php-client/src/Google_Client.php");
  require_once("google-api-php-client/src/contrib/Google_DriveService.php");
  include("settings.inc.php");  

  $client = new Google_Client();
  // Get your credentials from the APIs Console
  $client->setClientId($clientId);
  $client->setClientSecret($clientSecret);
  $client->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
  $client->setScopes(array('https://www.googleapis.com/auth/drive'));

  $service = new Google_DriveService($client);

  $authUrl = $client->createAuthUrl();

  echo "Authorisation URL:\n$authUrl\n\n";
  echo "Please visit the URL above and then save the given value into settings.inc.php\n";

snapshot49

snapshot51snapshot52

Making the archives
You don't want to post each file from your website individually, so the first step is to create an archive, I am using a standard gzipped tarball but you could use whatever you wanted as long as its available on your webhost!

  // Use the current date/time as unique identifier
  $uid = date("YmdHis");
  // Create tar.gz file
  shell_exec("cd ".$homedir." && tar cf - ".$sitedir." -C ".$homedir." | gzip -9 > ".$homedir.$fprefix.$uid.".tar.gz");
  // Dump datamabase
  shell_exec("mysqldump -u".$dbuser." -p".$dbpass." ".$dbname." > ".$homedir.$dprefix.$uid.".sql");
  shell_exec("gzip ".$homedir.$dprefix.$uid.".sql");

At this point, we now have two gz files on the server: one containing the contents of the www directory and the other is an sql dump of the database.

Sending the files
Now we have our files, we have our client ID and secret, and we have our authentication code we are ready to send the files to GoogleDrive.

The first thing to do is setup the connection, we will also authenticate for the first time and save the access token to a file for future connections. If at any point you start getting authentication errors, you'll need to delete token.json and run getauthcode.php again.

  $client = new Google_Client();
  // Get your credentials from the APIs Console
  $client->setClientId($clientId);
  $client->setClientSecret($clientSecret);
  $client->setRedirectUri("urn:ietf:wg:oauth:2.0:oob");
  $client->setScopes(array("https://www.googleapis.com/auth/drive"));
  $service = new Google_DriveService($client);  
  // Exchange authorisation code for access token
  if(!file_exists("token.json")) {
    // Save token for future use
    $accessToken = $client->authenticate($authCode);      
    file_put_contents("token.json",$accessToken);  
  }
  else $accessToken = file_get_contents("token.json");
  $client->setAccessToken($accessToken);

If all went well, the next piece of code will send the first file to GoogleDrive.

  $file = new Google_DriveFile();
  $file->setTitle($fprefix.$uid.".tar.gz");
  $file->setDescription("Server backup file");
  $file->setMimeType("application/gzip");
  $data = file_get_contents($homedir.$fprefix.$uid.".tar.gz");
  $createdFile = $service->files->insert($file, array('data' => $data, 'mimeType' => "application/gzip",));
  // Process response here....
  print_r($createdFile);

As you can see, there is actually very little we have to do ourselves, the Google SDK handles pretty much everything for us. We repeat the same code as above for the database backup file, and then all that remains in the code is to clean up.

  unlink($homedir.$fprefix.$uid.".tar.gz");
  unlink($homedir.$dprefix.$uid.".sql.gz");

Automating the process
Once everything is in place, you are authenticated and everything is working a simple crontab item should be enough to get things on the go.

5 0 * * 6 /usr/local/bin/php /home/myusername/backuptogoogledrive.php

This would run the script at 00:05 on a saturday.

Download the full example as a zip file here.

blog comments powered by Disqus