== Overview == rsbackup Server is designed for multiple groups of remote clients to be backed up. Due to the way it was originally created, the group was called a "Company" and the individual client machines were simply called Servers. In the default configuration for rsbackup Server and rsc assumes a directory, somewhere on your server, which is secure. Under that directory will be various "Company Names" and under each of these will be various "Server Names". A common directory structure would be: /home/backups /home/backups/client1 /home/backups/client1/server1 /home/backups/client1/server2 /home/backups/client2 /home/backups/client2/server1 /home/backups/client2/server2 Where client1 and client2 are the modified names of the companies in question. I say modified because using spaces or other delimiters in the directory names is not recommended, has not been tested, and may rot your teeth. For 'Acme Bomb Disposal', you might use the CompanyName of 'AcmeBombDisposal'. This directory is only seen by your systems administrators, and is only used to help you identify the client. For the ServerName, I would suggest using a standard DNS eligible name (ie, server-1.acmebombdisposal.local). You will need both of these values to be consistent across the server and the client; that is one of the ways the client authenticates to the server. === Determine location for backups === I tend to put everything under /home/backups, which is a separate partition that is encrypted and has enough disk space to handle multiple versions of my client backups. You can mount it where you please; /backups, /var/backups, /xslkjffs. Makes no difference. Just set up a good, secure, redundant location someplace on the server. By the way, rsbackupServer works just fine on a Xen DOMU, which can mean your encrypted file system can be mounted remotely. It also means that you can use iSCSI, LVM or some other dynamic file system so your backup area can grow as your needs grow. === Security === The rsbackup Server is the server side portion of the rsBackup system. There are some security concerns about running this as follows: * Must run as root user * Must allow unattended ssh access * Must process scripts passed by remote client * Client data stored on server Each of these is a major security issue in that in an incorrectly configured system, they would give a user full access to the server were the security ever compromised. The following steps must be taken on the server prior to using rsbackup-server. These modifications are not automated, and must be done by hand. * rsyncd is NOT installed, or if installed, is disabled. * sshd port is set to a non-standard value * sshd root login allowed with forced commands only * sshd allowUsers set to a list of root plus system administrators ONLY * sshd only allows access via public/private key pair, for root and systems administrators * sshd turns off all other forms of access * root user creates ~/.ssh/authorized_keys file with public key of every server to be connected, and uses the special version forced commands only to validate request * all root communication authenticated by rsbackup_server * Ensure minimum permissions necessary on all scripts, libraries and configuration files. They should be owned by root, and limited to being run/edited/etc... by root * Encrypt your data store to keep physical access issues to a minimum * Turn off all services to outside access except ssh. == Installation Procedure (Debian only. Write me for other systems) == Add the following to /etc/apt/sources.list # # Daily Data Repository # deb http://debian.dailydata.net/debian_repository / Install via apt-get update apt-get install rsbackup-server === Setting Permissions === # Set access to the appropriate files as follows: # Ensure the rsbackup library has correct permissions chown root:root /usr/share/perl5/rsbackup.pm chmod 644 /usr/share/perl5/rsbackup.pm # set ownership and limit running of rsbackupServer script chmod 700 /usr/sbin/rsbackupServer chown root:root /usr/sbin/rsbackupServer # create .ssh directory for root, and set permissions mkdir /root/.ssh chown root:root /root/.ssh chmod 700 /root/.ssh touch /root/.ssh/authorized_keys chown root:root /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys # Ensure that the rsbackup configuration directory limited only to root chown -fR root:root /etc/rsbackup find /root/rsbackup -exec chmod 700 \{\} \; === edit the following files === ==== /etc/default/rsync ==== Ensure RSYNC_ENABLED is set to false ==== /etc/ssh/sshd_config ==== # make a backup of the sshd configuration files cp -av /etc/ssh/sshd_config /etc/ssh/sshd_config.save You should move sshd to an unknown port. Pick a number between 1024 and 65535. This is "security by obscurity" and, while it will not stop a determined cracker, it makes live more difficult for them. It does not matter what port you use, just pick a number. In the sshd config file below, change Port 22 to Port #####, whatever that number you chose was. Write the number down, because you will need it on every client you set up. NOTE: you can have sshd listen to multiple ports, simply by adding additional Port lines in the configuration. Doing that, you could modify rsbackup_server to require each remote client log in on a unique port. I have not implemented that, and most likely will not, but it is possible. I do use one port for backups, and another for administrative access simply because i can prioritize the administrative access port in my router and limit the speed of the actual backups. Port ###### PermitRootLogin forced-commands-only PubkeyAuthentication yes HostbasedAuthentication no PermitEmptyPasswords no ChallengeResponseAuthentication no PasswordAuthentication no X11Forwarding no UsePAM yes AllowUsers root list_of_administrators # Restart the sshd daemon. DO NOT LOG OUT OF THIS TERMINAL!!! /etc/init.d/ssh reload If logged in remotely, open a separate terminal window and log in via ssh. If you are able to log in, you are fine. If not, set sshd back the way it was: cp -av /etc/ssh/sshd_config_save /etc/ssh/sshd_config /etc/init.d/ssh reload And, figure out what went wrong. DO NOT proceed further until ssh is working correctly. Did you use the new port when you tried to ssh in? Did you copy your public key? Fix this, then proceed. === Check for other issues === Now, verify that there are no open ports detected on your server. From a remote machine, execute the following command: nmap servername # where servername is the DNS name or IP address of your server The only correct output would be: Starting Nmap 5.00 ( http://nmap.org ) at 2011-02-17 23:15 CST All 1000 scanned ports on servername are closed Nmap done: 1 IP address (1 host up) scanned in 2.65 seconds If there is anything else, your system is not secure and you must shut down ports. If you have an SMTP daemon on the server, you should tell it to listen only to localhost, not your public IP. == Configuring rsbackupServer == Edit /etc/rsbackup/rsbackup_server.conf. You should set values for the following $ERROR_TO = 'errors@example.com'; $DETAILS_TO = 'reports@example.com'; $SENDMAIL = "/usr/sbin/sendmail -t"; $REPLY_TO = 'Reply-to: "validate_rsync" '; $SUBJECT = "Subject: Possible Break-in - " . `hostname`; $FROM = 'From: "backupserver" '; # path and file name definitions $LOCAL_BACKUP_PATH = '/home/backups'; # the root of the backup path === Gather information from client === Once these are set, you are ready to begin a client install and verify function of the server. Perform a client install and gather the following information: * Client Name from client rsbackup.conf file * Server name from client rsbackup.conf file * Backup start time from client /etc/cron.d/rsbackup * Public key of client root * IP Address of client root === Adding the public key of a client server === Edit /root/.ssh/authorized_keys. Have your entire public key line from the client server ready. Create a new line as follows: command="/usr/sbin/rsbackupServer", public key line where public key line is the public key from the client machine. NOTE: the space between the comma and the beginning of the public key line is required. An example might be as follows. Note that I reduced the size of the key a lot so this would show up on one line. The 'AAAgEpaw' is actually a very, very long string. command="/usr/sbin/rsbackupServer", ssh-rsa AAAgEpaw== root@backup This can be different depending on what your client machine's public key looks like. === Adding client to /etc/rsbackup/rsbackup_server.conf === Now, we should add the client to /etc/rsbackup/rsbackup_server.conf. Open that file and go to the very bottom (well, it can be anywhere, but I put them all at the very bottom). If this is the first time you have created a backup for this Company (ie, the group), create an entirely new entry by adding the following block of text. I have used indentation to make things nicer, and included the comments from the config file examples. $user{ 'CompanyName' } = { 'ServerName' => { 'ip' => '192.168.0.1', # IP Address, or '' to ignore where they are coming from 'size' => 50, # Amount of disk space in gigabytes allowed 'prepare' => [ 'version' ], # list of any pre-processing routines to run 'cleanup' => [ 'getSizeOnDisk' ] # list of any post processing routines to be run } }; * Change 'CompanyName' to the Client Name from the client server. This is generally a client, or company name, and defines a group of backup servers. * Change 'ServerName' to the actual name of the client machine. Again, this must match the value in rsbackup.conf on the client machine. * Change 'ip' to the static IP Address your client will be coming from. If it is variable, you may change it to the empty string ('') or simply comment it out or delete the line. * Comment out 'size', 'prepare', 'cleanup' at this time, by placing a pound sign in front of them. For AcmeBombDisposal, and the server files.acmebombdisposal.com coming from IP address 10.111.56.9, the block in rsbackup_server.conf would be: $user{ 'AcmeBombDisposal' } = { 'files.acmebombdisposal.com' => { 'ip' => '10.111.56.9', # IP Address, or '' to ignore where they are coming from # 'size' => 50, # Amount of disk space in gigabytes allowed # 'prepare' => [ 'version' ], # list of any pre-processing routines to run # 'cleanup' => [ 'getSizeOnDisk' ] # list of any post processing routines to be run } }; To add a second client machine, say svn.acmebombdisposal.com, coming from 172.16.0.36, you would duplicate the server block and add it (separating by a comma). Your configuration file would then be $user{ 'AcmeBombDisposal' } = { 'files.acmebombdisposal.com' => { 'ip' => '10.111.56.9', # IP Address, or '' to ignore where they are coming from # 'size' => 50, # Amount of disk space in gigabytes allowed # 'prepare' => [ 'version' ], # list of any pre-processing routines to run # 'cleanup' => [ 'getSizeOnDisk' ] # list of any post processing routines to be run }, 'svn.acmebombdisposal.com' => { 'ip' => '172.16.0.36', # IP Address, or '' to ignore where they are coming from # 'size' => 50, # Amount of disk space in gigabytes allowed # 'prepare' => [ 'version' ], # list of any pre-processing routines to run # 'cleanup' => [ 'getSizeOnDisk' ] # list of any post processing routines to be run } }; To add a new client, Zoe's Pet Supplies (ZoePetSupplies), and their server meow.zoes.local on a dynamic IP address, add a completely separate entry at the bottom of the file. Your configuration file would then have the following: $user{ 'AcmeBombDisposal' } = { 'files.acmebombdisposal.com' => { 'ip' => '10.111.56.9', # IP Address, or '' to ignore where they are coming from # 'size' => 50, # Amount of disk space in gigabytes allowed # 'prepare' => [ 'version' ], # list of any pre-processing routines to run # 'cleanup' => [ 'getSizeOnDisk' ] # list of any post processing routines to be run }, 'svn.acmebombdisposal.com' => { 'ip' => '172.16.0.36', # IP Address, or '' to ignore where they are coming from # 'size' => 50, # Amount of disk space in gigabytes allowed # 'prepare' => [ 'version' ], # list of any pre-processing routines to run # 'cleanup' => [ 'getSizeOnDisk' ] # list of any post processing routines to be run } }; $user{ 'ZoePetSupplies' } = { 'meow.zoes.local' => { 'ip' => '', # IP Address, or '' to ignore where they are coming from # 'size' => 50, # Amount of disk space in gigabytes allowed # 'prepare' => [ 'version' ], # list of any pre-processing routines to run # 'cleanup' => [ 'getSizeOnDisk' ] # list of any post processing routines to be run } }; Note, this is Perl, where whitespace is (mostly) for the human viewing it. The above could be written: $user{'AcmeBombDisposal'}={'files.acmebombdisposal.com'=>{'ip'=>'10.111.56.9',},'svn.acmebombdisposal.com'=>{'ip'=>'172.16.0.36',}}$user{'ZoePetSupplies'}={'meow.zoes.local'=>{'ip'=>'',}}; and still work. Perl doesn't care, but the spaces and indentation does help the humans a lot. So, I would suggest using it. The lines that were commented out could actually be deleted, but after you get the configuration set up and working, we would uncomment them and set them to appropriate values. I will explain each of them in turn below. * 'size' is the amount of disk space, in gigabytes, that is alloted to the end user. You can then write a module that will report actual size and, whether they are getting low on allocated space or not. We will see that in the add on moduless section. * 'prepare' is a list of modules to be executed prior to starting the backup. * 'cleanup' is a list of modules to be executed after successful completion of the backup. Post v6.x versions of rsbackup client issue a 'prepare' command to the server before actually backing up, and a 'cleanup' command after successful completion. The modules you install can be from the list provided, or can be custom written modules to meet your needs. If more than one module is entered here (separated by comma's), they will be done in the order you enter them. Thus, if you had a module to make a copy of the client site prior to starting a new backup, you would enter that in the 'prepare' section. After the backup was complete, you might want to remove old versions (copies) and calculate how much space the client was using. Thus, your preapre adn cleanup lines could look like this: 'prepare' => [ 'version backup version' ], 'cleanup' => [ 'getSizeOnDisk', 'version_cleanup version 5' ] 'prepare' executes the module 'version' with the parameters 'backup' and 'version' (this is a real module, which is being passed the source directory, backup/, and the target directory, version/). After the backup is complete, two commands are executed; The first, getSizeOnDisk performs a 'du -sb' on the client directory (no parameters). After that is complete, another script, version_cleanup is executed with two parameters, 'version' and '5' (it removes anything in the version/ directory older than 5 days). == Modules == The balance between usefulness and security is difficult. Modules were clearly needed to extend the capabilities of rsBackup, yet anytime you allow third parties to create or use a module, you are giving them the ability to execute code AS ROOT on a sensitive installation. As such, the following limitations were placed on modules. * A module must reside in the $MODULE_DIR directory * The $MODULE_DIR directory must be owned by root:root, with permissions 0700 * Individual modules must be owned by root:root, with permissions 0700 * Parameters to modules should be relative to the backup path. The current backup path is sent to the module by three parameters available to any module. Thus, to calculate the size of a backup, you would pass no parameters; the three standard parameters would contain enough information. * Customized values may be included in rsbackup_server.conf file for each machine. These values can be read from the configuration file by a module for additional capabilities. * Other parameters will be passed unmodified to a module. There are several standard modules included with rsbackup Server. They are located in /usr/share/docs/rsbackup-server/examples, along with some utilities in subdirectories. These modules may be used by simply copying them to /etc/rsbackup/modules, and setting their permissions correctly, ie owned by root:root, with permissions 0700. An example would be: cp -av /usr/share/docs/rsbackup-server/examples/getSizeOnDisk /etc/rsbackup/modules chmod 700 /etc/rsbackup/modules/getSizeOnDisk chown root:root /etc/rsbackup/modules/getSizeOnDisk If the module is not in the modules directory, owned by root, with permissions 700, rsbackup_server will refuse to execute it. The pre-built modules are: * getSizeOnDisk - executes a 'du -sb $rootDir' and displays the result to STDOUT (where it is captured by the report of the rsbackup client) * version - requires two parameters, sourcedir and targetdir. Copies sourcedir to targetdir/yyyy-mm-dd as a hard linked list. Uses minimal disk space and results in a very efficient directory tree replicates the sourcedir. * version_cleanup - The sibling of version. Accepts two parameters, versiondirectory and dayToKeep. Will remove any versions older than daysToKeep (based on directory name, assumes subdirectories were created using version module). == Writing Customized Modules == You may feel free to write customized modules to perform any additional functions you want. If you think these modules would be useful beyond your own needs, please consider sending it to me for inclusion in future releases or posting on the wiki. Any output to STDOUT is captured by rsbackup_server and returned, unmodified to the rsbackup client on the client machine. rsbackup client then generally includes this output in its report. A module is simply an executable program that accepts a minimum of three parameters: my $rootDir - root of all backups my $client - client name. Assumed to be subdirectory of $rootDir my $server - server name. Assumed to be subdirectory of $client my $confDir - full path/filename to configuration file These are placed LAST, after any other parameters you may need. While you do not need to pass any additional parameters, or even use these, you may include additional parameters as needed. The additional parameters must be constants, read from the configuration file's 'prepare' or 'cleanup' entries. While it is possible to write bash, php, or even binary scripts, you have an advantage if you use perl for the modules in that you can include rsbackup.pm library. A basic script (with no parameters) would be: #! /usr/bin/perl -w require 'rsbackup.pm'; my $rootDir = shift; my $client = shift; my $server = shift; my $confDir = shift; die "Invalid Call, exiting" unless ( $rootDir && $client && $server && $confDir ); my $result; # a place to hold our return text, or you can simply print it inline ... do whatever processing you need print $result; # returned to rsbackup_server, which will return it to rsbackup on the client machine 1; # exit nicely The same code, but with two user supplied parameters would be: #! /usr/bin/perl -w require 'rsbackup.pm'; # get user supplied parameters first my $warningSize = shift; my $mailWarningsTo = shift; # read standard parameters my $rootDir = shift; my $client = shift; my $server = shift; my $confDir = shift; die "Invalid Call, exiting" unless ( $rootDir && $client && $server && $confDir ); my $result; # a place to hold our return text, or you can simply print it inline ... do whatever processing you need print $result; # returned to rsbackup_server, which will return it to rsbackup on the client machine 1; # exit nicely