
# babackup

Babackup is a tool providing secure, time-traveling backup via ssh and rsync.
It has the following goals:

- No mysteries: It uses standard tools (rsync, ssh), 
    and storage formats (the file system)
    so it's easy to inspect what's going on,
    verify it's happy, and recover from the unexpected.
    
- High security:  Remote access is limited, so compromise of either
    a client or the server have a limited blast radius.
    
    Compromise of a client can at most cost the current and
    immediately prior backup, but cannot spread to remote access of
    the server or the entire backup history.
    
    Compromise of the server cannot spread to remote access of
    clients.  However, the server has a clear-text backup of the data
    from the client, so the data may be disclosed.

    Both the client and server sides can run with or without
    privilege.  With privilege (as root), file user and permissions
    are preserved.
    
    For these reasons, the both the client and the server can be 
    considered "high security" machines, but compromise of either
    will not spread to the other.
    
- History:  One can walk back history, time-machine like.  History is
    adaptively aged so we remember a lot about the near past and some
    about the far past.

- Storage efficiency:  Backups are de-duplicated, so if nothing
    changes from day to day, the incremental storage cost is minimal.
    
    Old backups are kept, with several recent ones and fewer old ones.

We expand on how we accomplish these goals in
["Technical Details"](#Technical Details) below.

## Why use babackup?

It provides a secure, mostly turn-key backup approach
that smooths over many rough edges.
    



# Using Babackup

## Normal Operation

On the client, run `babackup` periodically
(say, from cron).  That will see when backups last run, and run a new
one if it's been more than a day.  This side pushes a new, incremental
backup to the server.

Cron entries should run as each user that has a babackup.
A typical client-side cron entry would be:

    5 * * * * /usr/bin/babackup

Babackup reads its default client configuration from 
`~/.config/babackup/client.yaml` or `/etc/babackup/client.yaml`
(when run as root).

On the server, run `babackup_server` 
frequently (say, every 10 or 15 minutes) by each user.  It will detect when a
new backup has completed and prepare for the next one.
It will also periodically (daily) look over old backups and age them
out.  (Server-side configurations are in `server.yaml`.)

Cron entries much run on the server as each user that manages backups.
A typical server-side cron entries is:

    1,16,31,46 * * * * /usr/sbin/babackup_server

As a help, `babackup` and `babackup_server` 
remind one about these when a new backup is created.


## New Backups

### New Backups: On the Client

To **start backing up a new partition**, run

    babackup --name=my_source --new-path=/client/backup/source/ --new-server=serveruser@serverhost:server-side/storage/location --new-mode=rrsync
    
on the client. 
This command will add the new backup path to the
client configuration, and print out a command (described below) 
to run on the server-side. 
It gives the backup a name (here `my_source`)
to track this pairing.

Client-side setup updates the configuration
files so future runs know what to do.
It also generates a new, passwordless ssh key
to use for this backup.

Paths follow rsync conventions, so it should end in "/" to back up the
directory contents.  One can have multiple `--new-path` entries to
handle several things, but then the last component should be unique
and not end in a slash.  Server-side paths are relative to the
serveruser's home directory.  Both client and server paths may be
absolute.

Another useful option is `--new-exclude-from=/path/to/list.exclusion`,
which gives an rsync-style exclusion file of filenames to *not* skip.

Finally, remember that *you must run `babackup` periodically*
on the client, as described above in "Normal Operation".


### New Backups: On the Server

After generating a new backup on the client side,
the client will show a command to run on the server to set it up there.
Cut-and-paste what it tells you to run on the server side
and run it there as serveruser.

On the server side, that command installs the ssh key with an rsync
limitation to the backup directory,
and updates server-side configuration files so it knows
to watch the new backup,
and it initializes the storage location.

(You need to run-the server-side command in all cases,
even if you are using "local" mode.)

Finally, remember that *you must run `babackup_server` periodically*
on the server, as described above in "Normal Operation".


### Alternative Modes

Each new backup must have a mode
xxx


# Technical Details

Some technical details about how we meet our goals.

## Security

For security, all client-to-server remote access is done over ssh, 
protecting from eavesdropping and limiting remote access.

The server-side uses rrsync to limit remote access to writing to
the backup directory.  Therefore the client has no remote shell access
to the server, and the server has no access to the client.

This model means the client can use passwordless-ssh keys without
concern that an attacker can gain lateral movement between hosts.

However, as an additional layer, we generate and save passwords
for our keys.  This protects the keys on-disk from a naive attacker,
since it requires knowledge of babackup to extract a key's password.
While this layer protects against script kiddies,
rrsync is provides stronger technical protection.

Specifically: an attacker who compromises a client machine can corrupt
the current and a recent backup.  They can run a compromised backup
and fill up the server's disk.  They CANNOT eliminate
archived backups (those older then the current backup).  However, if they run
compromised backups daily, they will slowly age out old good backups.
(But slowly, because of our aging policy.)

Data restoration (that is: server-to-client data movement) is handled
out-of-band.  The client and the server users may be different people,
and we assume they can communicate out of band to do data recovery.

(Alternatively, a second ssh key could allow client-to-server
read-only access to data archive, to allow data recovery without
intervention from the server operator.)

## Data storage: simplicity, history, and efficiency

For simplicity and history of data storage, backups just go to the
file system.  Each day is in a separate date-stamped directory tree
(like Plan 9 backups, or Apple Time Machine).

For history, we age out old backups.  We age by day, week, month, and
year.  Typically we keep the N most recent backups for each tier, with
backups at each tier at least that duration apart.  Thus a fully
populated archive of daily backups will have up to 40 backups:  the 10
most recent days, then one per week for 10 weeks, then one per month
for 10 months, and finally one per year for 10 years.

For efficiency, backups use hardlinks for unchanged files, so they are
de-duplicated (an unchanged file takes nearly no extra space from day
to day).  (Hard links are managed by the rsync --link-dest option.)

## Alternatives

In a slightly better world we would encrypt backups before leaving the
client, allowing the server to be untrusted.  This approach was not
chosen because it lot more client-side infrastructure, making it
impossible to use unmodified rsync.


# History

## Release History

- 1.0 2024-01-14 First public release.

- 1.1 2024-01-15 Improve handling of --new-mode={rrsync,ssh}

- 1.2 2024-01-16 Correct handling of archive cleanup and shake out bugs.

- 1.3 2024-01-17 Ssh key now has a passphrase, and archive is now daily/etc.

- 1.4 2024-01-17 Given ssh a passphrase requires sshpass.

- 1.5 2024-01-19 One can now sync a list of paths with multiple --new-path.

- 1.6 2024-01-20 Add --new-mode=local and check for crontab entries.

- 1.7 2024-01-20 Fix some critical typos in babackup_server.

- 1.8 2024-01-22 Add --new-conditional-v4router and -new-conditional-v6router to constrain when backups run.

- 1.9 2024-01-23 Fix bugs in conditionals.

- 1.10 2024-01-23 More reobust handling of starting new users.

- 1.11 2024-01-24 Fix typo.

- 1.12 2024-01-24 rmtree cleanup.

- 1.13 2024-01-24 Fix bug in moving to archive (incorrect whitespace!).

- 1.14 2024-01-24 A test suite to avoid typo releases, and check for host key on startup.


## Ancient History

A first version of these ideas (rsync and a link-dest tree, inspired
by a post on the Internet pointing out the power of link-dest) was
deployed in 1999 by John Heidemann to back up his laptop.  This
version was mostly shell scripts (with more shell scripts for
configuration files), but most configuration was done by hand.
(Inspired by Ken Thompson, "the experienced user will usually know
what to configure".)

Around 2015 Yuri adapted these scripts for lab use.

In 2024 I rewrote the shell scripts in python to take over
configuration, and to enable an rrsync-protected mode.
(In response to an increased security threat of lateral movement via
passwordless ssh keys, the need to backup a semi-trusted laptop,
and the need to have high security clients and backup servers
that are still outside the "compromise" blast radius.

# INSTALLATION

Sigh, it doesn't currently use any of the standard python tools.

To install:

    make install
    
or

    make install DESTDIR=/usr/local
    
Also 

    make test
    


    
    
