Is there any specific reason why Go was chosen to write restic
?
Rust provides memory safety without garbage collection, concurrency without data races, and zero runtime overhead (see “Fearless Concurrency with Rust”, “Abstraction without overhead”, and “The Rust Programming Language” book).
Rust provides C-like performance, which is much better than Go (goolge “rust go benchmarks” for references). The rdedup
data deduplication engine is written in Rust.
This is not an answer, but a curious question; With Rust, can you cross-compile out of the box, e.g. like you just set GOOS and GOARCH in Go when building, to produce binaries for other OSs and architectures? That’s one thing I like about Go, a lot. Curious if you can do that with Rust too.
Before I answer your question, I’d like to repeat something else: For this project, the language it is written in is not so important. It is a tool to get the job done. While it’s true that Go’s current popularity helps attracting contributors and we’ve got a nice logo which is derived from the Gopher logo, the language is secondary.
For a backup program in general, and restic in particular, the repository/storage format is the most important thing. That’s why we started with a textual reference description as soon as it became clear that the basic features would work the way we imagined them to work (deduplication, content-addressable storage etc.)
So, back to your question:
Yes: At the time the project was started in January/February 2014, I only had a tiny bit of experience with Go, and I liked the language. I think I had briefly read the available documentation for Rust, but since it was very well pre-1.0 back then and had a reputation of not being stable (in terms of the language itself, not so much the compiler), I did not consider this an option. So, restic basically started with me trying to implement something new (a backup program) in a language I wasn’t very familiar with, just to get a feeling for it.
In retrospect, Go is a great choice for restic. The most important factors, at least from my point of view, are the easy readability, cross-compilation without hassles, and the recent popularity which brings many new contributors. The community is very welcoming and positive. Also, the reduced feature set is a plus in my opinion, e.g. for restic I can’t remember any situation where I wrote very ugly code and thought “well, with generics that would’ve been so much better”.
That does by no means imply that Rust would’ve been a worse choice, I think Rust is a very fine language with a thriving community. I can very well imagine restic having been written in Rust, that it became Go was rather accidental.
I hope this answers your question!
Personally, I’d love to get a bit more experience in Rust. I think it’s very valuable for being a good engineer to get to know several different programming languages and concepts. Before writing restic in Go, I’ve written a significant amount of code in Ruby, Python, and of course C (and less code in a couple of other languages like Perl and Shell). So I don’t have any experience with C++, I’ve tried to avoid that until today
Yes, the rustup
toolchain manager for Rust provides “push-button cross-compilation” capability, for details see “Taking Rust everywhere with rustup”, “rust-cross”, and rustup.rs
on GitHub.
If you have an interest in seeing Restic implemented in Rust, I would very much like to see the development of alternative clients which strive to be compatible with the on-disk repository/storage format.
The more active implementations, along with the requirement of interoperability, will only strengthen the specifications. When there’s one implementation, it’s just documentation. When there are two or more, it becomes a contract.
I personally have no favorite between Go and Rust. I’m slightly more familiar with Go at the moment, which makes the Go implementation a little bit more accessible to me (in terms of reading the source). It looks like a few design choices were influenced by the Go ecosystem (single binary distribution, choice of crypto based on availability in Go’s standard library, etc.). It would be interesting to see which design choices Rust’s ecosystem would influence.
While that would be an interesting experiment, it will also require a lot of coordination so that this potential alternative implementation stays compatible. In my opinion, we don’t have the resources to do that at the moment, I’d like to focus on improving restic as it is.
I think it would be pretty pointless to create other restic clients/clones instead of living with Go (which so far has served very well, and probably continues to do so) and spending that development time on improving the current software. It would be quite a waste to create redundant work unless there’s a specific problem that cannot be solved with the current language.
So maybe you can reconsider Rust when you start working on the next repository format v2
Joking aside, personally every time I have compared Rust with Go I have found Rust superior (this could be just personal preference though). Yes Rust is “younger”, version 1.0 was released in May 2015, in January/February 2014 it was still rough.
Somewhat tangential to this, I wonder how often people mistake restic for a Rust-based project because of the name. (I have seen more than one occasion where it was typoed to “rustic”.)
Personally I’m glad that restic has a distinctive name, rather than “Go-backup” or some similarly generic name.
That’s probably just overeager auto correction: “rustic” is an English word, whereas “restic” isn’t.
No, that’s not going to happen . Quoting Joel in Things You Should Never Do, Part I
They did it by making the single worst strategic mistake that any software company can make: They decided to rewrite the code from scratch.
The article is awesome btw, lots of great insight. And it’s only 18 years old
rust
is arguably faster than go
in many areas; but the speed comes at a higher cost when it comes to complexity and ease of writing. I’m no expert in rust
, but I know there is a much higher learning curve in rust
and there is a higher frequensy of “how do I even begin solving this” than with go
.
If anyone builds a restic-compatable client with rust please make sure it’s called rustic.
Thank you.
2 posts were split to a new topic: Rust implementation of rest-server
I note that, the quality of cryptographic libraries in Go is higher than that in standard libraries in other languages. I trust Go crypto, maintained by Google.
How about the chance of design flaws and vulnerabilities in Python or C++ libraries or OpenSSL? Well I rather not to use them.
I cannot judge the quality of crypto in Go or in Rust. However, I have to mention that the crypto used in the restic format seems to be well architected, but is not a widely used way to encrypt and MAC your data. I think this is also due to fact that those things were not seasoned when the restic format was developed. Nowadays there exist AEADs which are widely used.
The authenticated encryption used in restic is somewhat self-implemented in https://github.com/restic/restic/blob/master/internal/crypto/crypto.go and for Rust, I made the aes256ctr_poly1305aes crate which implements the Rust Aead trait.
Both implementations use the Go/Rust standard crypto libraries for the AES and Poly1305 algorithms.
So, the quality of the crypto implementation used in restic depends on the standard crpyto libraries as well as the implementation of the AES256CTR-Poly1305AES authenticated encryption.
You have probably seen this brief review, which speaks positively of Restic, I post it for others
I can’t judge Restic’s self-baked AEAD. It’s a bit of a yellow flag. Of course, using an AEAD from Go standard library is better. The part directly from standard library is OK though.
Perhaps developers could chime in, if more is known than in above link.
I just like to comment on this now that I’ve written around 6000 lines of Rust code to get rustic (which by the way is about three times the code I’ve contributed to restic in go)…
So, about the higher learning curve: That’s definitively true. But it’s also part of the fun when you have to learn and then realize that you actually completed something!
About the complexity: I would say this is a very fair trade-off in Rust. Sure, things are a bit more complex with generics/traits and sometimes you need to think more about the memory layout than you would do in other languages. But on the other side, there are so many things which makes things working very smoothly like the error handling or the brilliant crates available…
About the ease of writing: No, there is definitively no higher cost once you mastered the learning curve at the beginning. In contrast, so many things are achieved so easily in Rust that you sometimes really start wondering why this isn’t working in other languages. And I never had this if-it-compiles-it-works experience so often in any other language I used before than I had with Rust.
A concrete example about the ease of writing: Adding compression support to rustic took me about 3 hours during last weekend and almost immediately worked once the compiler was satisfied.
All right, I’ll stop advertising Rust for now and go to bed
How many lines of code is Restic and rustic? How about the cryptography parts (neglecting parts that connect to backend etc)?