• Stars
    star
    674
  • Rank 64,749 (Top 2 %)
  • Language
    Shell
  • License
    MIT License
  • Created about 7 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Rsync-based OSX-like time machine for Linux, MacOS and BSD for atomic and resumable local and remote backups

Linux Time Machine

Install | Uninstall | TL;DR | Features | How does it work | Restore | Retention | Usage | FAQ | Disclaimer | License

Linting Linux MacOS 10 MacOS 11 SSH Tag License

timemachine is a tiny and stable KISS driven and POSIX compliant script that mimics the behavior of OSX's timemachine. It uses rsync to incrementally back up your data to a different directory, hard disk or remote server via SSH. All operations are incremental, atomic and automatically resumable.

By default it uses the rsync options: --recursive, --perms, --owner, --group, --times and --links. In case your target filesystem does not support any of those options or you cannot use them due to missing permission, you can explicitly disable them via --no-perms, --no-owner, --no-group, --no-times, and --copy-links. See FAQ for examples.

Motivation

The goal of this project is to have a cross-operating system and minimal as possible backup script that can be easily reviewed by anyone without great effort. Additionally it should provide one task only and do it well without the need of external requirements and only rely on default installed tools.

🎉 Install

sudo make install

đŸšĢ Uninstall

sudo make uninstall

☕ TL;DR

Using POSIX.1-2008 argument syntax:

# Recursive, incremental and atomic backup (locally)
$ timemachine /source/dir /target/dir

# Recursive, incremental and atomic backup (via ssh)
$ timemachine /source/dir user@host:target/dir

# Recursive, incremental and atomic backup (via ssh with non-standard port)
$ timemachine --port 10000 /source/dir user@host:target/dir

# Append rsync options
$ timemachine /source/dir /target/dir -- --specials --progress
$ timemachine /source/dir /target/dir -- --specials --no-perms
$ timemachine /source/dir /target/dir -- --archive --progress

# Make the timemachine script be more verbose
$ timemachine -v /source/dir /target/dir
$ timemachine --verbose /source/dir /target/dir

# Make the timemachine script be even more verbose
$ timemachine -d /source/dir /target/dir
$ timemachine --debug /source/dir /target/dir

# Make the timemachine script and rsync more verbose
$ timemachine -v /source/dir /target/dir -- --verbose
$ timemachine --verbose /source/dir /target/dir -- --verbose

⭐ Features

Feature Description
SSH or local Local backups as well as backups via SSH are supported.
Incremental Backups are always done incrementally using rsync's ability to hardlink to previous backup directories. You can nevertheless always see the full backup on the file system of any incrementally made backup without having to generate it. This will also be true when deleting any of the previously created backup directories. See the Backups section for how this is achieved via rsync.

Incremental Backups also mean that only the changes on your source, compared to what is already on the target, have to be backed up. This will save you time as well as disk space on the target disk.
Partial When backing up, files are transmitted partially, so in case a 2GB movie file backup is interrupted the next run will pick up exactly where it left off at that file and will not start to copy it from scratch.
Resumable Not only is this script keeping partial files, but also the whole backup run is also resumable. Whenever there is an unfinished backup and you start timemachine again, it will automatically resume it. It will resume any previously failed backup as long as it finally succeeds.
Atomic [1] The whole backup procedure is atomic. Only if and when the backup procedure succeeds, it is then properly named and symlinked. Any non-successful backup directory is either waiting to be resumed or to be deleted.
  • [1] The backup process is atomic, but not the backup itself. rsync copies files as it finds them and in the meantime there could already be changes on the source. To achieve an atomic backup, either back up from a read-only volume or from a snapshot.

ℹī¸ How does it work?

Directory structure

The following directory structure will be created:

$ tree -L 1 /my/backup/folder
.
├── 2018-01-06__18-43-30/
├── 2018-01-06__18-44-23/
├── 2018-01-06__18-50-44/
├── 2018-01-06__18-50-52/
└── current -> 2018-01-06__18-50-52/

current will always link to the latest created backup. All backups are incremental except the first created one. You can nevertheless safely remove all previous folders and the remaining folders will still have all of their content.

Backup strategy

Except for the first one, backups are always and automatically done incrementally, so the least amount of space is consumed. Due to rsync's ability, every directory will still contain all files, even though they are just incremental backups. This is archived via hardlinks.

$ du -hd1 .
497M    ./2018-01-06__18-43-30
24K     ./2018-01-06__18-44-23
24K     ./2018-01-06__18-50-44
24K     ./2018-01-06__18-50-52
497M    .

You can also safely delete the initial full backup directory without having to worry about losing any of your full backup data:

$ rm -rf ./2018-01-06__18-43-30
$ du -hd1 .
497M    ./2018-01-06__18-44-23
24K     ./2018-01-06__18-50-44
24K     ./2018-01-06__18-50-52
497M    .

rsync and hardlinks are magic :-)

Failure handling and resume

In case the timemachine script aborts (self-triggered, disk unavailable or for any other reason) you can simply run it again to automatically resume the last failed run.

This is due to the fact that the backup process is atomic. During a non-complete run, all data will be stored in a directory named .inprogress/. This will hold all already transferred data and will be picked up during the next run. Once the backup is complete, it will be renamed and symlinked to current.

$ tree -a -L 1 /my/backup/folder
.
├── .inprogress/
├── 2018-01-06__18-43-30/
├── 2018-01-06__18-44-23/
├── 2018-01-06__18-50-44/
├── 2018-01-06__18-50-52/
└── current -> 2018-01-06__18-50-52/

â™ģī¸ Restore

No special software is required to restore your data. Backed up files can be easily browsed and thus copied back to where you need them. Recall the backup directory structure:

$ tree -L 1 /my/backup/folder
.
├── 2018-01-06__18-43-30/
├── 2018-01-06__18-44-23/
├── 2018-01-06__18-50-44/
├── 2018-01-06__18-50-52/
└── current -> 2018-01-06__18-50-52/

Chose a backup directory and simply copy them to where you need it:

# Test it out in dry run mode before applying
$ rsync --archive --progress --dry-run /my/backup/folder/2018-01-06__18-50-52/ /src/

# Apply restoration
$ rsync --archive --progress /my/backup/folder/2018-01-06__18-50-52/ /src/

🔁 Retention

As decribed above this project is KISS driven and only tries to do one job: back up your data.

Retention is a delicate topic as you want to be sure that data is removed as intended. For this there are already well-established tools that do an excellent job and have proven themselves over time: tmpreaper and tmpwatch.

🔒 Reliability

Linting Linux MacOS 10 MacOS 11 SSH

The script is written and maintained with maximum care. In order to retain a reliable and stable backup solution, a lot of effort goes into a vast amount of integration and regression tests. These tests not only give you measurable confidence, but also help new contributors to not accidentally introduce new or old bugs.

đŸ’ģ Usage

Available options

$ timemachine -h

Usage: timemachine [-vd]   <source> <dest> -- [rsync opts]

       timemachine [-vdpi] <source> <host>:<dest>        -- [rsync opts]
       timemachine [-vdpi] <source> <user>@<host>:<dest> -- [rsync opts]
       timemachine [-vdpi] <source> <ssh-alias>:<dest>   -- [rsync opts]

       timemachine [-vdpi] <host>:<source>        <dest> -- [rsync opts]
       timemachine [-vdpi] <user>@<host>:<source> <dest> -- [rsync opts]
       timemachine [-vdpi] <ssh-alias>:<source>   <dest> -- [rsync opts]

       timemachine -V, --version
       timemachine -h, --help

This shell script mimics the behavior of OSX's timemachine.
It uses rsync to incrementally back up your data to a different directory or remote server via SSH.
All operations are incremental, atomic and automatically resumable.

By default it uses --recursive --perms --owner --group --times --links.
In case your target filesystem does not support any of those options, you can explicitly
disable those options via --no-perms --no-owner --no-group --no-times and --copy-links.

Required arguments:
  <source>              Local source directory
  <dest>                Local destination directory.
  <host>:<dest>         SSH host and source/destination directory on server
  <user>@<host>:<dest>  SSH user, SSH host and source/destination directory on server
  <ssh-alias>:<dest>    SSH alias (defined in ~/.ssh/config) and source/destination directory on server

Options:
  -p, --port            Specify alternative SSH port for remote backups if it is not 22.
  -i, --identity        Specify path to SSH key.
  -v, --verbose         Be verbose.
  -d, --debug           Be even more verbose.

Misc Options:
  -V, --version         Print version information and exit
  -h, --help            Show this help screen

Examples:
  Simply back up one directory recursively
      timemachine /home/user /data
  Do the same, but be verbose
      timemachine -v /home/user /data
  Append rsync options and be very verbose
      timemachine -d /home/user /data -- --progress --verbose
  Log to file
      timemachine -v /home/user /data > /var/log/timemachine.log 2> /var/log/timemachine.err

Documentation:
  View more examples at: https://github.com/cytopia/linux-timemachine

Use with cron

The following can be used as an example crontab entry. It assumes you have an external disk (NFS, USB, etc..) that mounts at /backup. Before adding the crontab entry, ensure the filesystem in /backup is mounted and use:

$ touch /backup/mounted

This guards against accidentally backing up to an unmounted directory

Next, add the following to crontab using crontab -e as whichever user you intend to run the backup script as. You may need to place this in the root crontab if you are backing up sensitive files that only root can read

0 2 * * * if [[ -e /backup/mounted ]]; then /usr/local/bin/timemachine /home/someuser /backup; fi

This will cause timemachine to run at 2AM once per day. Since timemachine keeps track of backups with granularity up to the hour, minute and second, you could have it run more than once per day if you want backups to run more often.

💡 FAQ

Should I add trailing directory slashes (/)?

Trailing directory slashes only matter for the source directory and will not make a difference if added to the destination directory.

# The following backs up the contents of the src directory
$ timemachine src/ dst/
$ tree -L 2 /dst
.
├── 2018-01-06__18-43-30/
│   └── file.txt
└── current -> 2018-01-06__18-43-30/
# The following backs up the the src directory itself
$ timemachine src dst/
$ tree -L 3 /dst
.
├── 2018-01-06__18-43-30/
│   └── src
│       └── file.txt
└── current -> 2018-01-06__18-43-30/

How to dry-run the backup?

$ timemachine src/ dst/ -- --dry-run

How to use a non-standard SSH port?

$ timemachine --port 1337 src/ user@host:dst/

How to use SSH aliases from ~/.ssh/config?

$ cat ~/.ssh/config
Host my-ssh-alias
  HostName     192.168.0.1
  Port         1234
  User         john
  IdentityFile ~/.ssh/id_rsa__alternative_key
$ timemachine src/ my-ssh-alias:dst/

How to speed up remote backups?

# With  this option, rsync compresses the file data as it is sent to the des‐
# tination machine, which reduces the amount of  data  being  transmitted
$ timemachine src/ user@host:dst/ --compress

How to preserve ACLs?

$ timemachine src/ dst/ -- --acls

How to preserve extended attributes?

$ timemachine src/ dst/ -- --xattrs

How to disable preserving file and directory permissions?

$ timemachine src/ dst/ -- --no-owner --no-perms

How to disable preserving modification time?

$ timemachine src/ dst/ -- --no-times

How to copy the content instead of a symlink?

# This is useful in case your file system does not support symlinks.
# It is recommended to read rsync man page about symlinks to be sure
# about what you are doing
$ timemachine src/ dst/ -- --copy-links --safe-links
$ timemachine src/ dst/ -- --copy-links --safe-links --keep-dirlinks

How to ensure all files in the back up have the ownership of current user?

# Regardless of who owns the files, ensure the backup has uid and gid of current user
# This will only work if you have read-permission on all files.
$ timemachine src/ dst/ -- --no-owner --no-group

# If you do not have permission to read all files, you require sudo or root permission.
# The following will instruct rsync to ensure the backed up data has the uid and gid
# of the desired user.
$ sudo timemachine src/ dst/ -- --chown=<user>:<group>

❗ Disclaimer

Backups are one of the most important things. We all care about our data and want it to be safe, so do not blindly trust scripts when it comes to backups! Do review the code, it is not too complex and kept as short as possible. Have a look at how much effort goes into the integration tests to provide measurable stability.

Learn about rsync it is a very powerful tool and you might even be able to just use this for backups.

There are many other backup solutions out there that might be a better fit for your needs. Do your own research, look at GitHub issues, source code, integration tests and try them out as well.

:octocat: Contributing

See Contributing guidelines to help to improve this project.

📄 License

MIT License

Copyright (c) 2017 cytopia

More Repositories

1

devilbox

A modern Docker LAMP stack and MEAN stack for local development
PHP
4,153
star
2

ffscreencast

ffscreencast - ffmpeg screencast/desktop-recording with video overlay and multi monitor support
Shell
1,742
star
3

pwncat

pwncat - netcat on steroids with Firewall, IDS/IPS evasion, bind and reverse shell, self-injecting shell and port forwarding magic - and its fully scriptable with Python (PSE)
Shell
1,624
star
4

awesome-ci

Awesome Continuous Integration - Lot's of tools for git, file and static source code analysis.
Shell
322
star
5

badchars

Bad char generator to instruct encoders such as shikata-ga-nai to transform those to other chars.
Python
221
star
6

docker-ansible

Alpine-based multistage-build version of Ansible for reproducible usage in CI
Makefile
188
star
7

urlbuster

Powerful mutable web directory fuzzer to bruteforce existing and/or hidden files or directories.
Python
152
star
8

mysqldump-secure

[sh] Encrypted mysqldump script with compression, logging, blacklisting and Nagios/Icinga monitoring integration
Shell
141
star
9

thunar-custom-actions

Custom actions for Thunar (or Nautilus) File manager
Shell
135
star
10

ansible-debian

Buildfiles: Ansible automated leight-weight and sensible Debian provisioning
Jinja
86
star
11

smtp-user-enum

SMTP user enumeration via VRFY, EXPN and RCPT with clever timeout, retry and reconnect functionality.
Python
83
star
12

coinwatch

Coinmarketcap console client to keep track of your crypto currency trades - are you winning or losing?
Python
78
star
13

docker-bind

Bind (bind9) caching DNS server on Alpine or Debian with wild-card domain support [multi-arch]
Shell
77
star
14

docker-terraform-docs

Alpine-based multistage-build version of terraform-docs and terraform-docs-replace in multiple versions to be used for CI and other reproducible automations
HCL
60
star
15

crawlpy

Scrapy python crawler/spider with post/get login (handles CSRF), variable level of recursions and optionally save to disk
Python
55
star
16

aws-export-profile

Export AWS profiles to your shell environment
Shell
46
star
17

docker-dvwa

Docker Compose setup for DVWA with all available PHP versions
Makefile
44
star
18

ansible-role-cloudformation

Ansible role to render an arbitrary number of Jinja2 templates into cloudformation files and create any number of stacks.
Python
43
star
19

aws-export-assume-profile

Export AWS profiles to your shell environment
Shell
41
star
20

i3blocks-modules

Custom modules for i3blocks status bar
Shell
40
star
21

docker-terragrunt

Alpine-based multistage-build version of Terragrunt and Terraform for reproducible usage in CI
Makefile
40
star
22

fuzza

Customizable TCP fuzzing tool to test for remote buffer overflows.
Python
32
star
23

docker-yamllint

Alpine-based multistage-build of yamllint for reproducible usage in CI
Makefile
30
star
24

autorunner

Configurable and notification aware autostart helper for minimalistic window managers like i3, openbox and others
Shell
29
star
25

check_drupal

[sh] Nagios drupal plugin to monitor the state of a drupal site (or multisite) for security updates, core errors and more
Shell
27
star
26

ansible-role-k8s

This role render an arbitrary number of Jinja2 templates and deploys or removes them to/from Kubernetes clusters.
Python
26
star
27

makefiles

Makefile
25
star
28

redmine-like-a-boss

[sh] Simple redmine installation with plugins and themes
Shell
25
star
29

linkcheck

Search for URLs in files (optionally limited by extension) and validate their HTTP status code
Shell
23
star
30

aws-ec2-sg-exporter

A dockerized Prometheus exporter that compares desired/wanted IPv4/IPv6 CIDR against currently applied inbound CIDR rules in your security group(s).
Shell
22
star
31

kusanagi

Kusanagi is a bind and reverse shell payload generator with obfuscation and badchar support.
Python
21
star
32

metrics-server-prom

Prometheus adapter to scrape from Kubernetes metrics-server
Python
21
star
33

docker-black

Alpine-based multistage-build version of Python Black for reproducible usage in CI
Roff
20
star
34

ansible-modules

Custom ansible modules
Python
18
star
35

terraform-aws-iam

This Terraform module manages AWS IAM to its full extend.
HCL
18
star
36

dotfiles

dotfiles
Shell
17
star
37

docker-phpcs

Alpine-based multistage-build version of phpcs for reproducible usage in CI
Makefile
16
star
38

kali-openbox-menu

Kali-Linux menu for openbox
16
star
39

docker-php-cs-fixer

Alpine-based multistage-build version of php-cs-fixer for reproducible usage in CI
Makefile
16
star
40

git-rewrite-author

[sh] Rewrite git author and committer history (locally and remotely)
Shell
16
star
41

docker-ansible-lint

Alpine-based multistage-build version of ansible-lint for reproducible usage in CI
Makefile
14
star
42

awesome-nagios-plugins

A curated list of awesome nagios plugins
13
star
43

nginx-certwatch

[sh] certwatch cron implementation for nginx vhosts
Shell
13
star
44

docker-file-lint

Alpine-based Docker image to perform generic file checks on your source code in order to improve consistency within your repository (e.g. for easy usage in CI).
Shell
12
star
45

terraform-aws-route53-zone

A Terraform module that handles creation of multiple Route53 zones including attachment to new or existing delegation set
HCL
12
star
46

slidocli

Command line utility to list available questions on sli.do and automatically upvote any question specified by their id.
Shell
11
star
47

ansible-module-diff

Ansible module to diff strings, file contents or command outputs against each other
Python
11
star
48

yolo

discover new commands
Shell
10
star
49

docker-gofmt

Alpine-based multistage-build version of gofmt for reproducible usage in CI
Shell
9
star
50

check_php

[sh] Nagios plugin for PHP to check for startup errors, missing modules, wrong php.ini configurations and PHP updates.
Shell
9
star
51

ultimate-shell-template

The ultimate shell template with optional GUI support
Shell
9
star
52

check_git

Nagios plugin to monitor the state of a git repository: clean, branch, tag, gpg verified etc
Shell
9
star
53

ansible-role-aws_account_match

Ansible safe-guard role to ensure you are currently using the correct AWS account(s)
9
star
54

docker-pylint

Alpine-based multistage-build version of pylint for reproducible usage in CI
Makefile
9
star
55

header-fuzz

header-fuzz allows you to fuzz any HTTP header with a wordlist and evaluate success or failure based on the returning HTTP status code.
Shell
9
star
56

letsencrypt-watch

[sh] certwatch cron implementation for letsencrypt certificates
Shell
9
star
57

lsl

Colorful file labels for you terminal which are displayed in ls output.
Shell
8
star
58

docker-eslint

Alpine-based multistage-build version of eslint for reproducible usage in CI
Makefile
8
star
59

docker-yamlfmt

Alpine-based multistage-build version of yamlfmt for reproducible usage in CI
Makefile
8
star
60

docker-golint

Alpine-based multistage-build version of golint for reproducible usage in CI
Makefile
8
star
61

i3-utils-bin

Shell
7
star
62

docker-phplint

Alpine-based version of PHP for linting and reproducible usage in CI
Makefile
7
star
63

docker-linkcheck

Alpine-based multistage-build version of linkcheck for reproducible usage in CI
Makefile
7
star
64

docker-mypy

Alpine-based multistage-build version of Python mypy for reproducible usage in CI
Roff
6
star
65

terraform-aws-iam-cross-account

This Terraform module creates AWS cross-account assumable roles with multiple polcies to be specified via files
HCL
6
star
66

ansible-filter-get_attr

Ansible filter to have variable substitution in keys and values inside dictionaries
Python
6
star
67

docker-bandit

Alpine-based multistage-build version of bandit for reproducible usage in CI
Makefile
6
star
68

docker-terragrunt-fmt

Alpine-based multistage-build version of terragrunt-fmt to be used for CI and other reproducible automations
Shell
6
star
69

docker-jsonlint

Alpine-based multistage-build version of jsonlint with file globbing search for reproducible usage in CI
Makefile
6
star
70

docker-phpcbf

Alpine-based multistage-build version of phpcbf for reproducible usage in CI
Makefile
6
star
71

yii-check-translations

Shell script to check/validate yii translations in various folders
PHP
5
star
72

docker-goimports

Alpine-based multistage-build version of goimports for reproducible usage in CI
Shell
5
star
73

check_http_expect

[sh] Nagios plugin that will check a website (behind .htacess and/or behind POST login) for an expected string or regex expression.
Shell
5
star
74

vault-auto-unseal

HashiCorp Vault auto-unseal
Shell
5
star
75

jsparsy

Scan urls for javascript run-time errors
JavaScript
5
star
76

docker-checkmake

Alpine-based multistage-build version of checkmake for reproducible usage in CI
Makefile
5
star
77

dotfiles-kali

Shell
4
star
78

git-ids

Use git as an intrusion detection system for your servers
4
star
79

sweany

Sweany is a performance-orientated, self-validating and feature-rich MVC framework for PHP
PHP
4
star
80

terraform-aws-elb

This Terraform module creates an ELB with optionally a public and/or private Route53 DNS record attached to it.
HCL
4
star
81

docker-pycodestyle

Alpine-based multistage-build version of pycodestyle for reproducible usage in CI
Makefile
4
star
82

upload-artifact-verify-action

4
star
83

upload-artifact-retry-action

This action allows you to upload an artifact with retries in case the upload has failed. It wraps upload-artifact-verify-action and retries it
4
star
84

freebsd-tools

[sh] FreeBSD script collection
Shell
3
star
85

i3-utils

Some tools I use for my i3 setup
3
star
86

ecss

Exteended CSS (ECSS) is a preprocessor that easily adds constants and inheritance (single, multiple & recursive) as a language construct
PHP
3
star
87

docker-tag-action

GitHub Action to create Docker tag based on git branch or git tag
3
star
88

prometheus-redbox_exporter

Prometheus exporter that throws stuff to httpd endpoints and evaluates their response
Python
3
star
89

terraform-aws-rds

Remake of terraform-aws-modules/terraform-aws-rds without sub-modules
HCL
3
star
90

docker-pydocstyle

Alpine-based multistage-build version of pydocstyle for reproducible usage in CI
Makefile
2
star
91

asm

Assembly
2
star
92

git-tools

Shell
2
star
93

tools

Various cli tools
Shell
2
star
94

i3-utils-systemd

Makefile
2
star
95

check_mysqldump-secure

[sh] Nagios Plugin to monitor mysqldump database backups
Shell
2
star
96

docker-kubeval

Alpine-based multistage-build version of kubeval for reproducible usage in CI
Makefile
2
star
97

homebrew-tap

[ruby] Cytopia's homebrews
Ruby
2
star
98

download-artifact-retry-action

2
star
99

git-ref-matrix-action

This composite action creates a stringified JSON list of git refs to be used as a build matrix.
2
star
100

terraform-aws-iam-roles

This Terraform module creates an arbitrary number of IAM roles and policies/trusts to attach.
HCL
2
star