Synchronizing KeePass between Windows and Linux using SVN
November 21, 2010
The Problem: You use KeePass to securely
store unique passwords for all your accounts and need to sync them across Windows and Linux.
You don't want to use the synchronization feature in KeePass 2.x because it only supports FTP, and
the KeePassSync plugin is Windows-only.
The Solution: Use a tool that you're already familiar with and might have a setup
for already: SVN.
SVN will allow you to synchronize your database across an infinite number of machines, but since
the database is a binary-file you should be sure that you only have one copy of
the database open at any one time, otherwise you will run into merging problems.
SVN's lock command provides an easy solution to this problem. Anytime you open
the database you simply acquire the lock so it can't be opened by another machine,
then when you close the database, you release the lock. This solution might be a
problem for some people, but for syncing between the office and home it works great.
For the rest of this article, I'm going to assume that you know how to use SVN to create a repository with your KeePass database in it and how to checkout a copy of your database on each of your machines.
Once you get a checkout on your first machine, I highly recommend setting the "svn:needs-lock" property on your database file. This will automatically switch your database file between read-only and writable when you release and acquire a lock.
svn propset "svn:needs-lock" "*" Database.kdbx svn commit -m "added needs-lock property"
To make this solution work on Windows, you must have the following installed:
- Command-line version of SVN (not just TortoiseSVN). I recommend Slik SVN.
- Microsoft PowerShell, which was first released with Vista, but is also available to download for XP.
In order for the console window to be hidden while waiting for KeePass to exit, you'll need to put this PowerShell script, originally posted here, called Set-Console.ps1, somewhere in your system's PATH. (I recommend C:\Windows):
param ([switch] $hidden)
$code = @'
using System;
using System.Runtime.InteropServices;
public class ConsoleHelper
{
private const Int32 SW_HIDE = 0;
private const Int32 SW_SHOW = 5;
[DllImport("user32.dll")]
private static extern Boolean ShowWindow(
IntPtr hWnd,
Int32 nCmdShow
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool AllocConsole();
[DllImport("Kernel32.dll")]
private static extern IntPtr GetConsoleWindow();
public static void HideConsole()
{
IntPtr hwnd = GetConsoleWindow();
if (hwnd != IntPtr.Zero)
{
ShowWindow(hwnd, SW_HIDE);
}
}
public static void ShowConsole()
{
IntPtr hwnd = GetConsoleWindow();
if (hwnd != IntPtr.Zero)
{
ShowWindow(hwnd, SW_SHOW);
}
}
}
'@
[ConsoleHelper] > $null
$ch = [ConsoleHelper]
trap {
# Get an instance of the CSharp code provider
$cp = new-object Microsoft.CSharp.CSharpCodeProvider
# And compiler parameters...
$cpar = New-Object System.CodeDom.Compiler.CompilerParameters
$cpar.GenerateInMemory = $true
$cpar.GenerateExecutable = $false
$cpar.OutputAssembly = "custom"
$cr = $cp.CompileAssemblyFromSource($cpar, $code)
# display any errors (there should be none...)
if ( $cr.Errors.Count)
{
$codeLines = $code.Split("`n");
foreach ($ce in $cr.Errors)
{
write-host "Error: $($codeLines[$($ce.Line - 1)])"
$ce | out-default
}
Throw "Compile failed..."
}
else
{
# don't report the exception
continue
}
}
if ($hidden)
{
$ch::HideConsole()
}
else
{
$ch::ShowConsole()
}
Once you have the above script saved to Set-Console.ps1 in your system's PATH, you should be able to start using the script below. This script will open a console window briefly to inform you of what's going on. After successfully acquiring the SVN lock, the window will hide itself until you close KeePass, in which it will briefly open again. You simply need to change the five variables at the top to your needs.
$SVN_PATH = 'C:\Program Files\SlikSvn\bin\svn.exe'
$SVN_LOCK_MESS = 'auto-locked from powershell'
$SVN_COMMIT_MESS = '-auto-commit from powershell'
$KEEPASS_PATH = 'C:\Program Files\KeePass Password Safe 2\KeePass.exe'
$KEEPASS_FILE = 'C:\Documents and Settings\sean\My Documents\keepass\Database.kdbx'
echo 'Performing SVN update...'
& $SVN_PATH update "$KEEPASS_FILE" > $null
echo 'Acquiring SVN lock...'
$SVN_LOCK = & $SVN_PATH lock -m "$SVN_LOCK_MESS" "$KEEPASS_FILE" 2>&1
if ([Regex]::IsMatch($SVN_LOCK, 'warning')) {
echo 'Failed to acquire SVN lock!'
} else {
echo 'Starting KeePass and hiding window...'
$p = [Diagnostics.Process]::Start($KEEPASS_PATH, "`"$KEEPASS_FILE`"")
Start-Sleep 3
Set-Console -hidden
$p.WaitForExit()
echo 'Committing and releasing SVN lock...'
Set-Console
& $SVN_PATH commit "$KEEPASS_FILE" -m "$SVN_COMMIT_MESS" --no-unlock > $null
& $SVN_PATH unlock "$KEEPASS_FILE" > $null
}
echo 'Exiting...'
Start-Sleep 3
Once you have the script above saved to a file somewhere, you can create a Windows shortcut to run the script whenever you want to open your KeePass database. Create a shortcut and set it's target for example to:
powershell.exe &'C:\Documents and Settings\sean\My Documents\Database.ps1'
In order to get this to work on Linux, all you need is to have SVN and BASH installed. This script is meant to be run with the console hidden ("Application", rather than "Application in Terminal" from a launcher), and for messages be sent to your notification system for your GUI. For me on Ubuntu 10.10 with GNOME, it's notify-send. Simply change the six variables at the top to your needs.
#!/bin/bash SVN_PATH="/usr/bin/svn" SVN_LOCK_MESS="auto-locked from bash" SVN_COMMIT_MESS="-auto-commit from bash" KEEPASS_PATH="mono /usr/local/share/applications/KeePass-2.13/KeePass.exe" KEEPASS_FILE="/home/sean/keepass/Database.kdbx" NOTIFY_CMD="notify-send" `$SVN_PATH update $KEEPASS_FILE` > /dev/null SVN_LOCK=`$SVN_PATH lock $KEEPASS_FILE -m "$SVN_LOCK_MESS" 2>&1` if [[ $SVN_LOCK =~ "warning" ]]; then $NOTIFY_CMD "Failed to acquire SVN lock!" else $NOTIFY_CMD "SVN lock acquired successfully!" `$KEEPASS_PATH $KEEPASS_FILE` > /dev/null `$SVN_PATH commit $KEEPASS_FILE -m "$SVN_COMMIT_MESS" --no-unlock` > /dev/null `$SVN_PATH unlock $KEEPASS_FILE` > /dev/null $NOTIFY_CMD "Committed and released SVN lock!" fi
There ya go, now you just need to make sure to update your shortcuts to make sure you always use one of the scripts to open your database!
Zend Certified Engineer
September 14, 2009
I've been working with PHP for
quite some time now and thought that it certainly couldn't hurt to get
that certification. I purchased Zend's PHP5 certification bundle that
comes with 10 online practice exams, a PDF version of their study guide,
and a voucher to take the exam with Pearson Vue. I took the time to
study before school started up and a week later I was taking the exam
and got my certification.
Recent Tracks
- Placebo—Special K 3 months ago
- Linkin Park—In Pieces 3 months ago
- Coldplay—Hurts Like Heaven 3 months ago
- Breaking Benjamin—Sooner Or Later 3 months ago
- My Chemical Romance—Party Poison 3 months ago
- The Naked and Famous—Frayed 3 months ago
- Lostprophets—Rooftops (A Liberation Broadcast) 3 months ago
- The Used—Blue and Yellow 3 months ago
- Red Hot Chili Peppers—Can't Stop 3 months ago
- Muse—Hoodoo 3 months ago
