Installation

Installation with Ansible

Two roles are used to install the project:

Important

1) Required collections

The roles vbotka.rcb and vbotka.rsnapshot require collection community.general. In addition to this, vbotka.rcb requires also community.crypto. These collections should be included in standard Ansible packages. If they are not or if you want to use the latest versions install them

shell> ansible-galaxy collections install community.crypto
shell> ansible-galaxy collections install community.general

2) Install rsnapshot

Use Ansible role vbotka.rsnapshot to install and configure rsnapshot on the clients.

shell> ansible-galaxy install vbotka.rsnapshot

Create playbook

shell> cat rsnapshot.yml
- hosts: rcb_clients
  become: true
  become_user: root
  become_method: sudo
  roles:
    - vbotka.rsnapshot

Configure rsnapshot

rsnapshot_test: true
rsnapshot_no_create_root: '0'
rsnapshot_backup_points:
  - {dir: /etc/, host: localhost/}
  - {dir: /usr/local/etc/, host: localhost/}
  - {dir: /var/backups/, host: localhost/}
rsnapshot_backup_points_test:
  - {dir: /scratch/rcb-test/, host: localhost/}
rsnapshot_exclude:
  - regex: '.git/'
  - regex: '.#*'

Run the playbook

shell> ansible-playbook rsnapshot.yml

3) Install rcb

Use Ansible roles vbotka.rcb and vbotka.ansible_lib

shell> ansible-galaxy install vbotka.rcb
shell> ansible-galaxy install vbotka.ansible_lib

Download the example of an Ansible project

Download the examples of the Ansible playbooks, inventory and configuration

shell> tree .
├── ansible.cfg
├── hosts
├── rcb-backup-server.yml
├── rcb-devel.yml
├── rcb_privatekey_passphrase.yml
└── rcb.yml

The playbooks rcb.yml and rcb-backup-server.yml configure the rcb-clients and rcb-server respectively (see Inventory hosts below). The playbook rcb-devel.yml is used in the development. The file rcb_privatekey_passphrase.yml keeps the passphrase. It’s plain-text for the purpose of testing. In production, you might want to encrypt it by Ansible vault or any other password management.

4) Configure rcb

Configuration ansible.cfg

In the configuration file ansible.cfg change roles_path to where you installed the role vbotka.rcb

[defaults]
inventory = $PWD/hosts
roles_path = $HOME/.ansible/roles
stdout_callback = yaml

Inventory hosts

In the inventory hosts, there are two groups. To test the project, there is only one host in each group. Later you might want add more clients and, optionally, more servers. Fit the hosts and the variables to your needs

[rcb_clients]
10.1.0.12

[rcb_clients:vars]
ansible_connection=ssh
ansible_user=admin
ansible_python_interpreter=/usr/bin/python3.10

[rcb_server]
10.1.0.10

[rcb_server:vars]
ansible_connection=ssh
ansible_user=admin
ansible_python_interpreter=/usr/local/bin/python3.8

Common variables in rcb.yml and rcb-backup-server.yml

Change the below variables in both playbooks:

  • rcb_root_public_keys_dir: The directory on the Ansible controller to store the public keys of the clients.

  • rcb_bck_dst: The directory on the backup server to store the backups.

  • rcb_bck_user: The owner of the directory rcb_bck_dst

  • rcb_bck_group: The group of the directory rcb_bck_dst

Playbook rcb.yml

In the playbook rcb.yml which will configure the client(s) in the inventory group rcb_clients, change at least following variables:

  • rcb_bck_host: The backup server.

  • rcb_rcb_bck_root: The directory on the client which will be synchronized to backup server {{ rcb_bck_dst }}/{{ ansible_hostname }}

  • rcb_rcb_rst_root: The directory on the client where the backup from the server will be eventually restored.

  • rcb_rcb_crt_root: The directory for the client certificate, keys, and passphrase.

  • rcb_cert_cn: CN of the client certificate.

---

- hosts: rcb_clients
  become: true
  become_user: root
  become_method: sudo

  vars_files:
    - rcb_privatekey_passphrase.yml

  vars:

    rcb_bck_host: 10.1.0.10
    rcb_bck_dst: /export/rcbackup
    rcb_bck_dst_test: /export/rcbackup-test
    rcb_root_public_keys_dir: copy/rcb-root-ssh-pub-keys
    rcb_rcb_bck_root: /export/backup
    rcb_rcb_rst_root: /export/restore
    rcb_rcb_crt_root: /root/rcb/cert
    rcb_cert_cn: rcb_client_01.example.org

  roles:
    - vbotka.rcb

# EOF
...

Playbook rcb-backup-server.yml

In the playbook rcb-backup-server.yml which will configure the server(s) in the inventory group rcb_server, change at least the variable:

  • rcb_bck_shell: The login shell of rcb_bck_user

---

- hosts: rcb_server
  become: true
  become_user: root
  become_method: sudo

  vars:

    rcb_root_public_keys_dir: copy/rcb-root-ssh-pub-keys
    rcb_bck_dst: /export/rcbackup
    rcb_bck_dst_test: /export/rcbackup-test
    rcb_bck_user: rcbackup
    rcb_bck_group: rcbackup
    rcb_bck_shell: /usr/local/bin/bash

  tasks:

    - name: "Create user {{ rcb_bck_user }}"
      ansible.builtin.user:
        name: "{{ rcb_bck_user }}"
        shell: "{{ rcb_bck_shell }}"
      register: rcbuser

    - name: "Create directories"
      ansible.builtin.file:
        state: directory
        path: "{{ item }}"
        owner: "{{ rcb_bck_user }}"
        group: "{{ rcb_bck_group }}"
        mode: '0700'
      loop:
        - "{{ rcb_bck_dst }}"
        - "{{ rcb_bck_dst_test }}"

    - name: "Debug Public keys"
      ansible.builtin.debug:
        msg: "Public key {{ item }}"
      with_fileglob: "{{ rcb_root_public_keys_dir }}/{{ inventory_hostname }}/*.id_rsa.pub"
      loop_control:
        label: "{{ item|basename }}"
      when: debug|d(false)|bool

    - name: "Set up authorized_keys for {{ rcb_bck_user }}
             to {{ rcb_root_public_keys_dir }}/{{ inventory_hostname }}"
      ansible.posix.authorized_key:
        user: "{{ rcb_bck_user }}"
        key: "{{ lookup('file', '{{ item }}')}}"
      with_fileglob: "{{ rcb_root_public_keys_dir }}/{{ inventory_hostname }}/*.id_rsa.pub"
      loop_control:
        label: "{{ item|basename }}"

# EOF
...

Note

You can customize this playbook and depending on the OS install the required rsync.

File rcb_privatekey_passphrase.yml

Create a file with passphrase to the private key of the client certificate

rcb_privatekey_passphrase: my secret passphrase

Include the file rcb_privatekey_passphrase.yml in the playbook rcb.yml. The passphrase will be used to generate OpenSSL:

  • Private key {{ rcb_rcb_crt_root }}/backup.key

  • Certificate Signing Request {{ rcb_rcb_crt_root }}/backup.csr

  • Self Signed Certificate {{ rcb_rcb_crt_root }}/backup.crt

For later use, the passphrase will be stored in the file {{ rcb_privatekey_passphrase_file }} (default={{ rcb_rcb_crt_root }}/pem-pass-phrase).

Important

  • Enable DEFAULT_GATHERING. The variables ansible_os_family and ansible_distribution_* are needed to customize variables.

  • The variable ansible_hostname is needed to configure rcb_clients.

Review the configuration

Enable both rcb_debug and rcb_debug_classified

shell> ansible-playbook -t rcb_debug -e rcb_debug=true -e rcb_debug_classified=true rcb.yml

PLAY [10.1.0.12] *********************************************************************************

TASK [Gathering Facts] ***********************************************************************
ok: [10.1.0.12]

TASK [vbotka.rcb : vars: Set variables for al_include_os_vars_path] **************************
ok: [10.1.0.12]

TASK [vars: Include OS vars] *****************************************************************

TASK [vbotka.ansible_lib : al_include_os_vars_path: Debug] ***********************************
skipping: [10.1.0.12]

TASK [vbotka.ansible_lib : al_include_os_vars_path: End of play when al_os_vars_path not defined] ***
skipping: [10.1.0.12]

TASK [vbotka.ansible_lib : al_include_os_vars_path: Vars from /home/admin/.ansible/roles/vbotka.rcb/vars/defaults] ***
ok: [10.1.0.12]

TASK [vbotka.ansible_lib : al_include_os_vars_path: Debug result] ****************************
skipping: [10.1.0.12]

TASK [vbotka.ansible_lib : al_include_os_vars_path: Vars from /home/admin/.ansible/roles/vbotka.rcb/vars] ***
ok: [10.1.0.12]

TASK [vbotka.rcb : debug: RCB] ***************************************************************
ok: [10.1.0.12] => 
  msg: |-
    ansible_architecture: x86_64
    ansible_os_family: Debian
    ansible_distribution: Ubuntu
    ansible_distribution_major_version: 22
    ansible_distribution_version: 22.04
    ansible_distribution_release: jammy
    ansible_python_version: 3.10.12
    ansible_hostname: rcb_client_01.example.org
  
    rcb_apt_update_cache: False
    ubuntu_cache_valid_time: 14400
    rcb_install: True
    rcb_packages:
      - bash
      - git
      - hashdeep
      - rsnapshot
      - rsyncrypto
      - mtree-netbsd
      - bsd-mailx
  
    rcb_source_version: 1.1.2
    rcb_source_ignore_current_lock: False
    rcb_source_file: 1.1.2.tar.gz
    rcb_source_dir: rcb-1.1.2
    rcb_source_dest: /usr/local/src
    rcb_source_url: https://github.com/vbotka/rcb/archive
  
    rcb_root_public_keys_dir: copy/rcb-root-ssh-pub-keys
    rcb_bin_dir: /root/bin
    rcb_etc_dir: /usr/local/etc
  
    rcb_conf: rcb.conf
    rcb_rsnapshot_conf: rsnapshot.conf
    rcb_backup_conf: False
    rcb_rcb_email: root
    rcb_rcb_bck_root: /export/backup
    rcb_rcb_bck_prefix: snapshots/hourly.0
    rcb_rsyncrypto_trim_e: 4
    rcb_rsyncrypto_trim_d: 3
    rcb_rcb_rst_root: /export/restore
    rcb_rcb_crt_root: /root/rcb/cert
  
    rcb_test: False
    rcb_conf_test: rcb-test.conf
    rcb_rsnapshot_conf_test: rsnapshot-test.conf
    rcb_bck_dst_test: /export/rcbackup-test
    rcb_rcb_bck_prefix_test: snapshots-test/hourly.0

    rcb_cert_cn: rcb_client_01.example.org
    rcb_privatekey_cipher: auto
    rcb_privatekey_passphrase_file: /root/rcb/cert/pem-pass-phrase
    rcb_privatekey_passphrase_owner: root
    rcb_privatekey_passphrase_group: admin
    rcb_privatekey_passphrase_mode: 0640
    rcb_bck_host: 10.1.0.10
    rcb_bck_user: rcbackup
    rcb_bck_group: rcbackup
    rcb_bck_dst: /export/rcbackup
    rcb_link_restore: True
  
    rcb_rsnapshot_cron: True
    rcb_rsnapshot_cron_user: root
    rcb_rsnapshot_cron_path: /root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    rcb_rsnapshot_cron_mailto : root
  
    rcb_privatekey_passphrase: my secret passphrase

PLAY RECAP ***********************************************************************************
10.1.0.12: ok=5    changed=0    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0

5) Run Ansible playbooks

Following workflow was tested with Ubuntu rcb_clients and FreeBSD rcb_server.

phase1. Create root’s SSH keys on rcb-clients

Create root’s SSH keys on the hosts from the inventory group rcb_clients and store the public keys on the localhost in the directory {{ rcb_root_public_keys_dir }}/{{ rcb_bck_host }}/root-{{ ansible_hostname }}.id_rsa.pub. root on the hosts from the inventory group rcb_clients will be authorized to ssh to {{ rcb_bck_user }}@{{ rcb_bck_host }}

shell> ansible-playbook -t phase1 rcb.yml

Configure rcb-server

Create user {{ rcb_bck_user }}. Create directories for encrypted backups {{ rcb_bck_dst }} and to test the encrypted backups {{ rcb_bck_dst_test }}. Configure the ssh access of rcb_clients to rcb_server. Put the root’s public keys of rcb_clients, created in phase1, into the ~/.ssh/authorized_keys of {{ rcb_bck_user }} on the host(s) from the inventory group rcb_server.

shell> ansible-playbook rcb-backup-server.yml

phase2. Configure rcb-clients

shell> ansible-playbook -t phase2 rcb.yml