Usability issue with sftp and sftp.command


I’ve to use a sftp storage with restic 0.9.3. The sftp storage uses a key-based authentication and a specific port. As this user/ssh identity is only used by restic (and because of other policy reasons), I’m not able to put the identity to /root/.ssh and/or modify the /root/.ssh/config. root is required because it’s about backing up the main system files.

  1. First step: I used an interactive ssh session with agent forwarding from my local machine (my personal SSH key is authorized to connect to the sftp/ssh storage) to create the repo and do the initial backup. Just ran restic -r sftp: … Worked flawlessly!

  2. Then after reading Github issues I went down the -o sftp.command rabbit hole:

    restic -o sftp.command="ssh -i /path/to/.ssh/id_ed25519 -p 23 u12345@u12345.your-storagebox.tld -s sftp" -r sftp:u12345@u12345.your-storagebox.tld:/backups/server12345 stats

    And all I got was:

    Fatal: unable to open config file: Lstat: file does not exist
    Is there a repository at the following location?

    I’m confused. After several attempts I nearly gave up just to try it without the leading slash:

    restic -o sftp.command="ssh -i /path/to/.ssh/id_ed25519 -p 23 u12345@u12345.your-storagebox.tld -s sftp" -r sftp:u12345@u12345.your-storagebox.tld:backups/server12345 stats

    and it worked? Did I miss something? Maybe I’m just too tired, sorry :confused:


1 Like

I like this part :slight_smile:

This not so much :confused: sorry about the confusing interface.

You can specify the parameters in the sftp.command option, but it’s much easier to define a new host (alias) in the ~/.ssh/config file. That’s described in the manual. In your case this would be something similar to:

Host storagebox
    Hostname your-storagebox.tld
    Port 23
    User u12345
    IdentityFile /path/to/.ssh/id_ed25519

Then you can just use restic -r sftp:storagebox:/path/to/repo and don’t have to fiddle around with options to ssh. If it isn’t possible to use the /root/.ssh/config file, you can maybe use /etc/ssh/ssh_config. Otherwise it’s also possible to pass the path to the config file to ssh like this:

$ restic -o sftp.command="ssh -F /path/to/config storagebox -s sftp" sftp:doesnotmatter:/path/to/repo

So, back to the issue you describe: I find it very odd that you needed to pass a different path, it should always be the same (paths are interpreted only on the target server, so they are independent of the client). Once you have created a config file, you can easily check with sftp what the paths are:

$ sftp storagebox
Connected to storagebox.
sftp> ls /backups/server12345/config

sftp> ls backups/server12345/config

Can you do that and report back if there is any difference? Usually (depending on the what the sftp server is), relative paths are relative to the user’s home directory on the server.

I’m curious: can you tell us which provider/service that is? It sounds like it may be Hetzner, they have an offer called “storage box”. If so, your findings may be helpful to others searching the forum for the provider’s name :slight_smile:

Thanks for asking these questions, that’s exactly what the forum is for.

Thanks for the answer.

Yes, it’s Hetzner’s Storagebox:

sftp> ls /

remote readdir("/"): Permission denied

sftp> ls /backups

Can’t ls: “/backups” not found

sftp> ls backups

While this explains the error, the intialization worked with a slash:

➜ ~ restic -r init

enter password for new repository:

enter password again:

created restic repository affa024ca1 at

Please note that knowledge of your password is required to access

the repository. Losing your password means that your data is

irrecoverably lost.

I would expect to run into the error as early as possible (e.g. on init).

regarding ssh config:

Due to policy reasons I can’t modify /root/.ssh. I’m also a big fan of separation of concerns: I don’t want to allow other processes of the user to give access to the ssh identity used for the restic/sftp backup which would be the case using the traditional way as you have described very well.

Another reason for us is disk encryption: While we are using provider managed virtual machines which are usually not full-disk-encryptable, we mount several filesystems once the machine is up and unlocked. Keys to other services are only on encrypted filesystems while /root has to be on the unencrypted root filesystem. We know this is vulnerable to memory dumping (e.g. kvm host can easily grab the encryption key or files), at least it’s not readable in the provider’s disk backups (We don’t trust cloud providers very much). So if someone grabs a disk backup of our provider, they can’t access the sftp store because the key is still in the encrypted filesystem.

That’s odd and I don’t have an explanation why that works. Maybe it’s only listing that’s deactivated? What restic init does is it creates a bunch of directories and uploads the config file, it does not try to list any directories. You could test that with sftp by trying to create a new directory with a leading slash…

Can you also try running pwd on the sftp prompt to get the current directory?

Me too. As far as I know Hetzner is using proftpd with mod_sftp, maybe it’s an unusual implementation detail…

I don’t understand: If there’s a rogue process running as the same user as restic, that process should be able to access all data needed to access the restic repo…

Ah, that bit I can understand :slight_smile: So you need to fiddle around with the -o sftp.command="[...]" option.