Understanding restic use case from VPS to local

Please let me know if I understood few things correctly and help me figure out best way to achieve what I’m trying to:

  1. Restic must be installed on source machine (machine that needs to be backed up)
  2. This requires restic to have a way to reach target machine over internet.

I want to backup my VPS to my NAS (ZFS running on proxmox).
NAS is not accessible over internet and I can’t open ports on router.

In this scenario how should I approach back up ?

There are various options;

  • Set up a VPN between your NAS and the VPS, so they can communicate over this Virtual Private Network of their own.

  • Use an SSH tunnel from the NAS to the VPS with port forwarding from the VPS to the NAS (this goes over/through the SSH tunnel).

Use an SSH tunnel from the NAS to the VPS with port forwarding from the VPS to the NAS (this goes over/through the SSH tunnel).

Interesting.
Please let me know if my flow makes sense: (assuming time is synced between NAS and VPS)

  1. Initiate reverse SSH tunnel from NAS to VPS (say around 11:50PM)
  2. On VPS mount samba network drive in a directory (around 12:00AM)
  3. Run restic from directory to directory
  4. Unmount network drive once done
  5. Close SSH tunnel (around 12:40AM)

NAS has 2 crons running 1. open reverse tunnel 2. close tunnel
VPS has 1 cron running script to mount backup and unmount

Do not use SMB over Internet - it is not designed for it and performance will be terrible.

There are much better options e.g. sftp or if you don’t mind a little bit more config install minio and use S3.

And plan carefully your VPN setup… otherwise if your VPS is compromised somebody can get full access to your NAS. So only allow ports you really need etc. As a minimum I would only VPN between vm/jail/docker running on NAS and VPS.

And overall to avoid serious security problems I would backup VPS to some cloud storage and then on my NAS use restic replication to copy it from this cloud to local NAS storage.

simplest method for you would be ssh

(untested but should work):

on NAS: ssh -R 2222:127.0.0.1:22 user@vps backup

backup script on VPS would use sftp to 127.0.0.1:2222 as restic repo server (see Preparing a new repository — restic 0.16.1 documentation for more on this).

I would consider ad hoc vpn solutions for that like zerotier or tailscale. Especially if you don’t have a lot experience with building vpns by hand. It’s up and running in minutes while still gives you quite high security.
You can then use restic through that secure tunnel.

This works very well for me. On the backup server (behind NAT) I use rest-server and autossh to have an always-on tunnel to the host-to-be-backed via crontab:

@reboot sleep 20; autossh -N -R 1337:localhost:8000 user@host-to-be-backed.up

Also from the backup server I then initiate the backup whenever it’s time:

ssh user@host-to-be-backed.up "restic -r rest:http://user:pass@localhost:1337/repo backup /path"

Yes, I know, no SSL but the tunnel is encrypted anyway.

Thanks I think I understand this:
Please correct me if I’m wrong
rest-server running at port 8000, mapped to localhost:1337 on VPS.
restic runs on VPS (already has tunnel established through autossh) and uses user from local machine.

Also I see sftp should be part of ssh, does rest-server bring any other benefit?
I’ll look at autossh and how to read ssh-key through script.

Yes, rest-server uses port 8000 on the receiving server which is tunneled to 1337 on the client. restic runs on the client but it’s started remotely, mainly because I have a script that backs up multiple machines one after the other and because I don’t have to have the restic repo password on the client that way (check out --password-command).

user:pass” is the rest-server authentication (you have a .htpasswd file there). For me, the main advantages in using rest-server are that it’s quite fast, I can have multiple restic repos behind it and it has an append-only mode that keeps a compromised client from easily being able to delete and/or encrypt your backups.

I’ve implemented following as of now:
ON VPS:

/root/password_file
/root/repo_file

#repo_file has
sftp://<user>@localhost:2222//path/to/backup

On backup machine I can run:

ssh -R 2222:localhost:22 <user>@<vps>

and on VPS I can run:

restic --repository-file /root/repo_file --password-file /root/password_file backup /path/to/be/backed

This works and I’ve created backups.
I think required building blocks are in place.
I was trying to automate this process and I’m not sure if I’m doing it correctly.
Please let me know if following is done correctly:
On backup machine:
Create cron to run

ssh <user>@<vps> "restic --repository-file /root/repo_file --password-file /root/password_file backup /path/to/be/backed"

On backup machine run:

autossh -N -R 2222:localhost:22 <user>@<vps>

Expectation: cron should run backup when it’s executed.
Is this correct? Or how should I check if something is wrong?

It works. (just tested with cron close to current time)

Hm yes this works but it’s not very secure as you basically have an open line from the vps to your server now. I don’t recommend using it this way in production.

In my post above I proposed using rest-server which does provide an additional authentication and, if run in append-only-mode gives an attacker who compromised the vps not a lot of attack surface to the backup server.

The ssh tunnel basically just encrypts the http transfer and works without punching a hole into your firewall on the backup server side because it’s opened from within the firewall.

I see so rest-server is basically to add another layer of authentication. I’ll learn a bit more about rest-server and try to implement it, Thanks.

Also would you mind what does following line does (specifically initial part @reboot sleep 20 )

@reboot sleep 20; autossh -N -R 1337:localhost:8000 user@host-to-be-backed.up

Rest Server is a high performance HTTP server that implements restic’s REST backend API. It provides secure and efficient way to backup data remotely, using restic backup client via the rest: URL.”

@reboot sleep 20 executes the following command at each reboot and waits 20 seconds before doing so. Just to give your server enough time to start up.