A restic client written in rust

@MichaelEischer only started working on adding compression a few weeks ago

I also thought about the name and decided to let it as it is. The official name is actually “rustic-rs” which is also the crate name. I think that in the future the code will be separated in a library crate which provides all the functionality and a binary crate providing one ore more small binaries.

At the moment I’m trying to convert the logic to async Rust. That will be the next step in order to use async http client libraries and will allow to implement more backends.

About new features: Let me take to opportunity to advertise some of the existing new features. The backup command is already fully working:

alex@debian:~$ ./rustic-rs backup --help
rustic-rs-backup 
backup to the repository

USAGE:
    rustic-rs --repository <REPOSITORY> backup [OPTIONS] <SOURCE>

ARGS:
    <SOURCE>    backup source

OPTIONS:
        --exclude-if-present <FILE>    Exclude contents of directories containing filename (can be
                                       specified multiple times)
    -f, --force                        Use no parent, read all files
    -g, --glob <GLOB>                  Glob pattern to include/exclue (can be specified multiple
                                       times)
        --git-ignore                   Ignore files based on .gitignore files
        --glob-file <FILE>             Read glob patterns to exclude/include from a file (can be
                                       specified multiple times)
    -h, --help                         Print help information
        --iglob <GLOB>                 Same as --glob pattern but ignores the casing of filenames
        --iglob-file <FILE>            Same as --glob-file ignores the casing of filenames in
                                       patterns
    -n, --dry-run                      Do not upload or write any data, just show what would be done
        --parent <SNAPSHOT>            Snapshot to use as parent
        --with-atime                   Save access time for files and directories
    -x, --one-file-system              Exclude other file systems, don't cross filesystem boundaries
                                       and subvolumes

Note the *glob* options which allow include/exclude patterns and the --git-ignore option.

Also as a small improvement the number of nodes and total (restore) size of a snapshot is saved in the snapshots:

alex@debian:~$ ./rustic-rs -r /path/to/repo -p /path/to/key snapshots
 ID       | Time                | Host   | Tags | Paths                   | Nodes |      Size 
----------+---------------------+--------+------+-------------------------+-------+-----------
 a4c05cdd | 2022-03-06 23:31:16 | debian |      | /home2                  |     ? |         ? 
 760a8508 | 2022-03-06 23:40:22 | debian |      | /home2                  |   232 | 276.9 MiB 

The first snapshot was made by restic, the second by rustic (using the first as parent).

Of course it is much more easy to build a second implementation and early add some features there when there is always the reference implementation at hand.
But I hope we can use this second implementation to get benefits in both directions.

This could cause confusion: There is already a rustic which is a restic wrapper written in rust.

2 Likes

Here is an update of what changed in rustic.

Actually I’m about to prepare a 0.2 release which features:

Happy to get feedback in form of bug reports, feature requests or PRs on the github page!

2 Likes

I made a pre-release 0.2.0rc1 which contains the following changes:

  • new commands: init, forget, prune, repoinfo, tag, key
  • allow parallel lock-free repo access including prune
  • added REST backend
  • add compression support
  • most operations are now parallelized (using async rust)
  • added more statistical information to snapshots
  • now uses the same JSON format for trees/nodes as restic
  • better progress bars
  • various small fixes

I’m looking for beta testers! A binary for linux is available at the link above, but you can of course also simply compile it yourself.

I just released rustic 0.2.0.
Binaries will follow soon.

If you have any comments or questions about rustic, feel free to join the discussions on github. I’m especially interested in which features you think should be implemented next.

2 Likes

rustic 0.2.1 has just been released

rustic 0.2.2 has just been released

Some new features to mention:

  • rustic now supports rclone and via rclone all remote storages which are supported by rclone
  • rustic now supports cold storages (see e.g. Backup to AWS S3 Glacier) if an additional “hot repo” is specified
  • rustic now allows to specify or change some parameters in the config file via the init or the new config command
  • rustic now allows to customize pack sizes (see e.g. Control the minimal pack files size)

Help is needed to improve rustic further; you can help by

2 Likes

rustic 0.3.0 has just been released

Changes worth to note are:

  • rustic should be now fully compatible with restic. This means repos generated by (recent) restic can be used by rustic and vice-versa
  • rustic no longer uses temporary files but stores in-progress packfiles in-memory
  • restore checks present files and skip them during restore if they are valid; this makes restore resumeable
  • option restore --delete to delete files not in snapshot from restore destination

If you want to know more or have a question, join the rustic discussions!

2 Likes

Does this include compressed repos with version 2?

Yes, support for compressed repos with version 2 was introduced with rustic 0.2.0.

Actually version 2 is the standard when creating a repo with rustic. You have to use rustic-rs init --set-version 1 if you want a version repo.

1 Like

rustic 0.3.1 has just been released.

Some new features which are worth mentioning:

  • rustic now uses the binary name rustic
  • rustic now supports client configuration in config files, see rustic/examples at main · rustic-rs/rustic · GitHub
  • rustic snapshots now summarizes identical snapshots in one line in the output
  • rustic backup now supports much more options which are known by restic

For more information or discussions about rustic’s features, please visit

2 Likes

Out of curiosity, have you compared between Restic and Rustic performance?


I do not find rustic-rs in the Arch-User-Repository (AUR), but there is other old rustic as restic wrapper.

I did some comparisons with my repositories with the result that rustic generally uses less resources (memory, CPU time) than restic. Note that, however, rustic is not yet fully parallelized, so some operations which highly benefit from parallelization perform faster on restic if you have some CPU cores at hand.

Feel free to do your own tests or a qualified comparison and report at the rustic discussions or issues.

Note that rustic compiles to a single binary with no or only standard dynamic library dependencies. You can either use a pre-compiled version (see the rustic github page) or compile it yourself by doing:

  • install rust (https://rustup.rs/)
  • download or git clone the source code
  • run cargo build -r
1 Like

rustic 0.3.2 has been released.

Some features worth mentioning:

  • the logging has been completely overworked and now supports log levels and logging to a log file
  • the restore command with log-level debug now allows to exactly see differences between a snapshot and your local files (note that a --dry-run is also present).

For more information or discussions about rustic’s features, please visit

How many lines of code are rustic and restic? And how long did they take you guys to write that code?

Restic is very popular and has many developers on GitHub, around 300. I don’t know to what extent they are involved, but the numbers are large. For rustic I imagine this is far fewer, seems to be 7 people, so you have to mostly write the code?

@Eli6 I have already answered the lines of code question here. Currently, rustic is at about 8.500 lines of code.

About contributors, see

and

TL;DR: restic has 2-4 core developers, rustic so far only me. BTW: I’m looking forward to getting more people involved in rustic :wink:

Interesting that you got to implement it in about 10% of the Go code. I thought Rust is lower level and should take more code than Go for the same functionality.

In my experience the opposite is the case: Rust allows a much higher level of abstraction than Go does. This results in shorter and “cleaner” code. A good example is the error handling, which in Go is something like:

x, err :=  a.func()
if err != nil {
   return err
}

y, err := x.func2()
if err != nil {
   return err
}

while in Rust it reads:

let y = a.func()?.func2()?;
1 Like

I’m happy to announce rustic 0.4.0

New features worth mentioning are:

  • backup option --as-path allows to overwrite the path which is saved in a snapshot
  • Snapshots are extended by label, a description and “created by program”
  • labels allow to group snapshots (and to define parent snapshots for backup) additional to hosts and paths
  • diff now allows to compare dirs in snapshots with local dirs
  • New command repair. rustic repair index is basically the equivalent to restic rebuild-index wheras rustic repair snapshots does what you can only do with restic by compiling Add repair command by aawsome · Pull Request #2876 · restic/restic · GitHub. Note that rustic binaries are available if you need that command to repair a restic repo.

For more information or questions/discussions about this rustic release, please visit rustic 0.4.0 · Discussion #306 · rustic-rs/rustic · GitHub

1 Like