فهرست منبع

add cloud backups role

Blaine Story 3 سال پیش
والد
کامیت
0f73c4065a

+ 2 - 2
group_vars/shareunderware.yml

@@ -4,7 +4,7 @@ container_uid: 1001
 container_group: "{{ container_user }}"
 container_gid: "{{ container_uid }}"
 
-appdata_path: /opt
+backups: containers
 
 global_env_vars:
   - PUID={{ container_uid }}
@@ -24,7 +24,7 @@ containers:
       - 80:80
       - 443:443
     volumes:
-      - "{{ appdata_path }}/swag:/config"
+      - /opt/swag:/config
     restart: unless-stopped
     include_global_env_vars: true
     environment:

+ 4 - 4
group_vars/warchildstory.yml

@@ -4,7 +4,7 @@ container_uid: 1001
 container_group: "{{ container_user }}"
 container_gid: "{{ container_uid }}"
 
-appdata_path: /opt
+backups: containers
 
 global_env_vars:
   - PUID={{ container_uid }}
@@ -31,7 +31,7 @@ containers:
       - 80:80
       - 443:443
     volumes:
-      - "{{ appdata_path }}/swag:/config"
+      - /opt/swag:/config
     restart: unless-stopped
     include_global_env_vars: true
     environment:
@@ -49,7 +49,7 @@ containers:
     container_name: grocy
     include_global_env_vars: true
     volumes:
-      - "{{ appdata_path }}/grocy:/config"
+      - /opt/grocy:/config
     restart: unless-stopped
     networks:
       - warchildstory
@@ -61,7 +61,7 @@ containers:
     container_name: list
     include_global_env_vars: true
     volumes:
-      - "{{ appdata_path }}/list:/config"
+      - /opt/list:/config
     restart: unless-stopped
     networks:
       - warchildstory

+ 2 - 0
hosts.ini

@@ -30,6 +30,8 @@ shareunderware.com
 [libreelec:vars]
 ansible_ssh_user=root
 
+
+
 #[weber]
 #weber-server
 #weber-kodi

+ 2 - 0
plays/nodes/shareunderware.yml

@@ -7,3 +7,5 @@
   roles:
     - role: docker
     - role: statusservices
+    - role: cloud-backups
+      tags: rclone

+ 2 - 0
plays/nodes/warchildstory.yml

@@ -7,3 +7,5 @@
   roles:
     - role: docker
     - role: statusservices
+    - role: cloud-backups
+      tags: rclone

+ 48 - 0
roles/cloud-backups/tasks/main.yml

@@ -0,0 +1,48 @@
+---
+- name: Install necessary packages
+  package:
+    name:
+      - rclone
+    state: present
+
+- name: Create rclone config directory
+  file:
+    path: /root/.config/rclone
+    state: directory
+    owner: root
+    group: root
+    mode: '0755'
+
+- name: Install rclone.conf
+  template:
+    src: rclone.conf.j2
+    dest: /root/.config/rclone/rclone.conf
+    owner: root
+    group: root
+    mode: '0600'
+
+- name: Create rclone log directory
+  file:
+    path: /var/log/rclone
+    state: directory
+    owner: root
+    group: root
+    mode: '0750'
+
+- name: Copy Backup scripts
+  template:
+    src: backup-to-b2.sh.j2
+    dest: /usr/local/bin/backup-to-b2.sh
+    owner: root
+    group: root
+    mode: '0755'
+
+- name: Create cronjob to backup data to b2
+  cron:
+    name: "weekly data syncs to backblaze b2"
+    weekday: '0'
+    minute: '15'
+    hour: '3'
+    user: root
+    job: "/usr/local/bin/backup-to-b2.sh"
+    state: present

+ 11 - 0
roles/cloud-backups/templates/backup-to-b2.sh-WeberServer.j2

@@ -0,0 +1,11 @@
+#!/bin/bash
+# {{ ansible_managed }}
+
+LOG_FILE="/var/log/rclone.log"
+
+# Container Data
+echo "Starting backup of container data..." | ts "%Y/%m/%d %H:%M:%S" >> "$LOG_FILE"
+
+/usr/bin/rclone copy /opt/ b2-container-data:current/Weber --backup-dir=b2-container-data:old/Weber --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --exclude "*log" --log-file=$LOG_FILE -v
+
+echo "Finished backing up container data" | ts "%Y/%m/%d %H:%M:%S" >> "$LOG_FILE"

+ 68 - 0
roles/cloud-backups/templates/backup-to-b2.sh-tvheadend.j2

@@ -0,0 +1,68 @@
+#!/bin/bash
+# {{ ansible_managed }}
+
+EMAIL_ADDRESS="blaine@nas.home.lan"
+LOG_FILE="/var/log/rclone.log"
+
+LOG_DIR="/var/log/rclone/$(date +%Y-%m-%d)"
+
+mkdir -p "$LOG_DIR"
+
+# Photos 
+PHOTOS_LOG="/tmp/b2-photos.log"
+> $PHOTOS_LOG
+echo "Starting backup of photos..." | ts >> "$LOG_FILE"
+#/usr/bin/rclone copy /mnt/nas/private/Photos b2-photos:current --backup-dir=b2-photos:old --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --exclude "*DS_Store" --log-file=$PHOTOS_LOG | ts | tee -a "$LOG_FILE"
+/usr/bin/rclone copy /mnt/nas/private/Photos b2-photos:current --fast-list --immutable --exclude "*DS_Store" --log-file=$PHOTOS_LOG -v | ts | tee -a "$LOG_FILE"
+
+if [[ $? > 0 ]]; then
+  mail -s "[$(hostname)] rclone - Photos Backup Error" "$EMAIL_ADDRESS" < $PHOTOS_LOG
+fi
+
+mv "$PHOTOS_LOG" "$LOG_DIR"
+
+echo "Finished backing up photos" | ts >> "$LOG_FILE"
+
+
+# Data
+DATA_LOG="/tmp/b2-data.log"
+> $DATA_LOG
+echo "Starting backup of data..." | ts >> "$LOG_FILE"
+/usr/bin/rclone copy /mnt/nas/private/Data b2-data:current --backup-dir=b2-data:old --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --exclude "*DS_Store" --log-file=$DATA_LOG -v | ts | tee -a "$LOG_FILE"
+
+if [[ $? > 0 ]]; then
+  mail -s "[$(hostname)] rclone - Data Backup Error" "$EMAIL_ADDRESS" < $PHOTOS_LOG
+fi
+
+mv "$DATA_LOG" "$LOG_DIR"
+
+echo "Finished backing up data" | ts >> "$LOG_FILE"
+
+
+# Music
+MUSIC_LOG="/tmp/b2-music.log"
+> $MUSIC_LOG
+echo "Starting backup of music..." | ts >> "$LOG_FILE"
+/usr/bin/rclone copy /mnt/nas/public b2-music:current --backup-dir=b2-music:old --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --include=Music/** --include="Music Videos"/** --log-file=$MUSIC_LOG -v | ts | tee -a "$LOG_FILE"
+
+if [[ $? > 0 ]]; then
+  mail -s "[$(hostname)] rclone - Music Backup Error" "$EMAIL_ADDRESS" < $MUSIC_LOG
+fi
+
+mv "$MUSIC_LOG" "$LOG_DIR"
+
+echo "Finished backing up music" | ts >> "$LOG_FILE"
+
+# Recipes
+RECIPES_LOG="/tmp/b2-recipes.log"
+> $RECIPES_LOG
+echo "Starting backup of recipes..." | ts >> "$LOG_FILE"
+/usr/bin/rclone copy /mnt/nas/public b2-data:current --backup-dir=b2-data:old --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --include=Recipes/**  --log-file=$RECIPES_LOG -v | ts | tee -a "$LOG_FILE"
+
+if [[ $? > 0 ]]; then
+  mail -s "[$(hostname)] rclone - Recipes Backup Error" "$EMAIL_ADDRESS" < $RECIPES_LOG
+fi
+
+mv "$RECIPES_LOG" "$LOG_DIR"
+
+echo "Finished backing up recipes" | ts >> "$LOG_FILE"

+ 90 - 0
roles/cloud-backups/templates/backup-to-b2.sh.j2

@@ -0,0 +1,90 @@
+#!/bin/bash
+# {{ ansible_managed }}
+
+EMAIL_ADDRESS="root@localhost"
+LOG_FILE="/var/log/rclone/rclone-$(date +%Y-%m-%d).log"
+
+
+{% if backups is defined and 'containers' in backups %}
+{% if containers is defined %}
+echo "### START CONTAINERS ###" | ts >> "$LOG_FILE"
+{% for container in containers %}
+{% if container.volumes is defined %}
+{% for volume in container.volumes %}
+echo "Starting backup of container '{{ container.service_name }}' volume '{{ volume | regex_replace(':.*') }}'." | ts >> "$LOG_FILE"
+/usr/bin/rclone copy {{ volume | regex_replace(':.*') }}/ b2-container-data:current/{{ ansible_hostname }}/{{ container.service_name }}/{{ volume | regex_replace(':.*') | basename }} \
+      --backup-dir=b2-container-data:old/{{ ansible_hostname }}/{{ container.service_name }}/{{ volume | regex_replace(':.*') | basename }} \
+      --suffix=-$(date +%Y-%m-%d) \
+      --fast-list \
+      --suffix-keep-extension \
+      --exclude "*log" \
+      --log-file="$LOG_FILE" -v
+echo "Finished backup of container '{{ container.service_name }}' volume '{{ volume | regex_replace(':.*') }}'." | ts >> "$LOG_FILE"
+
+{% endfor %}
+{% endif %}
+{% endfor %}
+{% endif %} 
+{% endif %}
+
+
+{% if ansible_hostname == 'tvheadend' %}
+## Photos 
+PHOTOS_LOG="/tmp/b2-photos.log"
+> $PHOTOS_LOG
+echo "Starting backup of photos..." | ts >> "$LOG_FILE"
+#/usr/bin/rclone copy /mnt/nas/private/Photos b2-photos:current --backup-dir=b2-photos:old --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --exclude "*DS_Store" --log-file=$PHOTOS_LOG | ts | tee -a "$LOG_FILE"
+/usr/bin/rclone copy /mnt/nas/private/Photos b2-photos:current --fast-list --immutable --exclude "*DS_Store" --log-file=$PHOTOS_LOG -v | ts | tee -a "$LOG_FILE"
+
+if [[ $? > 0 ]]; then
+  mail -s "[$(hostname)] rclone - Photos Backup Error" "$EMAIL_ADDRESS" < $PHOTOS_LOG
+fi
+
+mv "$PHOTOS_LOG" "$LOG_DIR"
+
+echo "Finished backing up photos" | ts >> "$LOG_FILE"
+
+
+# Data
+DATA_LOG="/tmp/b2-data.log"
+> $DATA_LOG
+echo "Starting backup of data..." | ts >> "$LOG_FILE"
+/usr/bin/rclone copy /mnt/nas/private/Data b2-data:current --backup-dir=b2-data:old --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --exclude "*DS_Store" --log-file=$DATA_LOG -v | ts | tee -a "$LOG_FILE"
+
+if [[ $? > 0 ]]; then
+  mail -s "[$(hostname)] rclone - Data Backup Error" "$EMAIL_ADDRESS" < $PHOTOS_LOG
+fi
+
+mv "$DATA_LOG" "$LOG_DIR"
+
+echo "Finished backing up data" | ts >> "$LOG_FILE"
+
+
+# Music
+MUSIC_LOG="/tmp/b2-music.log"
+> $MUSIC_LOG
+echo "Starting backup of music..." | ts >> "$LOG_FILE"
+/usr/bin/rclone copy /mnt/nas/public b2-music:current --backup-dir=b2-music:old --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --include=Music/** --include="Music Videos"/** --log-file=$MUSIC_LOG -v | ts | tee -a "$LOG_FILE"
+
+if [[ $? > 0 ]]; then
+  mail -s "[$(hostname)] rclone - Music Backup Error" "$EMAIL_ADDRESS" < $MUSIC_LOG
+fi
+
+mv "$MUSIC_LOG" "$LOG_DIR"
+
+echo "Finished backing up music" | ts >> "$LOG_FILE"
+
+# Recipes
+RECIPES_LOG="/tmp/b2-recipes.log"
+> $RECIPES_LOG
+echo "Starting backup of recipes..." | ts >> "$LOG_FILE"
+/usr/bin/rclone copy /mnt/nas/public b2-data:current --backup-dir=b2-data:old --suffix=-$(date +%Y-%m-%d) --fast-list --suffix-keep-extension --include=Recipes/**  --log-file=$RECIPES_LOG -v | ts | tee -a "$LOG_FILE"
+
+if [[ $? > 0 ]]; then
+  mail -s "[$(hostname)] rclone - Recipes Backup Error" "$EMAIL_ADDRESS" < $RECIPES_LOG
+fi
+
+mv "$RECIPES_LOG" "$LOG_DIR"
+
+echo "Finished backing up recipes" | ts >> "$LOG_FILE"
+{% endif %}

+ 65 - 0
roles/cloud-backups/templates/rclone.conf.j2

@@ -0,0 +1,65 @@
+[b2-unencrypted]
+type = b2
+account = {{ b2_account_key }}
+key = {{ b2_key_id }}
+hard_delete = true
+
+[wasabi-unencrypted]
+type = s3
+provider = Wasabi
+env_auth = false
+access_key_id = {{ wasabi_access_key }}
+secret_access_key = {{ wasabi_secret_access_key }}
+endpoint = s3.us-west-1.wasabisys.com
+
+{% if backups == 'all' or 'full_images' in backups %}
+[b2-backups]
+type = crypt
+remote = b2-unencrypted:{{ b2_backups_bucket }}
+filename_encryption = standard
+password = {{ b2_backups_config_encryption_password }}
+password2 = {{ b2_backups_config_encryption_salt }}
+
+[wasabi-backups]
+type = crypt
+remote = wasabi-unencrypted:{{ wasabi_backups_bucket }}
+filename_encryption = standard
+password = {{ b2_backups_config_encryption_password }}
+password2 = {{ b2_backups_config_encryption_salt }}
+
+{% endif %}
+{% if backups == 'all' or 'nasdata' in backups %}
+[b2-data]
+type = crypt
+remote = b2-unencrypted:{{ b2_data_bucket }}
+filename_encryption = standard
+directory_name_encryption = true
+password = {{ b2_data_config_encryption_password }}
+password2 = {{ b2_data_config_encryption_salt }}
+
+[b2-music]
+type = crypt
+remote = b2-unencrypted:{{ b2_music_bucket }}
+filename_encryption = standard
+directory_name_encryption = true
+password = {{ b2_music_config_encryption_password }}
+password2 = {{ b2_music_config_encryption_salt }}
+
+[b2-photos]
+type = crypt
+remote = b2-unencrypted:{{ b2_photos_bucket }}
+filename_encryption = standard
+directory_name_encryption = true
+password = {{ b2_photos_config_encryption_password }}
+password2 = {{ b2_photos_config_encryption_salt }}
+
+{% endif %}
+{% if backups == 'all' or 'containers' in backups %}
+[b2-container-data]
+type=crypt
+remote = b2-unencrypted:{{ b2_container_data_bucket }}
+filename_encryption = standard
+directory_name_encryption = true
+password = {{ b2_container_data_encryption_password }}
+password2 = {{ b2_container_data_encryption_salt }}
+{% endif %}