1.. include:: ../global.rst.inc 2.. highlight:: none 3 4Central repository server with Ansible or Salt 5============================================== 6 7This section will give an example how to setup a borg repository server for multiple 8clients. 9 10Machines 11-------- 12 13There are multiple machines used in this section and will further be named by their 14respective fully qualified domain name (fqdn). 15 16* The backup server: `backup01.srv.local` 17* The clients: 18 19 - John Doe's desktop: `johndoe.clnt.local` 20 - Webserver 01: `web01.srv.local` 21 - Application server 01: `app01.srv.local` 22 23User and group 24-------------- 25 26The repository server needs to have only one UNIX user for all the clients. 27Recommended user and group with additional settings: 28 29* User: `backup` 30* Group: `backup` 31* Shell: `/bin/bash` (or other capable to run the `borg serve` command) 32* Home: `/home/backup` 33 34Most clients shall initiate a backup from the root user to catch all 35users, groups and permissions (e.g. when backing up `/home`). 36 37Folders 38------- 39 40The following folder tree layout is suggested on the repository server: 41 42* User home directory, /home/backup 43* Repositories path (storage pool): /home/backup/repos 44* Clients restricted paths (`/home/backup/repos/<client fqdn>`): 45 46 - johndoe.clnt.local: `/home/backup/repos/johndoe.clnt.local` 47 - web01.srv.local: `/home/backup/repos/web01.srv.local` 48 - app01.srv.local: `/home/backup/repos/app01.srv.local` 49 50Restrictions 51------------ 52 53Borg is instructed to restrict clients into their own paths: 54``borg serve --restrict-to-path /home/backup/repos/<client fqdn>`` 55 56The client will be able to access any file or subdirectory inside of ``/home/backup/repos/<client fqdn>`` 57but no other directories. You can allow a client to access several separate directories by passing multiple 58``--restrict-to-path`` flags, for instance: ``borg serve --restrict-to-path /home/backup/repos/<client fqdn> --restrict-to-path /home/backup/repos/<other client fqdn>``, 59which could make sense if multiple machines belong to one person which should then have access to all the 60backups of their machines. 61 62There is only one ssh key per client allowed. Keys are added for ``johndoe.clnt.local``, ``web01.srv.local`` and 63``app01.srv.local``. But they will access the backup under only one UNIX user account as: 64``backup@backup01.srv.local``. Every key in ``$HOME/.ssh/authorized_keys`` has a 65forced command and restrictions applied as shown below: 66 67:: 68 69 command="cd /home/backup/repos/<client fqdn>; 70 borg serve --restrict-to-path /home/backup/repos/<client fqdn>", 71 restrict <keytype> <key> <host> 72 73.. note:: The text shown above needs to be written on a single line! 74 75The options which are added to the key will perform the following: 76 771. Change working directory 782. Run ``borg serve`` restricted to the client base path 793. Restrict ssh and do not allow stuff which imposes a security risk 80 81Due to the ``cd`` command we use, the server automatically changes the current 82working directory. Then client doesn't need to have knowledge of the absolute 83or relative remote repository path and can directly access the repositories at 84``<user>@<host>:<repo>``. 85 86.. note:: The setup above ignores all client given commandline parameters 87 which are normally appended to the `borg serve` command. 88 89Client 90------ 91 92The client needs to initialize the `pictures` repository like this: 93 94:: 95 96 borg init backup@backup01.srv.local:pictures 97 98Or with the full path (should actually never be used, as only for demonstrational purposes). 99The server should automatically change the current working directory to the `<client fqdn>` folder. 100 101:: 102 103 borg init backup@backup01.srv.local:/home/backup/repos/johndoe.clnt.local/pictures 104 105When `johndoe.clnt.local` tries to access a not restricted path the following error is raised. 106John Doe tries to backup into the Web 01 path: 107 108:: 109 110 borg init backup@backup01.srv.local:/home/backup/repos/web01.srv.local/pictures 111 112:: 113 114 ~~~ SNIP ~~~ 115 Remote: borg.remote.PathNotAllowed: /home/backup/repos/web01.srv.local/pictures 116 ~~~ SNIP ~~~ 117 Repository path not allowed 118 119Ansible 120------- 121 122Ansible takes care of all the system-specific commands to add the user, create the 123folder, install and configure software. 124 125:: 126 127 - hosts: backup01.srv.local 128 vars: 129 user: backup 130 group: backup 131 home: /home/backup 132 pool: "{{ home }}/repos" 133 auth_users: 134 - host: johndoe.clnt.local 135 key: "{{ lookup('file', '/path/to/keys/johndoe.clnt.local.pub') }}" 136 - host: web01.clnt.local 137 key: "{{ lookup('file', '/path/to/keys/web01.clnt.local.pub') }}" 138 - host: app01.clnt.local 139 key: "{{ lookup('file', '/path/to/keys/app01.clnt.local.pub') }}" 140 tasks: 141 - package: name=borg state=present 142 - group: name="{{ group }}" state=present 143 - user: name="{{ user }}" shell=/bin/bash home="{{ home }}" createhome=yes group="{{ group }}" groups= state=present 144 - file: path="{{ home }}" owner="{{ user }}" group="{{ group }}" mode=0700 state=directory 145 - file: path="{{ home }}/.ssh" owner="{{ user }}" group="{{ group }}" mode=0700 state=directory 146 - file: path="{{ pool }}" owner="{{ user }}" group="{{ group }}" mode=0700 state=directory 147 - authorized_key: user="{{ user }}" 148 key="{{ item.key }}" 149 key_options='command="cd {{ pool }}/{{ item.host }};borg serve --restrict-to-path {{ pool }}/{{ item.host }}",restrict' 150 with_items: "{{ auth_users }}" 151 - file: path="{{ home }}/.ssh/authorized_keys" owner="{{ user }}" group="{{ group }}" mode=0600 state=file 152 - file: path="{{ pool }}/{{ item.host }}" owner="{{ user }}" group="{{ group }}" mode=0700 state=directory 153 with_items: "{{ auth_users }}" 154 155Salt 156---- 157 158This is a configuration similar to the one above, configured to be deployed with 159Salt running on a Debian system. 160 161:: 162 163 Install borg backup from pip: 164 pkg.installed: 165 - pkgs: 166 - python3 167 - python3-dev 168 - python3-pip 169 - python-virtualenv 170 - libssl-dev 171 - openssl 172 - libacl1-dev 173 - libacl1 174 - build-essential 175 - libfuse-dev 176 - fuse 177 - pkg-config 178 pip.installed: 179 - pkgs: ["borgbackup"] 180 - bin_env: /usr/bin/pip3 181 182 Setup backup user: 183 user.present: 184 - name: backup 185 - fullname: Backup User 186 - home: /home/backup 187 - shell: /bin/bash 188 # CAUTION! 189 # If you change the ssh command= option below, it won't necessarily get pushed to the backup 190 # server correctly unless you delete the ~/.ssh/authorized_keys file and re-create it! 191 {% for host in backupclients %} 192 Give backup access to {{host}}: 193 ssh_auth.present: 194 - user: backup 195 - source: salt://conf/ssh-pubkeys/{{host}}-backup.id_ecdsa.pub 196 - options: 197 - command="cd /home/backup/repos/{{host}}; borg serve --restrict-to-path /home/backup/repos/{{host}}" 198 - restrict 199 {% endfor %} 200 201 202Enhancements 203------------ 204 205As this section only describes a simple and effective setup it could be further 206enhanced when supporting (a limited set) of client supplied commands. A wrapper 207for starting `borg serve` could be written. Or borg itself could be enhanced to 208autodetect it runs under SSH by checking the `SSH_ORIGINAL_COMMAND` environment 209variable. This is left open for future improvements. 210 211When extending ssh autodetection in borg no external wrapper script is necessary 212and no other interpreter or application has to be deployed. 213 214See also 215-------- 216 217* `SSH Daemon manpage <https://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man8/sshd.8>`_ 218* `Ansible <https://docs.ansible.com>`_ 219* `Salt <https://docs.saltstack.com/>`_ 220