refinded a bit more and updated README.md
This commit is contained in:
parent
38f2dfb6fa
commit
c540bc595b
23
README.md
23
README.md
|
@ -1,13 +1,13 @@
|
||||||
# synchole
|
# synchole
|
||||||
|
|
||||||
Shell script to syncronize two or more [pi-hole](https://pi-hole.net) servers. It replicates all changes to _blacklist.txt_, _whitelist.txt_, _regex.list_, _/etc/hosts_ and runs `updateGravity`/`restartdns` on all members.
|
Shell script to syncronize a SLAVE [pi-hole](https://pi-hole.net) server with a MASTER pi-hole server. It downloads _blacklist.txt_, _whitelist.txt_ and _regex.list_ from the MASTER, updates local files and runs `updateGravity` on the SLAVE.
|
||||||
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Login via SSH to the `MASTER` server.
|
1. Login via SSH to the `MASTER` server.
|
||||||
|
|
||||||
2. Create symlinks for all files you want to sync within the webroot of the `MASTER` pihole.
|
2. Create symlinks for all files you want to be able to sync within the webroot of the `MASTER` pihole.
|
||||||
```
|
```
|
||||||
cd /var/www/html
|
cd /var/www/html
|
||||||
sudo mkdir synchole
|
sudo mkdir synchole
|
||||||
|
@ -19,13 +19,15 @@ sudo ln -s /etc/pihole/regex.list .
|
||||||
|
|
||||||
3. Login via SSH to the `SLAVE` server.
|
3. Login via SSH to the `SLAVE` server.
|
||||||
|
|
||||||
4. Install synchole on the `SLAVE` server.
|
4. Install _wget_ and _[synchole](https://socialg.it/david/synchole)_ on the `SLAVE` server.
|
||||||
```
|
```
|
||||||
cd /opt
|
sudo apt-get update
|
||||||
sudo git clone https://socialg.it/david/synchole.git
|
sudo apt-get install wget
|
||||||
|
sudo wget https://socialg.it/david/synchole/raw/master/synchole.sh -O /usr/bin/synchole.sh
|
||||||
|
sudo chmod +x /usr/bin/synchole.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Configure the synchole script.
|
5. Configure the synchole script to your liking.
|
||||||
```
|
```
|
||||||
sudo vim /opt/synchole.sh
|
sudo vim /opt/synchole.sh
|
||||||
```
|
```
|
||||||
|
@ -35,14 +37,9 @@ The config section is at the top of the script.
|
||||||
```
|
```
|
||||||
sudo crontab -e
|
sudo crontab -e
|
||||||
```
|
```
|
||||||
Example cronjob: `*/5 * * * * /opt/synchole/synchole.sh -q` (this runs the synchole every 5 minutes)
|
Example cronjob: `*/5 * * * * /opt/synchole/synchole.sh -q` (this runs synchole every 5 minutes)
|
||||||
|
|
||||||
7. Setup postfix to send notifications (from cron) on the `SLAVE` server.
|
8. Repeat steps 3 through 6 for additional `SLAVE` servers.
|
||||||
```
|
|
||||||
<placeholder>
|
|
||||||
```
|
|
||||||
|
|
||||||
8. Repeat steps 3 through 7 for additional `SLAVE` servers.
|
|
||||||
|
|
||||||
9. Happy syncholeing!
|
9. Happy syncholeing!
|
||||||
|
|
||||||
|
|
191
synchole.sh
191
synchole.sh
|
@ -2,23 +2,25 @@
|
||||||
|
|
||||||
#
|
#
|
||||||
# synchole.sh
|
# synchole.sh
|
||||||
|
# Pi-Hole syncronizer
|
||||||
#
|
#
|
||||||
|
|
||||||
# **** configuration ****
|
# **** configuration ****
|
||||||
|
|
||||||
LISTS="whitelist.txt blacklist.txt regex.list" #pihole files to sync
|
|
||||||
LISTS_PATH="/etc/pihole" #pihole files path
|
|
||||||
MASTER="10.1.3.2" #IP or hostname of the MASTER server
|
MASTER="10.1.3.2" #IP or hostname of the MASTER server
|
||||||
DEBUG=1 #enable verbose output (1=on, 0=off)
|
DEBUG=1 #enable verbose output (1=on, 0=off)
|
||||||
BACKUP_PATH="/etc/pihole/synchole-backups" #path to backups
|
|
||||||
BACKUP_VERSIONS=10 #how many backups should be kept
|
BACKUP_VERSIONS=10 #how many backups should be kept
|
||||||
TEMP_PATH="/tmp/synchole-downloads" #path to list downloads
|
BACKUP_PATH="/etc/pihole/synchole-backups" #path to backups
|
||||||
DEPENDENCIES="wget"
|
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"
|
NAME="synchole"
|
||||||
VERSION="0.1"
|
VERSION="0.1"
|
||||||
AUTHOR="david@socialnerds.org"
|
AUTHOR="david@socialnerds.org"
|
||||||
LICENSE="GPLv3"
|
LICENSE="GPLv3"
|
||||||
|
DEPENDENCIES="wget"
|
||||||
|
|
||||||
|
|
||||||
# **** functions ****
|
# **** functions ****
|
||||||
|
@ -30,20 +32,13 @@ amiroot() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
## check for local environment
|
## check if pi-hole is installed
|
||||||
amipihole() {
|
amipihole() {
|
||||||
if [ ! $(which pihole) ]; then
|
if [ ! $(which pihole) ]; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
## check if system is debian based
|
|
||||||
amidebian() {
|
|
||||||
if [ ! $(which apt-get) ]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
## output handling
|
## output handling
|
||||||
log() {
|
log() {
|
||||||
case $1 in
|
case $1 in
|
||||||
|
@ -55,43 +50,23 @@ log() {
|
||||||
;;
|
;;
|
||||||
"debug")
|
"debug")
|
||||||
if [ $DEBUG -eq 1 ]; then
|
if [ $DEBUG -eq 1 ]; then
|
||||||
level="\033[2md\033[0m"
|
level="\033[2md\033[0m"
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
"success")
|
"success")
|
||||||
level="\033[32m✓\033[0m"
|
level="\033[32m✓\033[0m"
|
||||||
;;
|
;;
|
||||||
"info")
|
"info")
|
||||||
level=">"
|
level="i"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
level="\033[31mLoglevel unknown. Programming error? ($*)\033[0m"
|
level="\033[31mLoglevel unknown. Programming error? ($*)\033[0m"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
sleep 0.4; echo -e "[$NAME][$level] $2"
|
sleep 0.5; echo -e "[$level] $2"
|
||||||
}
|
|
||||||
|
|
||||||
## update package sources
|
|
||||||
update_repos() {
|
|
||||||
apt-get update > /dev/null
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
## install debian package
|
|
||||||
install_package() {
|
|
||||||
if [ -n $1 ]; then
|
|
||||||
apt-get install -y $1 &> /dev/null
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
## backup single list file to $BACKUP_PATH
|
## backup single list file to $BACKUP_PATH
|
||||||
|
@ -101,11 +76,11 @@ backup_list() {
|
||||||
else
|
else
|
||||||
for VERSION in $(eval echo {$BACKUP_VERSIONS..1}); do
|
for VERSION in $(eval echo {$BACKUP_VERSIONS..1}); do
|
||||||
if [ -w $BACKUP_PATH/$1.$VERSION ]; then
|
if [ -w $BACKUP_PATH/$1.$VERSION ]; then
|
||||||
if [ $VERSION -eq $BACKUP_VERSIONS ]; then
|
if [ $VERSION -eq $BACKUP_VERSIONS ]; then
|
||||||
rm $BACKUP_PATH/$1.$VERSION
|
rm $BACKUP_PATH/$1.$VERSION
|
||||||
else
|
else
|
||||||
mv $BACKUP_PATH/$1.$VERSION $BACKUP_PATH/$1.$(($VERSION+1))
|
mv $BACKUP_PATH/$1.$VERSION $BACKUP_PATH/$1.$(($VERSION+1))
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ -w $BACKUP_PATH/$1 ]; then
|
if [ -w $BACKUP_PATH/$1 ]; then
|
||||||
|
@ -120,79 +95,100 @@ backup_list() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# **** start of script ****
|
## 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
|
||||||
|
}
|
||||||
|
|
||||||
log info "Commencing preflight checks."
|
## update pi-hole lists (run updateGravity)
|
||||||
|
update_gravity() {
|
||||||
|
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 ****
|
||||||
|
|
||||||
## preflight checks
|
## preflight checks
|
||||||
if ! amiroot; then
|
if ! amiroot; then
|
||||||
log error "You must be root. Exiting."
|
log error "You must be root"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
log debug "I am root. Continuing."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! amidebian; then
|
|
||||||
log error "I am no debian based system. Exiting."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
log debug "I am debian based. Continuing."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! amipihole; then
|
if ! amipihole; then
|
||||||
log error "I am no pihole. Exiting."
|
log error "I am no pihole"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
log debug "I am a pihole system. Continuing."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for DEPENDENCY in $DEPENDENCIES; do
|
for DEPENDENCY in $DEPENDENCIES; do
|
||||||
if install_package $DEPENDENCY; then
|
if ! $(which $DEPENDENCY); then
|
||||||
log debug "$DEPENDENCY successfully installed. Continuing."
|
log error "$DEPENDENCY is not installed"
|
||||||
else
|
|
||||||
log error "$DEPENDENCY could not be installed. Exiting."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
log success "Preflight checks passed."
|
log success "Preflight checks passed"
|
||||||
|
|
||||||
## generate $BACKUP_PATH and $TEMP_PATH if not available
|
## generate $BACKUP_PATH and $DOWNLOAD_PATH if not available
|
||||||
if [ ! -d $BACKUP_PATH ]; then
|
if ! create_path $DOWNLOAD_PATH; then
|
||||||
log info "$BACKUP_PATH does not exist. Creating."
|
log error "Something went wrong while creating $DOWNLOAD_PATH"
|
||||||
mkdir -p $BACKUP_PATH
|
exit 1
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
log error "Something went wrong while creating $BACKUP_PATH. Exiting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log debug "$BACKUP_PATH exists. Continuing"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -d $TEMP_PATH ]; then
|
if ! create_path $BACKUP_PATH; then
|
||||||
log info "$BACKUP_PATH does not exist. Creating."
|
log error "Something went wrong while creating $BACKUP_PATH"
|
||||||
mkdir -p $TEMP_PATH
|
exit 1
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
log error "Something went wrong while creating $TEMP_PATH. Exiting."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log debug "$TEMP_PATH exists. Continuing."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
## download remote files from MASTER and backup local lists
|
## download remote files from MASTER and backup local lists
|
||||||
CHANGES=0
|
CHANGES=0
|
||||||
for LIST in $LISTS; do
|
for LIST in $LISTS; do
|
||||||
log info "Downloading $LIST."
|
log info "Downloading $LIST."
|
||||||
wget http://$MASTER/synchole/$LIST -q -O $TEMP_PATH/$LIST
|
if ! download_list $LIST; then
|
||||||
if [ $? -ne 0 ]; then
|
log error "Something went wrong while downloading $LIST"
|
||||||
log error "Something went wrong while downloading http://$MASTER/synchole/$LIST. Exiting."
|
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
log success "Successfully downloaded $LIST."
|
log success "Successfully downloaded $LIST."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
diff $TEMP_PATH/$LIST $LISTS_PATH/$LIST
|
#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
|
if [ $? -ne 0 ]; then
|
||||||
log info "Backing up $LIST."
|
log info "Backing up $LIST."
|
||||||
if [ -r $LISTS_PATH/$LIST ]; then
|
if [ -r $LISTS_PATH/$LIST ]; then
|
||||||
|
@ -207,33 +203,28 @@ for LIST in $LISTS; do
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log info "Installing $LIST."
|
log info "Installing $LIST."
|
||||||
cp $TEMP_PATH/$LIST $LISTS_PATH/$LIST
|
if ! install_list $LIST; then
|
||||||
if [ $? -ne 0 ]; then
|
log error "Something went wrong while installing $LIST"
|
||||||
log error "Something went wrong installing updated file to $LIST_PATH/$LIST"
|
|
||||||
else
|
else
|
||||||
log success "Successfully installed updated $LIST."
|
log success "Successfully installed $LIST"
|
||||||
CHANGES=1
|
CHANGES=1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
log warn "No changes in $LIST. Skipping."
|
log debug "No changes in $LIST"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
#run updateGravity
|
## run updateGravity
|
||||||
if [ $CHANGES -eq 1 ]; then
|
if [ $CHANGES -eq 1 ]; then
|
||||||
pihole -g > /dev/null
|
if update_gravity; then
|
||||||
if [ $? -ne 0 ]; then
|
log error "Something went wrong while updating gravity"
|
||||||
log error "Something went wrong while updating Gravity. Exiting."
|
|
||||||
else
|
else
|
||||||
log success "Successfully updated Gravity."
|
log success "Gravity has been successfully updated"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
log warn "No files have been changed. Skipping Gravity update."
|
log debug "No files have been changed, skipping gravity update"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#run restartdns (if hosts.list has been updated)
|
|
||||||
|
|
||||||
log success "Touchdown."
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
# **** end of script ****
|
# **** end of script ****
|
||||||
|
|
Reference in New Issue