diff --git a/docs/conf.py b/docs/conf.py index 777416adf..77fe87894 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -111,7 +111,7 @@ def set_rst_settings(app): def setup(app): - app.add_stylesheet('css/borg.css') + app.add_css_file('css/borg.css') app.connect('builder-inited', set_rst_settings) # Theme options are theme-specific and customize the look and feel of a theme diff --git a/docs/deployment/pull-backup.rst b/docs/deployment/pull-backup.rst index 772dac176..f4c67f8ea 100644 --- a/docs/deployment/pull-backup.rst +++ b/docs/deployment/pull-backup.rst @@ -1,9 +1,23 @@ .. include:: ../global.rst.inc .. highlight:: none +======================= Backing up in pull mode ======================= +Typically the borg client connects to a backup server using SSH as a transport +when initiating a backup. This is referred to as push mode. + +If you however require the backup server to initiate the connection or prefer +it to initiate the backup run, one of the following workarounds is required to +allow such a pull mode setup. + +A common use case for pull mode is to backup a remote server to a local personal +computer. + +SSHFS +===== + Assuming you have a pull backup system set up with borg, where a backup server pulls the data from the target via SSHFS. In this mode, the backup client's file system is mounted remotely on the backup server. Pull mode is even possible if @@ -174,3 +188,116 @@ directly extract it without the need of mounting with SSHFS: Note that in this scenario the tar format is the limiting factor – it cannot restore all the advanced features that BorgBackup supports. See :ref:`borg_export-tar` for limitations. + +socat +===== + +In this setup a SSH connection from the backup server to the client is +established that uses SSH reverse port forwarding to transparently +tunnel data between UNIX domain sockets on the client and server and the socat +tool to connect these with the borg client and server processes, respectively. + +The program socat has to be available on the backup server and on the client +to be backed up. + +When **pushing** a backup the borg client (holding the data to be backed up) +connects to the backup server via ssh, starts ``borg serve`` on the backup +server and communicates via standard input and output (transported via SSH) +with the process on the backup server. + +With the help of socat this process can be reversed. The backup server will +create a connection to the client (holding the data to be backed up) and will +**pull** the data. + +In the following example *borg-server* connects to *borg-client* to pull a backup. + +To provide a secure setup sockets should be stored in ``/run/borg``, only +accessible to the users that run the backup process. So on both systems, +*borg-server* and *borg-client* the folder ``/run/borg`` has to be created:: + + sudo mkdir -m 0700 /run/borg + +On *borg-server* the socket file is opened by the user running the ``borg +serve`` process writing to the repository +so the user has to have read and write permissions on ``/run/borg``:: + + borg-server:~$ sudo chown borgs /run/borg + +On *borg-client* the socket file is created by ssh, so the user used to connect +to *borg-client* has to have read and write permissions on ``/run/borg``:: + + borg-client:~$ sudo chown borgc /run/borg + +On *borg-server*, we have to start the command ``borg serve`` and make its +standard input and output available to a unix socket:: + + borg-server:~$ socat UNIX-LISTEN:/run/borg/reponame.sock,fork EXEC:"borg serve --append-only --restrict-to-path /path/to/repo" + +Socat will wait until a connection is opened. Then socat will execute the +command given, redirecting Standard Input and Output to the unix socket. The +optional arguments for ``borg serve`` are not necessary but a sane default. + +.. note:: + When used in production you may also use systemd socket-based activation + instead of socat on the server side. You would wrap the ``borg serve`` command + in a `service unit`_ and configure a matching `socket unit`_ + to start the service whenever a client connects to the socket. + + .. _service unit: https://www.freedesktop.org/software/systemd/man/systemd.service.html + .. _socket unit: https://www.freedesktop.org/software/systemd/man/systemd.socket.html + +Now we need a way to access the unix socket on *borg-client* (holding the +data to be backed up), as we created the unix socket on *borg-server* +Opening a SSH connection from the *borg-server* to the *borg-client* with reverse port +forwarding can do this for us:: + + borg-server:~$ ssh -R /run/borg/reponame.sock:/run/borg/reponame.sock borgc@borg-client + +.. note:: + + As the default value of OpenSSH for ``StreamLocalBindUnlink`` is ``no``, the + socket file created by sshd is not removed. Trying to connect a second time, + will print a short warning, and the forwarding does **not** take place:: + + Warning: remote port forwarding failed for listen path /run/borg/reponame.sock + + When you are done, you have to manually remove the socket file, otherwise + you may see an error like this when trying to execute borg commands:: + + Remote: YYYY/MM/DD HH:MM:SS socat[XXX] E connect(5, AF=1 "/run/borg/reponame.sock", 13): Connection refused + Connection closed by remote host. Is borg working on the server? + + +When a process opens the socket on *borg-client*, SSH will forward all +data to the socket on *borg-server*. + +The next step is to tell borg on *borg-client* to use the unix socket to communicate with the +``borg serve`` command on *borg-server* via the socat socket instead of SSH:: + + borg-client:~$ export BORG_RSH="sh -c 'exec socat STDIO UNIX-CONNECT:/run/borg/reponame.sock'" + +The default value for ``BORG_RSH`` is ``ssh``. By default Borg uses SSH to create +the connection to the backup server. Therefore Borg parses the repo URL +and adds the server name (and other arguments) to the SSH command. Those +arguments can not be handled by socat. We wrap the command with ``sh`` to +ignore all arguments intended for the SSH command. + +All Borg commands can now be executed on *borg-client*. For example to create a +backup execute the ``borg create`` command:: + + borg-client:~$ borg create ssh://borg-server/path/to/repo::archive /path_to_backup + +When automating backup creation, the +interactive ssh session may seem inappropriate. An alternative way of creating +a backup may be the following command:: + + borg-server:~$ ssh \ + -R /run/borg/reponame.sock:/run/borg/reponame.sock \ + borgc@borg-client \ + borg create \ + --rsh "sh -c 'exec socat STDIO UNIX-CONNECT:/run/borg/reponame.sock'" \ + ssh://borg-server/path/to/repo::archive /path_to_backup \ + ';' rm /run/borg/reponame.sock + +This command also automatically removes the socket file after the ``borg +create`` command is done.