Initial Commit - Kumonoboru with working Actions
This commit is contained in:
31
.gitea/workflows/kumonoboru.yaml
Normal file
31
.gitea/workflows/kumonoboru.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
name: Configure Kumonoboru
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
run: |
|
||||||
|
apt -y update
|
||||||
|
apt -y install python3 python3-pip skopeo
|
||||||
|
|
||||||
|
- name: Install Ansible
|
||||||
|
run: |
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
pip install ansible
|
||||||
|
|
||||||
|
- name: Set up SSH
|
||||||
|
uses: webfactory/ssh-agent@v0.5.0
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Run Ansible Playbook
|
||||||
|
run: |
|
||||||
|
ansible-playbook -i inventory.yaml -e 'ANSIBLE_SUDO_PASS="${{ secrets.SUDO_PASS }}"' kumonoboru.yaml -vv
|
||||||
5
inventory.yaml
Normal file
5
inventory.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
all:
|
||||||
|
hosts:
|
||||||
|
takahe:
|
||||||
|
ansible_host: 192.168.0.66
|
||||||
|
ansible_user: shmick
|
||||||
8
kumonoboru.service.j2
Normal file
8
kumonoboru.service.j2
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Kumonoboru - cloud backup utility
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/bin/bash /usr/local/bin/kumonoboru.sh
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
185
kumonoboru.sh
Executable file
185
kumonoboru.sh
Executable file
@@ -0,0 +1,185 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
##Simple script to run Restic backups
|
||||||
|
|
||||||
|
help()
|
||||||
|
{
|
||||||
|
echo "Kumonoboru - Back up important location to the B2 cloud using Restic."
|
||||||
|
echo " {-c|--clean} -- Force prune of the remote repositories"
|
||||||
|
echo " {-r|--repository} repository -- Only backup the specified repository."
|
||||||
|
echo " {-l|--limit} #[Kbps] -- Limit upload & download speed"
|
||||||
|
echo " {-v|--verbose} -- Print debug messages"
|
||||||
|
echo " {-h|--help} -- Print this help message and exit"
|
||||||
|
echo "Available repositories:"
|
||||||
|
echo "Gerbil-TK Photos (path: /var/Red-Vol/Media/Pictures)"
|
||||||
|
echo "Pukeko-XYZ-Containers Containers (path: /var/Red-Vol/Media/Containers)"
|
||||||
|
echo "Pukeko-XYZ-Cloud Data from all devices (path: /var/Red-Vol/Media/Cloud)"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
#Pass arguments to the script
|
||||||
|
flags()
|
||||||
|
{
|
||||||
|
#This is utterly useless
|
||||||
|
if [[ $# == "0" ]]; then
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
while test $# -gt 0
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
(-c|--clean)
|
||||||
|
export CLEAN="1"
|
||||||
|
shift;;
|
||||||
|
(-r|--repository)
|
||||||
|
shift
|
||||||
|
export REPOSITORY="$1"
|
||||||
|
shift;;
|
||||||
|
(-l|--limit)
|
||||||
|
shift
|
||||||
|
export BWLIMIT="$1"
|
||||||
|
shift;;
|
||||||
|
(-h|--help)
|
||||||
|
help;;
|
||||||
|
(*) help;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
flags "$@"
|
||||||
|
|
||||||
|
#Defaults
|
||||||
|
if [[ -z $BWLIMIT ]]; then
|
||||||
|
export BWLIMIT="0"
|
||||||
|
else
|
||||||
|
echo -e "Bandwidth will be limited to" "$BWLIMIT Kbps"
|
||||||
|
fi
|
||||||
|
if [[ -n $CLEAN ]]; then
|
||||||
|
echo -e "Cleaning will take place per request."
|
||||||
|
fi
|
||||||
|
if [[ -n $REPOSITORY ]]; then
|
||||||
|
echo -e "Will only process repository" "$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export B2_ACCOUNT_ID=8582a42a3b99 #Master Key
|
||||||
|
export B2_ACCOUNT_KEY=00041845e8dd29d7e3d091d77bb8a631ee71332be7 #Master Application ID
|
||||||
|
RESTIC_PASSWORD='f$774$#je4%U8vp8ov*UsZMHqL$m3Smh#fEbbt7hyULQxfnnWmSiS5MEndzVWT$$n^@s$P*o4vV*^rgv3jvvrv@y35VppU$$y*vnG5V@botU&4$39Y6t9HSb3Z548M!4'
|
||||||
|
|
||||||
|
|
||||||
|
#Safety function; accepts repository to check
|
||||||
|
safety(){
|
||||||
|
REPOSITORY="$1"
|
||||||
|
echo -e "Checking if repository is in use - " "$REPOSITORY"
|
||||||
|
#Check no other Restic process is using this repository; Free unnecessary locks, if present
|
||||||
|
if [[ -n $(ps aux | grep restic | grep "$REPOSITORY") ]]; then
|
||||||
|
echo -e "Repository is in use - ignoring"
|
||||||
|
return 1
|
||||||
|
# ^ If there's a restic process holding the repository, leave it alone.
|
||||||
|
else
|
||||||
|
echo -e "Repository is not in use - unlocking"
|
||||||
|
restic -q -r b2:$REPOSITORY unlock
|
||||||
|
# ^ If a lock exists but no process, the repository is safe and should be unlocked.
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#Backup function; accepts repository and path to backup
|
||||||
|
backup(){
|
||||||
|
REPOSITORY="$1"
|
||||||
|
REPOSITORY_PATH="$2"
|
||||||
|
if safety "$REPOSITORY"; then
|
||||||
|
#Run the backup
|
||||||
|
echo -e "Backing up repository" "$REPOSITORY"
|
||||||
|
if restic --cache-dir="$RESTIC_CACHE_DIR" -r b2:"$REPOSITORY" backup "$REPOSITORY_PATH" --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT"; then
|
||||||
|
echo -e "$REPOSITORY_PATH" "completed upload to $REPOSITORY."
|
||||||
|
else
|
||||||
|
echo -e "$REPOSITORY failed to upload path" "$REPOSITORY_PATH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check(){
|
||||||
|
REPOSITORY="$1"
|
||||||
|
PRUNE="$2"
|
||||||
|
echo -e "Checking integrity (prune: $PRUNE) of repository" "$REPOSITORY"
|
||||||
|
## ^ This variable will have value if repo is already clean, indicating
|
||||||
|
#+ This is a post backup check.
|
||||||
|
if [[ -n $PRUNE ]]; then
|
||||||
|
echo -e "This repository has been cleaned already; will not clean again."
|
||||||
|
fi
|
||||||
|
if safety "$REPOSITORY"; then
|
||||||
|
echo -e "Checking repository health - " "$REPOSITORY"
|
||||||
|
if restic -r b2:"$REPOSITORY" check --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT"; then
|
||||||
|
echo -e "Repository passed integrity check - " "$REPOSITORY"
|
||||||
|
echo -e "Current snapshots:"
|
||||||
|
restic -r b2:"$REPOSITORY" snapshots | tee -a $LOG
|
||||||
|
else
|
||||||
|
echo -e "Repository failed integrity check - " "$REPOSITORY"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
clean(){
|
||||||
|
REPOSITORY="$1"
|
||||||
|
if safety "$REPOSITORY"; then
|
||||||
|
echo -e "Cleaning repository" "$REPOSITORY"
|
||||||
|
if restic -r b2:$REPOSITORY forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT"; then
|
||||||
|
echo -e "Repository is trim - " "$REPOSITORY"
|
||||||
|
echo -e "Running post clean check..."
|
||||||
|
check "$REPOSITORY" "1"
|
||||||
|
# Marks repository as cleaned already ^ so it won't passed to this function again.
|
||||||
|
else
|
||||||
|
echo -e "Failed to prune repository" "$REPOSITORY"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#If cleaning was forced, or if it's the first of this month - clean.
|
||||||
|
if [[ -n $CLEAN ]] || [[ $(date +%d) == "1" ]]; then
|
||||||
|
check Gerbil-TK
|
||||||
|
clean Gerbil-TK
|
||||||
|
check Pukeko-XYZ-Containers
|
||||||
|
clean Pukeko-XYZ-Containers
|
||||||
|
check Pukeko-XYZ-Cloud
|
||||||
|
clean Pukeko-XYZ-Cloud
|
||||||
|
|
||||||
|
#If a specific repository was requested, back it up; otherwise, back them all up.
|
||||||
|
elif [[ -n $REPOSITORY ]] && [[ -z $CLEAN ]]; then
|
||||||
|
case "$REPOSITORY" in
|
||||||
|
(Gerbil-TK)
|
||||||
|
backup Gerbil-TK /var/Red-Vol/Media/Pictures/
|
||||||
|
;;
|
||||||
|
(Pukeko-XYZ-Containers)
|
||||||
|
backup Pukeko-XYZ-Containers /var/Red-Vol/Media/Containers/
|
||||||
|
;;
|
||||||
|
(Pukeko-XYZ-Cloud)
|
||||||
|
backup Pukeko-XYZ-Cloud /var/Red-Vol/Media/Cloud/
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
help;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
#If cleaning was not forced, backup the repositories
|
||||||
|
elif [[ -z $CLEAN ]]; then
|
||||||
|
backup Gerbil-TK /var/Red-Vol/Media/Pictures/
|
||||||
|
backup Pukeko-XYZ-Containers /var/Red-Vol/Media/Containers/
|
||||||
|
backup Pukeko-XYZ-Cloud /var/Red-Vol/Media/Cloud/
|
||||||
|
|
||||||
|
#If a specific repository was requested to be cleaned, clean it
|
||||||
|
elif [[ -n $REPOSITORY ]] && [[ -n $CLEAN ]]; then
|
||||||
|
case "$REPOSITORY" in
|
||||||
|
(Gerbil-TK)
|
||||||
|
check Gerbil-TK
|
||||||
|
clean Gerbil-TK
|
||||||
|
;;
|
||||||
|
(Pukeko-XYZ-Containers)
|
||||||
|
check Pukeko-XYZ-Containers
|
||||||
|
clean Pukeko-XYZ-Containers
|
||||||
|
;;
|
||||||
|
(Pukeko-XYZ-Cloud)
|
||||||
|
check Pukeko-XYZ-Cloud
|
||||||
|
clean Pukeko-XYZ-Cloud
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
help;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
#Wrap up this run's log and report nicely
|
||||||
|
echo "All done; have a nice day!"
|
||||||
|
exit 0
|
||||||
9
kumonoboru.timer.j2
Normal file
9
kumonoboru.timer.j2
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Kumonoboru - cloud backup utility
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=daily
|
||||||
|
Persistent=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
32
kumonoboru.yaml
Normal file
32
kumonoboru.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
- hosts: takahe
|
||||||
|
gather_facts: no
|
||||||
|
become: yes
|
||||||
|
vars:
|
||||||
|
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
|
||||||
|
ansible_sudo_pass: "{{ ANSIBLE_SUDO_PASS }}"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install Restic
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: restic
|
||||||
|
state: latest
|
||||||
|
|
||||||
|
- name: Install kumonoboru
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: kumonoboru.sh
|
||||||
|
dest: /usr/local/bin/kumonoboru.sh
|
||||||
|
mode: 'a+x'
|
||||||
|
|
||||||
|
- name: Template service and timer to host
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ item }}.j2"
|
||||||
|
dest: /etc/systemd/system/{{ item }}
|
||||||
|
with_items:
|
||||||
|
- kumonoboru.service
|
||||||
|
- kumonoboru.timer
|
||||||
|
|
||||||
|
- name: Start kumonoboru timer
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: kumonoboru.timer
|
||||||
|
state: started
|
||||||
|
daemon_reload: true
|
||||||
Reference in New Issue
Block a user