Centralized backups using rsync and OpenSSH on Windows 10

I consider backups to be the “desert island” service of IT; if you’re going to provide one service to your users or business, it has to be backups. Data changes all the time, users make mistakes, and disasters happen. What gets us through are simple, reliable backups.

On *nix systems, I prefer to use simple, built-in tools to perform backups, and it doesn’t get much simpler than rsync and OpenSSH; rsync copies the changes (and ignores what stays the same) and SSH secures the data in transport. These two tools, combined with something like rsnapshot to manage versions and reduce data duplication, make for a backup infrastructure that can be setup relatively quickly with no worry about extra software installation and licensing.

On Windows systems, no such built-in tools really exist. Yes, there is a backup utility on Windows 10, but this tool requires a local hard disk attached to the computer, a solution that does not scale very well. Alternatively, you could use the older image-based backup, but Microsoft if backing away from this solution; what’s more, it stores data in a proprietary format and doesn’t do anything to reduce data duplication. While this sort of backup is a good supplement to traditional backups, especially for critical servers like domain controllers, it’s ultimately inadequate by itself and overkill for desktop workstations that don’t require a full system backup. On the desktop, we mostly care about user documents, media, and configurations since everything else (software, patches, and OS version) will be more or less boilerplate within the organization.

In April 2018, Microsoft started providing a way to install OpenSSH in Windows 10, opening up some new doors for administrators to remotely access their systems. With a little bit of extra work, we can recreate the same type of backup infrastructure that has existed for years on *nix systems. I should note, however, that this solution is only appropriate for non-encrypted, local user profiles. Roaming profiles are stored in a central location and can easily be duplicated from there. Encrypted profiles make it practically impossible to read user data without the decryption key even with an administrator account, so the backup agent (in this case, a service account), would not be permitted to even access the files without the private key.

By the way, all of these steps I’m about to describe can be scripted and managed via Group Policy. For one or two clients, automating these steps is probably overkill, but for even small networks of a few workstations, developing an automated solution that works will save a ton of time and headache. You need only figure out how to do it once for one client, after which, duplicating the process is straightforward.

So, how do we get started? Well, we need some storage that can be accessed by our backup server. Storage options, server setup, and file systems are beyond the scope of this article, so let’s keep things simple by assuming that your backup server is a Linux box with direct-attached storage for backups. This server needs an SSH client (default installed on most distros), rsync (default installed on most distros), and rsnapshot (available in the repos of most distros) or some other backup management software. You also need to generate a public/private SSH key pair. I still recommend using large RSA keys (4096 bits or higher) for backward compatibility, but the Windows version of OpenSSH supports most modern algorithms including elliptical curve and ED25519.

Once you’ve got a backup server setup, it’s time to move on to the clients. First, you need a service account that will execute the backups on your client. This must be a user with permission to access other users’ files and maybe system files, too. Do not use the built-in administrator account but a new account in the administrators group. You could get even more specific with permissions if your backup scope is particularly narrow. I also recommend using Computer Policy (or Group Policy) to prohibit local login of the service account. Make sure to use a strong password on the service account, as well.

Then, enable the following policy options to be able to install the OpenSSH server:

  • Computer Configuration\Administrative Templates\System\Specify settings for optional component installation and component repair
  • Make sure to check “Download repair content and optional features directly from Windows Update instead of Windows Server Update Services (WSUS)” – This is only necessary is you’re using a local WSUS repository.

Then we can use this guide to install OpenSSH via the GUI or some Powershell commands to do it via the CLI:

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~

This command installs the service, creates configuration files, and open firewall ports which we can then tweak to our needs. I suggest locking down the configuration and authorized keys files accordingly:

cacls %PROGRAMDATA%\ssh\sshd_config /t /g "Authenticated Users:r" "Administrators:f" "SYSTEM:f"
cacls %PROGRAMDATA%\ssh\administrators_authorized_keys /t /g "Administrators:f" "SYSTEM:f"

Your SSH config file should look something like this:

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.
#Port 22
#AddressFamily any
#ListenAddress ::
#HostKey __PROGRAMDATA__/ssh/ssh_host_rsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_dsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ecdsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile	.ssh/authorized_keys
#AuthorizedPrincipalsFile none
# For this to work you will also need host keys in %programData%/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#PermitTTY yesThese permissions assume your SSH service account is in the administrators group, allowing it to access system files and other users' files as necessary. I also suggest modifying your clients' policy to prevent direct login from your service account; this can be done with Group Policy. 
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# override default of no subsystems
Subsystem	sftp	sftp-server.exe
# Example of overriding settings on a per-user basis
#Match User anoncvs
#	AllowTcpForwarding no
#	PermitTTY no
#	ForceCommand cvs server
AllowGroups administrators
Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

You need to add your backup server’s public key to the administrators_authorized_keys file to enable passwordless login. Now, restart the ssh service:

net stop sshd
net start sshd

At this point, you should test the service account by logging into the client with the service account from the backup server and accessing some files. If this step is successful, we can move onto installing rsync.

Getting rsync on the Windows client is the most difficult step as it’s not built-in to Windows. Installing the Linux subsystem for Windows won’t help you either as it doesn’t come with rsync. So, I like to use a scripted installation of cwrsync. To install it, you need only copy the installation files to a directory on the client; no extra configuration necessary on the client. I use C:\cwrsync as the installation directory.

At this point, you should test your setup with a simple copy operation from the backup server:

rsync --rsync-path=/c/cwrsync/rsync.exe serviceaccount@backupclient:/c/Users/User1/testfile.txt ./

If the test file transfers successfully, all the heavy lifting is done! Now you just need a way to manage your backups. Again, I like to use rsnapshot but there are a variety of other backup options on Linux that can utilize SSH like Amanda or backshift, though I have not personally tested those solutions.

The main advantage to this backup solution is simplicity and licensing (or the lack thereof). It enables you to use the same backup server for both *nix and Windows clients. If your backup server is joined to the domain, you could even use Samba to securely share read-only copies of backups back to your users, eliminating administrator intervention for trivial backup restorations.