#!/bin/bash # # synchole.sh # Pi-Hole syncronizer # # **** configuration **** MASTER="10.1.3.2" #IP or hostname of the MASTER server DEBUG=1 #enable verbose output (1=on, 0=off) BACKUP_VERSIONS=10 #how many backups should be kept BACKUP_PATH="/etc/pihole/synchole-backups" #path to backups DOWNLOAD_PATH="/tmp/synchole-downloads" #path to list downloads LISTS="whitelist.txt blacklist.txt regex.list" #pihole files to sync LISTS_PATH="/etc/pihole" #pihole files path NAME="synchole" VERSION="0.1" AUTHOR="david@socialnerds.org" LICENSE="GPLv3" DEPENDENCIES="wget" # **** functions **** ## check for elevated privileges amiroot() { if [ $(whoami) != "root" ]; then return 1 fi } ## check if pi-hole is installed amipihole() { if [ ! $(which /usr/local/bin/pihole) ]; then return 1 fi } ## output handling log() { if [ -t 1 ]; then CRON=0 else CRON=1 fi case $1 in "error") level="\033[31m✗\033[0m" ;; "warn") level="\033[33m!\033[0m" ;; "debug") if [ $DEBUG -eq 1 ] && [ $CRON -eq 0 ]; then level="\033[2md\033[0m" else return 0 fi ;; "success") if [ $CRON -eq 0 ]; then level="\033[32m✓\033[0m" else return 0 fi ;; "info") if [ $CRON -eq 0 ]; then level="i" else return 0 fi ;; *) level="\033[31mLoglevel unknown. Programming error? ($1)\033[0m" ;; esac sleep 0.5; echo -e "[$NAME]-[$level] ${@:2}" } ## backup single list file to $BACKUP_PATH backup_list() { if [ -z $1 ]; then return 1 else for VERSION in $(eval echo {$BACKUP_VERSIONS..1}); do if [ -w $BACKUP_PATH/$1.$VERSION ]; then if [ $VERSION -eq $BACKUP_VERSIONS ]; then rm $BACKUP_PATH/$1.$VERSION else mv $BACKUP_PATH/$1.$VERSION $BACKUP_PATH/$1.$(($VERSION+1)) fi fi done if [ -w $BACKUP_PATH/$1 ]; then cp $BACKUP_PATH/$1 $BACKUP_PATH/$1.1 fi if [ -r $LISTS_PATH/$1 ]; then cp $LISTS_PATH/$1 $BACKUP_PATH/$1 if [ $? -ne 0 ]; then return 1 fi fi fi } ## create path/to/folder if it does not exist create_path() { if [ -z $1 ]; then return 1 else if [ ! -d $1 ]; then mkdir -p $1 if [ $? -ne 0 ]; then return 1 fi fi fi } ## update pi-hole lists (run updateGravity) update_gravity() { /usr/local/bin/pihole -g > /dev/null if [ $? -ne 0 ]; then return 1 fi } ## install new list install_list() { if [ -z $1 ]; then return 1 else cp $DOWNLOAD_PATH/$1 $LISTS_PATH/$1 if [ $? -ne 0 ]; then return 1 fi fi } ## download remote file download_list() { if [ -z $1 ]; then return 1 else wget http://$MASTER/synchole/$1 -q -O $DOWNLOAD_PATH/$1 if [ $? -ne 0 ]; then return 1 fi fi } # **** start of script **** log debug "Starting synchole" ## preflight checks log debug "Running preflight checks" if ! amiroot; then log error "You must be root" exit 1 fi if ! amipihole; then log error "I am no pihole" exit 1 fi for DEPENDENCY in $DEPENDENCIES; do if [ ! $(which $DEPENDENCY) ]; then log error "$DEPENDENCY is not installed" exit 1 fi done log success "Preflight checks passed successfully" ## generate $BACKUP_PATH and $DOWNLOAD_PATH if not available if ! create_path $DOWNLOAD_PATH; then log error "Something went wrong while creating $DOWNLOAD_PATH" exit 1 fi if ! create_path $BACKUP_PATH; then log error "Something went wrong while creating $BACKUP_PATH" exit 1 fi ## download remote files from MASTER and backup local lists CHANGES=0 for LIST in $LISTS; do log debug "Downloading $LIST from $MASTER" if ! download_list $LIST; then log error "Something went wrong while downloading $LIST" exit 1 else log success "Successfully downloaded $LIST" fi #TODO: don't install new list if to many changes or # somehow verify if new file is an actual list # maybe check if wget actually downloaded a file or were we redirected diff $DOWNLOAD_PATH/$LIST $LISTS_PATH/$LIST if [ $? -ne 0 ]; then log debug "Backing up $LIST" if [ -r $LISTS_PATH/$LIST ]; then if ! backup_list $LIST; then log error "Something went wrong while backing up $LIST" exit 1 else log debug "Successfully backed up $LIST" fi else log debug "$LIST not found, skipping" fi log debug "Installing $LIST." if ! install_list $LIST; then log error "Something went wrong while installing $LIST" exit 1 else log success "Successfully installed new $LIST" CHANGES=1 fi else log debug "No changes in $LIST" fi done ## run updateGravity if [ $CHANGES -eq 1 ]; then log debug "Updating gravity" if ! update_gravity; then log error "Something went wrong while updating gravity" exit 1 else log success "Gravity has been successfully updated" fi else log debug "No files have been changed, skipping gravity update" fi #TODO: sync hosts and restartdns on changes exit 0 # **** end of script ****