A transport provides an authenticated io.ReadWriteCloser to the RPC layer.
io.ReadWriteCloser is essentially a bidirectional reliable communication channel.)
Currently, only the
ssh+stdinserver transport is supported.
The way the
ssh+stdinserver transport works is inspired by git shell and Borg Backup.
It is implemented in the Go package
The config excerpts are taken from the Tutorial which you should complete before reading further.
jobs: - name: pull_backup type: source serve: type: stdinserver client_identity: backup-srv.example.com ...
The serving job opens a UNIX socket named after
client_identity in the runtime directory, e.g.
On the same machine, the
zrepl stdinserver $client_identity command connects to that socket.
zrepl stdinserver backup-srv.example.com connects to the UNIX socket
It then passes its stdin and stdout file descriptors to the zrepl daemon via cmsg(3).
zrepl daemon in turn combines them into an
Write() turns into a write to stdout, a
Read() turns into a read from stdin.
Interactive use of the
stdinserver subcommand does not make much sense.
However, we can force its execution when a user with a particular SSH pubkey connects via SSH.
This can be achieved with an entry in the
authorized_keys file of the serving zrepl daemon.
# for OpenSSH >= 7.2 command="zrepl stdinserver CLIENT_IDENTITY",restrict CLIENT_SSH_KEY # for older OpenSSH versions command="zrepl stdinserver CLIENT_IDENTITY",no-port-forwarding,no-X11-forwarding,no-pty,no-agent-forwarding,no-user-rc CLIENT_SSH_KEY
- CLIENT_IDENTITY is substituted with
backup-srv.example.comin our example
- CLIENT_SSH_KEY is substituted with the public part of the SSH keypair specified in the
connectdirective on the connecting host.
You may need to adjust the
PermitRootLogin option in
forced-commands-only or higher for this to work.
Refer to sshd_config(5) for details.
To recap, this is of how client authentication works with the
- Connections to the
client_identityUNIX socket are blindly trusted by zrepl daemon.
- Thus, the runtime directory must be private to the zrepl user (checked by zrepl daemon)
- The admin of the host with the serving zrepl daemon controls the
- Thus, the administrator controls the mapping
PUBKEY -> CLIENT_IDENTITY.
jobs: - name: pull_app-srv type: pull connect: type: ssh+stdinserver host: app-srv.example.com user: root port: 22 identity_file: /etc/zrepl/ssh/identity options: # optional - "Compression=on"
The connecting zrepl daemon
- Creates a pipe
- In the forked process
- Replaces forked stdin and stdout with the corresponding pipe ends
- Executes the
sshbinary found in
- The identity file (
-i) is set to
- The remote user, host and port correspond to those configured.
- Further options can be specified using the
optionsfield, which appends each entry in the list to the command line using
- The identity file (
- Wraps the pipe ends in an
io.ReadWriteCloserand uses it for RPC.
As discussed in the section above, the connecting zrepl daemon expects that
zrepl stdinserver $client_identity is executed automatically via an
authorized_keys file entry.
The environment variables of the underlying SSH process are cleared.
$SSH_AUTH_SOCK will not be available.
It is suggested to create a separate, unencrypted SSH key solely for that purpose.