December 27, 2020

Proof of concept: Backup from Unix to Nixos with Borg

I want to get a directory backed up with borg on my nixos-server (regulus.fritz.box). The client may just be a regular unixoid, doesn't have to be nixos (I am using MacOS for testing). All the commands (unless explicitly stated otherwise) are executed on the client. Both systems have borg installed. This is a tutorial, so most explaining will be about what to do, not why to do it.

Setup

We first create the directory with our valuable data.

echo "1234567890" > files_to_back_up/zahlen.txt
echo "abcdefghijklmnopqrstuvwxyz" > files_to_back_up/buchstaben.txt

For borg to access the server without a password we need to create a keyfile pair (on the client). Name it however you want.

ssh-keygen -N '' -t ed25519 -f key_backups_of_NUE-MAC-087_id_ed25519
Generating public/private ed25519 key pair.
Your identification has been saved in key_backups_of_NUE-MAC-087_id_ed25519.
Your public key has been saved in key_backups_of_NUE-MAC-087_id_ed25519.pub.
The key fingerprint is:
SHA256:KAkg+ve2A+D9TWYYdlshCIECDfP3SWAXAyml8NkZFPA jlippmann@NUE-MAC-087
The key's randomart image is:
+--[ED25519 256]--+
|Oo.=@*+o         |
|+*+*.=... .      |
|..*.E .  . .     |
| ..o +oo. .      |
| ..o+.++So       |
|  ..oo. =        |
|     oo=         |
|     .o..        |
|      ..         |
+----[SHA256]-----+

Have a look at the public key:

cat key_backups_of_NUE-MAC-087_id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE+u6Q/ycvxM1XG7JitWqla/nTKvT29rHS9IUjZMaPwH jlippmann@NUE-MAC-087

Now we tell the server about this key and what should be done with it. Nixos will do all the complicated stuff for us (creating a user and paths, setting the rights correctly), we just have to add the following to the (server-)nixos-configuration.

  services.borgbackup.repos = {
    my_borg_repo = {
      authorizedKeys = [
        # Here goes the public key we just created
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE+u6Q/ycvxM1XG7JitWqla/nTKvT29rHS9IUjZMaPwH jlippmann@NUE-MAC-087"
      ] ;
      # where the backup will be placed
      path = "/var/lib/my_borg_repo" ;
    };
  };

Rebuild and switch. A user of the name borg has been created, has been assigned the mentioned directory and the key has been placed in the correct spot. You can check that this worked like this (still on the server):

cat /etc/ssh/authorized_keys.d/borg
command="cd '/var/lib/my_borg_repo' && borg serve --restrict-to-repository .  ",restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE+u6Q/ycvxM1XG7JitWqla/nTKvT29rHS9IUjZMaPwH jlippmann@NUE-MAC-087

Initialize the backup

We will have a password, which is the password for our backup itself. To be more precise: it is the password for a key stored in the backup-repo with which the backup wil be encrypted. It has nothing to do with the keypair we created earlier (which is just for connecting to the server). To safe time we will export this backup-passwort to a shell variable beforehand. There are other ways, for example setting a BORG_PASSCOMMAND. If you don't you will be asked to enter the password each time interactively (which is nice for exploration but bad for scripting.

export BORG_PASSPHRASE="test"

Now back on the client we can init the borg repo. Note especially the trailing colon and dot in the adress.

borg init --encryption=repokey-blake2 --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:.
By default repositories initialized with this version will produce security
errors if written to with an older version (up to and including Borg 1.0.8).

If you want to use these older versions, you can disable the check by running:
borg upgrade --disable-tam ssh://borg@regulus.fritz.box/./.

See https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability for details about the security implications.

IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
Use "borg key export" to export the key, optionally in printable format.
Write down the passphrase. Store both at safe place(s).

To confirm that we indeed created the repository remotly we can check that the repo was created on the server:

ls /var/lib/my_borg_repo/
config  data  hints.1  index.1  integrity.1  nonce  README

Back on the client again, lets do this key export that was mentioned after we initialized the repo. I THINK that key is what the repo is encrypted with.

borg key export --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:. test_export
cat test_export
BORG_KEY ab6cb44a7ed5b13e6bb9fd62e93731d741de161d031aa74c5e903a7c1e9cb9ef
hqlhbGdvcml0aG2mc2hhMjU2pGRhdGHaAZ5SR2ULbAiQQxcmb1tD+y99ZEzBll9Pe/D0C0
dlQAniuUFgHa2J/dCH3FNkT92QfzgQW3k/SP6obl5JOYRUJRGEPJNYa2RwcSquV9xpqnTg
/QsOWNJQuQBX2dZIMWRiHYVKvXiK11jPI0HyO1c8SV9YgfH8mJtWd+0uX4eLnqCFGBWXfO
hTgKMdRTtkcV89HjZqYI4fW64AnSB6DLPyQutm0jXeRFdYtdZbujufS5SRb9rBYxcypOSu
8TT5zNcu+Sus2vr5gc303CXM9Ktv8wYiuErC6YlP5dClfU8N9ihqS91lIc32R1QbufTSgt
h0yBEugYqGLRDr+ZVGVdwojshgQoyECH9l87FNyQnExvFXm2TNg0O8gWwnja+xNU+0yta5
DNG2tHmCi99Et10ezKton6MXIGcWBwErFlZ5E+vG1pmP3AiUVM7gtUCICp/foJWhoQKlf5
U8xUDid/t34/YGv9kHAWpvXWVQej1lAC4kpaVQ+ZcyGOSN9VUKCniOmbF1ip2cymF0biYn
CnOR5G1Bwc+XSbLlVmUR/xwIJOakaGFzaNoAIAEIyyWhmLMISUJYyy2Iay4O9o7cffYSzR
mUjalZJFK9qml0ZXJhdGlvbnPOAAGGoKRzYWx02gAgpY+xYO83BALtVodzGH4aJgpD6jzt
5Ao3IMLckcx5xeSndmVyc2lvbgE=

Create a backup

Now we can do our first backup:

borg create --stats --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:.::01_first_backup files_to_back_up
------------------------------------------------------------------------------
Archive name: 01_first_backup
Archive fingerprint: e40e34c423ed1dba3ab1243840a3840b244f0f423f8bc96e50773879ae3184cd
Time (start): Sat, 2020-12-26 22:13:26
Time (end):   Sat, 2020-12-26 22:13:26
Duration: 0.04 seconds
Number of files: 2
Utilization of max. archive size: 0%
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
This archive:                1.20 kB              1.12 kB              1.12 kB
All archives:                1.20 kB              1.12 kB              1.12 kB

                       Unique chunks         Total chunks
Chunk index:                       4                    4
------------------------------------------------------------------------------

Now we can see if it is realy there:

borg list  --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:.
01_first_backup                      Sat, 2020-12-26 22:13:26 [e40e34c423ed1dba3ab1243840a3840b244f0f423f8bc96e50773879ae3184cd]

And see what is in it:

borg list  --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:.::01_first_backup
drwxr-xr-x jlippmann 1728021072        0 Mon, 2020-12-21 07:48:10 files_to_back_up
-rw-r--r-- jlippmann 1728021072       11 Sat, 2020-12-26 22:04:13 files_to_back_up/zahlen.txt
-rw-r--r-- jlippmann 1728021072       27 Sat, 2020-12-26 22:04:13 files_to_back_up/buchstaben.txt

change some files and back up again

Now we add/change some files, create a new backup (without –stats this time) and check if it is there as well.

echo "ABCDEFGHIJKLMNOPQRSTUVWXYZ" >> files_to_back_up/buchstaben.txt # change a file
echo "gnu penguin chamaeleon" > files_to_back_up/animals.txt         # add a new file
# new backup
borg create --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:.::02_second_backup files_to_back_up

List all the backups.

borg list  --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:.
01_first_backup                      Sat, 2020-12-26 22:13:26 [e40e34c423ed1dba3ab1243840a3840b244f0f423f8bc96e50773879ae3184cd]
02_second_backup                     Sat, 2020-12-26 22:15:35 [7a9d60039583b5c01dbf50df4b3f11c7736f1f5701c8822cc80b97e90aa2d220]

Look into 02_second_backup.

borg list --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:.::02_second_backup
drwxr-xr-x jlippmann 1728021072        0 Sat, 2020-12-26 22:15:33 files_to_back_up
-rw-r--r-- jlippmann 1728021072       11 Sat, 2020-12-26 22:04:13 files_to_back_up/zahlen.txt
-rw-r--r-- jlippmann 1728021072       54 Sat, 2020-12-26 22:15:33 files_to_back_up/buchstaben.txt
-rw-r--r-- jlippmann 1728021072       23 Sat, 2020-12-26 22:15:33 files_to_back_up/animals.txt

Looking at the size of the file buchstaben.txt we see that it has grown.

Restore from backup

Next we loose our precious directory by accident…

rm -rf files_to_back_up # Oh no!

… and want to get an old version of it back.

borg extract --rsh "ssh -i key_backups_of_NUE-MAC-087_id_ed25519" borg@regulus.fritz.box:.::01_first_backup

The files are back, as expected.

ls -la files_to_back_up
total 16
drwxr-xr-x   4 jlippmann  1728021072  128 21 Dez 07:48 .
drwxr-xr-x  12 jlippmann  1728021072  384 26 Dez 22:40 ..
-rw-r--r--   1 jlippmann  1728021072   27 26 Dez 22:04 buchstaben.txt
-rw-r--r--   1 jlippmann  1728021072   11 26 Dez 22:04 zahlen.txt