This commit is contained in:
Michael Stanclift 2020-10-07 22:02:38 -05:00
commit b7e50324c2
25 changed files with 2063 additions and 2196 deletions

View File

@ -28,17 +28,19 @@ Gravity Sync is not developed by or affiliated with the Pi-hole project. This is
## Setup Steps
1. Read the installation Requirements!
2. Install Gravity Sync to your Pi-hole.
3. Configure your Gravity Sync installation.
4. Test your Gravity Sync install.
5. Automate future synchronizations.
2. Prepare your Pi-hole hosts.
3. Install Gravity Sync to your secondary Pi-hole.
4. Configure your Gravity Sync installation.
5. Test your Gravity Sync install.
6. Automate future synchronizations.
7. Profit.
## Requirements
- Pi-hole 5.0 (or higher) must already be installed on at least two systems, using any of the Linux distribution that Pi-hole is [certified to run on](https://docs.pi-hole.net/main/prerequesites/#supported-operating-systems).
- While it is possible to leverage container/Docker deployments of Pi-hole and Gravity Sync, this configuration is currently not officially supported. Instructions here assume a "native" installation of Pi-hole.
- You will need to make sure that you have `SUDO` enabled for the user accounts on both the primary and secondary Pi-hole. Most of the pre-built images available for the Raspberry Pi already have this configured. During configuration you will be prompted to enable this for your Gravity Sync user.
- Make sure `SSH` and `RSYNC` are installed on both the primary and secondary Pi-hole prior to installation. These two binaries are what does the heavy lifting between your Pi-hole nodes. In the past, Dropbear was supported but this has proven problematic. If you're using a ultra-lightweight Pi distribution (such as DietPi) that uses Dropbear by default, you will need to convert to OpenSSH as of Gravity Sync version 2.2.
- You will need to make sure that you have a Linux user account designated on both Pi-hole systems with `sudo` abilities on both the primary and secondary Pi-hole. Most of the pre-built images available for the Raspberry Pi already have this configured. During configuration you will be prompted to enable this for your Gravity Sync user.
- Make sure OpenSSH `ssh` and `rsync` commands are available on both the primary and secondary Pi-hole prior to installation. These two binaries are what do the heavy lifting between your Pi-hole nodes. If you're using a ultra-lightweight Pi distribution (such as DietPi) that uses Dropbear by default, you will need to convert to OpenSSH.
- You will need to make sure that `SQLite3` is installed on both Pi-hole systems, in order for the backup and restore functions against the databases to completely successfully. This should be covered by the installation of Pi-hole or already installed on most Linux distros.
### Pi-hole Architecture
@ -58,19 +60,13 @@ Starting with version 2.0, Gravity Sync will attempt to sync the Adlist database
Minimal preperation is required (as of version 2.2.3) on your primary Pi-hole.
Login to your *primary* Pi-hole, and install a copy of the software there:
Login to your *primary* Pi-hole, and run the following command:
```bash
git clone https://github.com/vmstan/gravity-sync.git $HOME/gravity-sync
export GS_INSTALL=primary && curl -sSL https://raw.githubusercontent.com/vmstan/gravity-sync/master/prep/gs-install.sh | bash
```
From your home directory, you should run `./gravity-sync/gravity-sync.sh sudo`
**Once this process has completed, you can remove the entire `gravity-sync` directory from the primary Pi-hole.**
```bash
rm $HOME/gravity-sync
```
This will verify you have everything necessary to use Gravity Sync. It will also add a passwordless sudo configuration file for the current user to run commands in `/etc/pihole` -- The installer will then exit, and direct you to proceed to the secondary Pi-hole.
After you have completed this step, log out of the *primary* Pi-hole.
@ -78,13 +74,13 @@ After you have completed this step, log out of the *primary* Pi-hole.
From this point forward, all operations will take place on your secondary Pi-hole.
Login to your *secondary* Pi-hole, and install a copy of the software there:
Login to your *secondary* Pi-hole, and run the following command:
```bash
git clone https://github.com/vmstan/gravity-sync.git $HOME/gravity-sync
export GS_INSTALL=secondary && curl -sSL https://raw.githubusercontent.com/vmstan/gravity-sync/master/prep/gs-install.sh | bash
```
You will now have a folder called `gravity-sync` in your home directory. Everything Gravity Sync runs from there.
This will verify you have everything necessary to use Gravity Sync. The installer will then use Git to make a copy of the Gravity Sync executables in your home directory, and direct you to proceed to Configuration step below. Once this has completed, you will now have a folder called `gravity-sync` in your home directory. Everything Gravity Sync runs from there.
Proceed to the Configuration section.
@ -94,12 +90,12 @@ After you install Gravity Sync to your *secondary Pi-hole* you will need to crea
```bash
cd $HOME/gravity-sync
./gravity-sync.sh config
./gravity-sync.sh configure
```
This will guide you through the process of:
- Specifying the IP or xDNS name of your primary Pi-hole.
- Specifying the IP or DNS name of your primary Pi-hole.
- Specifying the SSH username to connect to your primary Pi-hole.
- Selecting the SSH authentication mechanism (key-pair or password.)
- Configuring your key-pair and applying it to your primary Pi-hole.
@ -185,7 +181,7 @@ Your copy of the `gravity-sync.conf` file, logs and backups should not be be imp
You can run a `./gravity-sync.sh config` at any time to generate a new configuration file if you're concerned that you're missing something.
- If the update script fails, make sure you did your original deployment via `git clone` and not a manual install. Refer to [ADVANCED.md](https://github.com/vmstan/gravity-sync/blob/master/ADVANCED.md) for more details.
- If the update script fails, make sure you did your original deployment via `git clone` and not a manual install. Refer to [ADVANCED.md](https://github.com/vmstan/gravity-sync/blob/master/docs/ADVANCED.md) for more details.
## Starting Over
@ -213,7 +209,7 @@ If you are completely uninstalling Gravity Sync, the last step would be to remov
## Advanced Installation
Please review the [Advanced Installation](https://github.com/vmstan/gravity-sync/blob/master/ADVANCED.md) guide for more assistance.
Please review the [Advanced Installation](https://github.com/vmstan/gravity-sync/blob/master/docs/ADVANCED.md) guide for more assistance.
## Troubleshooting

View File

@ -1 +1 @@
2.2.3
3.0.0

View File

@ -18,8 +18,8 @@ Download the latest release from [GitHub](https://github.com/vmstan/gravity-sync
```bash
cd ~
wget https://github.com/vmstan/gravity-sync/archive/v2.2.3.zip
unzip v2.2.3.zip -d gravity-sync
wget https://github.com/vmstan/gravity-sync/archive/v3.0.0.zip
unzip v3.0.0.zip -d gravity-sync
cd gravity-sync
```

View File

@ -1,5 +1,17 @@
# The Changelog
## 3.0
### The Breakout Release
This release focuses on breaking out elements of the script from the main file into a collection of a dozen or so files located under the `includes/gs-*.sh` hirearchy. Seperating out allows new contributors to work on different parts of the script individually, provides an oppertunity to clean up and reorganize parts of the code, and hopefully provides less risk of breaking the entire script.
This release also features a brand new installation script, including a host check for both the primary and secondary Pi-hole system. This should reduce frustration of users who are missing parts of the system requirements. This will also place a file in the sudoers.d file on both systems to make sure passwordless sudo is configured as part of the installation.
Lastly, we adopts Pi-hole style iconography such as `✓ ✗ e ! ?` instead of `[ GOOD ]` in command output.
Enjoy!
## 2.2
### The Purged Release

File diff suppressed because it is too large Load Diff

114
includes/gs-automate.sh Normal file
View File

@ -0,0 +1,114 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-automate.sh #############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Automate Task
function task_automate {
TASKTYPE='AUTOMATE'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
CRON_EXIST='0'
CRON_CHECK=$(crontab -l | grep -q "${GS_FILENAME}" && echo '1' || echo '0')
if [ ${CRON_CHECK} == 1 ]
then
MESSAGE="Automation Task Already Exists"
echo_info
CRON_EXIST='1'
fi
MESSAGE="Configuring Hourly Smart Sync"
echo_info
if [[ $1 =~ ^[0-9][0-9]?$ ]]
then
INPUT_AUTO_FREQ=$1
else
MESSAGE="Sync Frequency in Minutes (1-30) or 0 to Disable"
echo_need
read INPUT_AUTO_FREQ
fi
if [ $INPUT_AUTO_FREQ -gt 30 ]
then
MESSAGE="Invalid Frequency Range"
echo_fail
exit_nochange
elif [ $INPUT_AUTO_FREQ -lt 1 ]
then
if [ $CRON_EXIST == 1 ]
then
clear_cron
MESSAGE="Sync Automation Disabled"
echo_warn
else
MESSAGE="No Sync Automation Scheduled"
echo_warn
fi
else
if [ $CRON_EXIST == 1 ]
then
clear_cron
fi
MESSAGE="Saving New Sync Automation"
echo_stat
(crontab -l 2>/dev/null; echo "*/${INPUT_AUTO_FREQ} * * * * ${BASH_PATH} $HOME/${LOCAL_FOLDR}/${GS_FILENAME} smart > ${LOG_PATH}/${CRONJOB_LOG}") | crontab -
error_validate
fi
MESSAGE="Configuring Daily Backup Frequency"
echo_info
if [[ $2 =~ ^[0-9][0-9]?$ ]]
then
INPUT_AUTO_BACKUP=$2
else
MESSAGE="Hour of Day to Backup (1-24) or 0 to Disable"
echo_need
read INPUT_AUTO_BACKUP
fi
if [ $INPUT_AUTO_BACKUP -gt 24 ]
then
MESSAGE="Invalid Frequency Range"
echo_fail
exit_nochange
elif [ $INPUT_AUTO_BACKUP -lt 1 ]
then
MESSAGE="No Backup Automation Scheduled"
echo_warn
else
MESSAGE="Saving New Backup Automation"
echo_stat
(crontab -l 2>/dev/null; echo "0 ${INPUT_AUTO_BACKUP} * * * ${BASH_PATH} $HOME/${LOCAL_FOLDR}/${GS_FILENAME} backup >/dev/null 2>&1") | crontab -
error_validate
fi
exit_withchange
}
## Clear Existing Automation Settings
function clear_cron {
MESSAGE="Removing Existing Automation"
echo_stat
crontab -l > cronjob-old.tmp
sed "/${GS_FILENAME}/d" cronjob-old.tmp > cronjob-new.tmp
crontab cronjob-new.tmp 2>/dev/null
error_validate
rm cronjob-old.tmp
rm cronjob-new.tmp
}
## Cron Task
function task_cron {
TASKTYPE='CRON'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
show_crontab
}

75
includes/gs-backup.sh Normal file
View File

@ -0,0 +1,75 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-backup.sh ###############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Backup Task
function task_backup {
TASKTYPE='BACKUP'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
backup_settime
backup_local_gravity
backup_local_custom
backup_cleanup
logs_export
exit_withchange
}
function backup_settime {
BACKUPTIMESTAMP=$(date +%F-%H%M%S)
}
function backup_local_gravity {
MESSAGE="Performing Backup of Local ${GRAVITY_FI}"
echo_stat
sqlite3 ${PIHOLE_DIR}/${GRAVITY_FI} ".backup '$HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${GRAVITY_FI}.backup'"
error_validate
}
function backup_local_custom {
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ -f ${PIHOLE_DIR}/${CUSTOM_DNS} ]
then
MESSAGE="Performing Backup Up Local ${CUSTOM_DNS}"
echo_stat
cp ${PIHOLE_DIR}/${CUSTOM_DNS} $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${CUSTOM_DNS}.backup
error_validate
fi
fi
}
function backup_remote_gravity {
MESSAGE="Performing Backup of Remote ${GRAVITY_FI}"
echo_stat
CMD_TIMEOUT='60'
CMD_REQUESTED="sudo sqlite3 ${PIHOLE_DIR}/${GRAVITY_FI} \".backup '${PIHOLE_DIR}/${GRAVITY_FI}.backup'\""
create_sshcmd
}
function backup_remote_custom {
if [ "$SKIP_CUSTOM" != '1' ]
then
MESSAGE="Performing Backup of Remote ${CUSTOM_DNS}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo cp ${PIHOLE_DIR}/${CUSTOM_DNS} ${PIHOLE_DIR}/${CUSTOM_DNS}.backup"
create_sshcmd
fi
}
function backup_cleanup {
MESSAGE="Cleaning Up Old Backups"
echo_stat
find $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/$(date +%Y)*.backup -mtime +${BACKUP_RETAIN} -type f -delete
error_validate
}

54
includes/gs-colors.sh Normal file
View File

@ -0,0 +1,54 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-colors.sh ###############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Script Colors
RED='\033[0;91m'
GREEN='\033[0;92m'
CYAN='\033[0;96m'
YELLOW='\033[0;93m'
PURPLE='\033[0;95m'
BLUE='\033[0;94m'
BOLD='\033[1m'
NC='\033[0m'
## Message Codes
FAIL="[${RED}${NC}]"
WARN="[${PURPLE}!${NC}]"
GOOD="[${GREEN}${NC}]"
STAT="[${CYAN}e${NC}]"
INFO="[${YELLOW}i${NC}]"
NEED="[${BLUE}?${NC}]"
## Echo Stack
### Informative
function echo_info {
echo -e "${INFO} ${YELLOW}${MESSAGE}${NC}"
}
### Warning
function echo_warn {
echo -e "${WARN} ${PURPLE}${MESSAGE}${NC}"
}
### Executing
function echo_stat {
echo -en "${STAT} ${MESSAGE}"
}
### Success
function echo_good {
echo -e "\r${GOOD} ${MESSAGE}"
}
### Failure
function echo_fail {
echo -e "\r${FAIL} ${MESSAGE}"
}
### Request
function echo_need {
echo -en "${NEED} ${MESSAGE}: "
}

15
includes/gs-compare.sh Normal file
View File

@ -0,0 +1,15 @@
## Compare Task
function task_compare {
TASKTYPE='COMPARE'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
show_target
validate_gs_folders
validate_ph_folders
validate_os_sshpass
previous_md5
md5_compare
exit_withchange
}

View File

@ -20,10 +20,10 @@ function task_configure {
config_generate
fi
# backup_settime
# backup_local_gravity
# backup_local_custom
# backup_cleanup
backup_settime
backup_local_gravity
backup_local_custom
backup_cleanup
exit_withchange
}

48
includes/gs-exit.sh Normal file
View File

@ -0,0 +1,48 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-exit.sh #################################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## No Changes Made
function exit_nochange {
SCRIPT_END=$SECONDS
MESSAGE="${PROGRAM} ${TASKTYPE} Aborting ($((SCRIPT_END-SCRIPT_START)) seconds)"
echo_info
exit 0
}
## Changes Made
function exit_withchange {
SCRIPT_END=$SECONDS
MESSAGE="${PROGRAM} ${TASKTYPE} Completed ($((SCRIPT_END-SCRIPT_START)) seconds)"
echo_info
exit 0
}
## List GS Arguments
function list_gs_arguments {
echo -e "Usage: $0 [options]"
echo -e "Example: '$0 pull'"
echo -e ""
echo -e "Setup Options:"
echo -e " ${YELLOW}config${NC} Create a new ${CONFIG_FILE} file"
echo -e " ${YELLOW}automate${NC} Add a scheduled pull task to crontab"
echo -e " ${YELLOW}update${NC} Update ${PROGRAM} to the latest version"
echo -e " ${YELLOW}version${NC} Display installed version of ${PROGRAM}"
echo -e " ${YELLOW}sudo${NC} Configure passwordless sudo for current user"
echo -e ""
echo -e "Replication Options:"
echo -e " ${YELLOW}smart${NC} Detect changes on each side and bring them together"
echo -e " ${YELLOW}pull${NC} Force remote configuration changes to this server"
echo -e " ${YELLOW}push${NC} Force local configuration made on this server back"
echo -e " ${YELLOW}restore${NC} Restore the ${GRAVITY_FI} on this server"
echo -e " ${YELLOW}backup${NC} Backup the ${GRAVITY_FI} on this server"
echo -e " ${YELLOW}compare${NC} Just check for differences"
echo -e ""
echo -e "Debug Options:"
echo -e " ${YELLOW}logs${NC} Show recent successful replication jobs"
echo -e " ${YELLOW}cron${NC} Display output of last crontab execution"
echo -e ""
exit_nochange
}

148
includes/gs-hashing.sh Normal file
View File

@ -0,0 +1,148 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-hasing.sh ###############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Validate Sync Required
function md5_compare {
HASHMARK='0'
MESSAGE="Analyzing ${GRAVITY_FI} on ${REMOTE_HOST}"
echo_stat
primaryDBMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${PIHOLE_DIR}/${GRAVITY_FI}" | sed 's/\s.*$//')
error_validate
MESSAGE="Analyzing ${GRAVITY_FI} on $HOSTNAME"
echo_stat
secondDBMD5=$(md5sum ${PIHOLE_DIR}/${GRAVITY_FI} | sed 's/\s.*$//')
error_validate
if [ "$primaryDBMD5" == "$last_primaryDBMD5" ] && [ "$secondDBMD5" == "$last_secondDBMD5" ]
then
HASHMARK=$((HASHMARK+0))
else
MESSAGE="Differenced ${GRAVITY_FI} Detected"
echo_warn
HASHMARK=$((HASHMARK+1))
fi
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ -f ${PIHOLE_DIR}/${CUSTOM_DNS} ]
then
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${PIHOLE_DIR}/${CUSTOM_DNS}
then
REMOTE_CUSTOM_DNS="1"
MESSAGE="Analyzing ${CUSTOM_DNS} on ${REMOTE_HOST}"
echo_stat
primaryCLMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${PIHOLE_DIR}/${CUSTOM_DNS} | sed 's/\s.*$//'")
error_validate
MESSAGE="Analyzing ${CUSTOM_DNS} on $HOSTNAME"
echo_stat
secondCLMD5=$(md5sum ${PIHOLE_DIR}/${CUSTOM_DNS} | sed 's/\s.*$//')
error_validate
if [ "$primaryCLMD5" == "$last_primaryCLMD5" ] && [ "$secondCLMD5" == "$last_secondCLMD5" ]
then
HASHMARK=$((HASHMARK+0))
else
MESSAGE="Differenced ${CUSTOM_DNS} Detected"
echo_warn
HASHMARK=$((HASHMARK+1))
fi
else
MESSAGE="No ${CUSTOM_DNS} Detected on ${REMOTE_HOST}"
echo_info
fi
else
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${PIHOLE_DIR}/${CUSTOM_DNS}
then
REMOTE_CUSTOM_DNS="1"
MESSAGE="${REMOTE_HOST} has ${CUSTOM_DNS}"
HASHMARK=$((HASHMARK+1))
echo_info
fi
MESSAGE="No ${CUSTOM_DNS} Detected on $HOSTNAME"
echo_info
fi
fi
if [ "$HASHMARK" != "0" ]
then
MESSAGE="Replication Required"
echo_warn
HASHMARK=$((HASHMARK+0))
else
MESSAGE="No Replication Required"
echo_info
exit_nochange
fi
}
function previous_md5 {
if [ -f "${LOG_PATH}/${HISTORY_MD5}" ]
then
last_primaryDBMD5=$(sed "1q;d" ${LOG_PATH}/${HISTORY_MD5})
last_secondDBMD5=$(sed "2q;d" ${LOG_PATH}/${HISTORY_MD5})
last_primaryCLMD5=$(sed "3q;d" ${LOG_PATH}/${HISTORY_MD5})
last_secondCLMD5=$(sed "4q;d" ${LOG_PATH}/${HISTORY_MD5})
else
last_primaryDBMD5="0"
last_secondDBMD5="0"
last_primaryCLMD5="0"
last_secondCLMD5="0"
fi
}
function md5_recheck {
MESSAGE="Performing Replicator Diagnostics"
echo_info
HASHMARK='0'
MESSAGE="Reanalyzing ${GRAVITY_FI} on ${REMOTE_HOST}"
echo_stat
primaryDBMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${PIHOLE_DIR}/${GRAVITY_FI}" | sed 's/\s.*$//')
error_validate
MESSAGE="Reanalyzing ${GRAVITY_FI} on $HOSTNAME"
echo_stat
secondDBMD5=$(md5sum ${PIHOLE_DIR}/${GRAVITY_FI} | sed 's/\s.*$//')
error_validate
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ -f ${PIHOLE_DIR}/${CUSTOM_DNS} ]
then
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${PIHOLE_DIR}/${CUSTOM_DNS}
then
REMOTE_CUSTOM_DNS="1"
MESSAGE="Reanalyzing ${CUSTOM_DNS} on ${REMOTE_HOST}"
echo_stat
primaryCLMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${PIHOLE_DIR}/${CUSTOM_DNS} | sed 's/\s.*$//'")
error_validate
MESSAGE="Reanalyzing ${CUSTOM_DNS} on $HOSTNAME"
echo_stat
secondCLMD5=$(md5sum ${PIHOLE_DIR}/${CUSTOM_DNS} | sed 's/\s.*$//')
error_validate
else
MESSAGE="No ${CUSTOM_DNS} Detected on ${REMOTE_HOST}"
echo_info
fi
else
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${PIHOLE_DIR}/${CUSTOM_DNS}
then
REMOTE_CUSTOM_DNS="1"
MESSAGE="${REMOTE_HOST} has ${CUSTOM_DNS}"
echo_info
fi
MESSAGE="No ${CUSTOM_DNS} Detected on $HOSTNAME"
echo_info
fi
fi
}

41
includes/gs-intent.sh Normal file
View File

@ -0,0 +1,41 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-intent.sh ###############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Validate Intent
function intent_validate {
if [ "$VERIFY_PASS" == "0" ]
then
PHASER=$((( RANDOM % 4 ) + 1 ))
if [ "$PHASER" = "1" ]
then
INTENT="FIRE PHOTON TORPEDOS"
elif [ "$PHASER" = "2" ]
then
INTENT="FIRE ALL PHASERS"
elif [ "$PHASER" = "3" ]
then
INTENT="EJECT THE WARPCORE"
elif [ "$PHASER" = "4" ]
then
INTENT="ENGAGE TRACTOR BEAM"
fi
MESSAGE="Type ${INTENT} to Confirm"
echo_need
read INPUT_INTENT
if [ "${INPUT_INTENT}" != "${INTENT}" ]
then
MESSAGE="${TASKTYPE} Aborted"
echo_info
exit_nochange
fi
else
MESSAGE="Verification Bypassed"
echo_warn
fi
}

94
includes/gs-logging.sh Normal file
View File

@ -0,0 +1,94 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-logging.sh ##############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Logs Task
function task_logs {
TASKTYPE='LOGS'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
logs_gs
}
## Core Logging
### Write Logs Out
function logs_export {
if [ "${TASKTYPE}" != "BACKUP" ]
then
MESSAGE="Saving File Hashes"
echo_stat
rm -f ${LOG_PATH}/${HISTORY_MD5}
echo -e ${primaryDBMD5} >> ${LOG_PATH}/${HISTORY_MD5}
echo -e ${secondDBMD5} >> ${LOG_PATH}/${HISTORY_MD5}
echo -e ${primaryCLMD5} >> ${LOG_PATH}/${HISTORY_MD5}
echo -e ${secondCLMD5} >> ${LOG_PATH}/${HISTORY_MD5}
error_validate
fi
MESSAGE="Logging Successful ${TASKTYPE}"
echo_stat
echo -e $(date) "[${TASKTYPE}]" >> ${LOG_PATH}/${SYNCING_LOG}
error_validate
}
### Output Sync Logs
function logs_gs {
MESSAGE="Tailing ${LOG_PATH}/${SYNCING_LOG}"
echo_info
echo -e "========================================================"
echo -e "Recent Complete ${YELLOW}SMART${NC} Executions"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep SMART
echo -e "Recent Complete ${YELLOW}PULL${NC} Executions"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep PULL
echo -e "Recent Complete ${YELLOW}PUSH${NC} Executions"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep PUSH
echo -e "Recent Complete ${YELLOW}BACKUP${NC} Executions"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep BACKUP
echo -e "Recent Complete ${YELLOW}RESTORE${NC} Executions"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep RESTORE
echo -e "========================================================"
exit_nochange
}
## Crontab Logs
### Core Crontab Logs
function show_crontab {
MESSAGE="Replaying Last Cronjob"
echo_stat
if [ -f ${LOG_PATH}/${CRONJOB_LOG} ]
then
if [ -s ${LOG_PATH}/${CRONJOB_LOG} ]
echo_good
MESSAGE="Tailing ${LOG_PATH}/${CRONJOB_LOG}"
echo_info
echo -e "========================================================"
date -r ${LOG_PATH}/${CRONJOB_LOG}
cat ${LOG_PATH}/${CRONJOB_LOG}
echo -e "========================================================"
exit_nochange
then
echo_fail
MESSAGE="${LOG_PATH}/${CRONJOB_LOG} is Empty"
echo_info
exit_nochange
fi
else
echo_fail
MESSAGE="${LOG_PATH}/${CRONJOB_LOG} is Missing"
echo_info
exit_nochange
fi
}

178
includes/gs-pull.sh Normal file
View File

@ -0,0 +1,178 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-pull.sh #################################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Pull Task
function task_pull {
TASKTYPE='PULL'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
show_target
validate_gs_folders
validate_ph_folders
validate_sqlite3
validate_os_sshpass
pull_gs
exit
}
## Pull Gravity
function pull_gs_grav {
backup_local_gravity
backup_remote_gravity
MESSAGE="Pulling ${GRAVITY_FI} from ${REMOTE_HOST}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${PIHOLE_DIR}/${GRAVITY_FI}.backup"
RSYNC_TARGET="$HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${GRAVITY_FI}.pull"
create_rsynccmd
MESSAGE="Replacing ${GRAVITY_FI} on $HOSTNAME"
echo_stat
sudo cp $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${GRAVITY_FI}.pull ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
MESSAGE="Validating Settings of ${GRAVITY_FI}"
echo_stat
GRAVDB_OWN=$(ls -ld ${PIHOLE_DIR}/${GRAVITY_FI} | awk 'OFS=":" {print $3,$4}')
if [ "$GRAVDB_OWN" != "$FILE_OWNER" ]
then
MESSAGE="Validating Ownership on ${GRAVITY_FI}"
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Setting Ownership on ${GRAVITY_FI}"
echo_stat
sudo chown ${FILE_OWNER} ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
MESSAGE="Continuing Validation of ${GRAVITY_FI}"
echo_stat
fi
GRAVDB_RWE=$(namei -m ${PIHOLE_DIR}/${GRAVITY_FI} | grep -v f: | grep ${GRAVITY_FI} | awk '{print $1}')
if [ "$GRAVDB_RWE" != "-rw-rw-r--" ]
then
MESSAGE="Validating Permissions on ${GRAVITY_FI}"
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Setting Permissions on ${GRAVITY_FI}"
echo_stat
sudo chmod 664 ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
MESSAGE="Continuing Validation of ${GRAVITY_FI}"
echo_stat
fi
echo_good
}
## Pull Custom
function pull_gs_cust {
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ "$REMOTE_CUSTOM_DNS" == "1" ]
then
backup_local_custom
backup_remote_custom
MESSAGE="Pulling ${CUSTOM_DNS} from ${REMOTE_HOST}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${PIHOLE_DIR}/${CUSTOM_DNS}.backup"
RSYNC_TARGET="$HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${CUSTOM_DNS}.pull"
create_rsynccmd
MESSAGE="Replacing ${CUSTOM_DNS} on $HOSTNAME"
echo_stat
sudo cp $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${CUSTOM_DNS}.pull ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
MESSAGE="Validating Settings on ${CUSTOM_DNS}"
echo_stat
CUSTOMLS_OWN=$(ls -ld ${PIHOLE_DIR}/${CUSTOM_DNS} | awk '{print $3 $4}')
if [ "$CUSTOMLS_OWN" != "rootroot" ]
then
MESSAGE="Validating Ownership on ${CUSTOM_DNS}"
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Setting Ownership on ${CUSTOM_DNS}"
echo_stat
sudo chown root:root ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
MESSAGE="Continuing Validation of ${GRAVITY_FI}"
echo_stat
fi
CUSTOMLS_RWE=$(namei -m ${PIHOLE_DIR}/${CUSTOM_DNS} | grep -v f: | grep ${CUSTOM_DNS} | awk '{print $1}')
if [ "$CUSTOMLS_RWE" != "-rw-r--r--" ]
then
MESSAGE="Validating Permissions on ${CUSTOM_DNS}"
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Setting Ownership on ${CUSTOM_DNS}"
echo_stat
sudo chmod 644 ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
MESSAGE="Continuing Validation of ${GRAVITY_FI}"
echo_stat
fi
echo_good
fi
fi
}
## Pull Reload
function pull_gs_reload {
MESSAGE="Isolating Regeneration Pathways"
echo_info
sleep 1
MESSAGE="Updating FTLDNS Configuration"
echo_stat
${PIHOLE_BIN} restartdns reloadlists >/dev/null 2>&1
error_validate
MESSAGE="Reloading FTLDNS Services"
echo_stat
${PIHOLE_BIN} restartdns >/dev/null 2>&1
error_validate
}
## Pull Function
function pull_gs {
previous_md5
md5_compare
backup_settime
pull_gs_grav
pull_gs_cust
pull_gs_reload
md5_recheck
logs_export
exit_withchange
}

78
includes/gs-purge.sh Normal file
View File

@ -0,0 +1,78 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-purge.sh ################################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Purge Task
function task_purge {
TASKTYPE="THE-PURGE"
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
MESSAGE="THIS WILL RESET YOUR ENTIRE GRAVITY SYNC INSTALLATION"
echo_warn
MESSAGE="This will remove:"
echo_warn
MESSAGE="- All backups files."
echo_warn
MESSAGE="- Your ${CONFIG_FILE} file."
echo_warn
if [ -f "$HOME/${LOCAL_FOLDR}/dev" ]
then
MESSAGE="- Your development branch updater."
elif [ -f "$HOME/${LOCAL_FOLDR}/beta" ]
then
MESSAGE="- Your beta branch updater."
fi
echo_warn
MESSAGE="- All cronjob/automation tasks."
echo_warn
MESSAGE="- All job history/logs."
echo_warn
MESSAGE="- Associated SSH id_rsa keys."
echo_warn
MESSAGE="This function cannot be undone!"
echo_warn
MESSAGE="YOU WILL NEED TO REBUILD GRAVITY SYNC AFTER EXECUTION"
echo_warn
MESSAGE="Pi-hole binaries, configuration and services ARE NOT impacted!"
echo_info
MESSAGE="Your device will continue to resolve and block DNS requests,"
echo_info
MESSAGE="but your ${GRAVITY_FI} and ${CUSTOM_DNS} WILL NOT sync anymore,"
echo_info
MESSAGE="until you reconfigure Gravity Sync on this device."
echo_info
intent_validate
MESSAGE="Cleaning Gravity Sync Directory"
echo_stat
git clean -f -X -d >/dev/null 2>&1
error_validate
clear_cron
MESSAGE="Deleting SSH Key-files"
echo_stat
rm -f $HOME/${SSH_PKIF} >/dev/null 2>&1
rm -f $HOME/${SSH_PKIF}.pub >/dev/null 2>&1
error_validate
MESSAGE="Realigning Dilithium Matrix"
echo_stat
sleep 1
MESSAGE="Realigning Dilithium Matrix"
echo_good
update_gs
}

127
includes/gs-push.sh Normal file
View File

@ -0,0 +1,127 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-push.sh #################################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Push Task
function task_push {
TASKTYPE='PUSH'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
show_target
validate_gs_folders
validate_ph_folders
validate_sqlite3
validate_os_sshpass
push_gs
exit
}
## Push Gravity
function push_gs_grav {
backup_remote_gravity
backup_local_gravity
MESSAGE="Copying ${GRAVITY_FI} from ${REMOTE_HOST}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${PIHOLE_DIR}/${GRAVITY_FI}.backup"
RSYNC_TARGET="$HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${GRAVITY_FI}.push"
create_rsynccmd
MESSAGE="Pushing ${GRAVITY_FI} to ${REMOTE_HOST}"
echo_stat
RSYNC_REPATH="sudo rsync"
RSYNC_SOURCE="$HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${GRAVITY_FI}.backup"
RSYNC_TARGET="${REMOTE_USER}@${REMOTE_HOST}:${PIHOLE_DIR}/${GRAVITY_FI}"
create_rsynccmd
MESSAGE="Setting Permissions on ${GRAVITY_FI}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chmod 664 ${PIHOLE_DIR}/${GRAVITY_FI}"
create_sshcmd
MESSAGE="Setting Ownership on ${GRAVITY_FI}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chown ${RFILE_OWNER} ${PIHOLE_DIR}/${GRAVITY_FI}"
create_sshcmd
}
## Push Custom
function push_gs_cust {
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ "$REMOTE_CUSTOM_DNS" == "1" ]
then
backup_remote_custom
backup_local_custom
MESSAGE="Copying ${CUSTOM_DNS} from ${REMOTE_HOST}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${PIHOLE_DIR}/${CUSTOM_DNS}.backup"
RSYNC_TARGET="$HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${CUSTOM_DNS}.push"
create_rsynccmd
MESSAGE="Pushing ${CUSTOM_DNS} to ${REMOTE_HOST}"
echo_stat
RSYNC_REPATH="sudo rsync"
RSYNC_SOURCE="$HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${CUSTOM_DNS}.backup"
RSYNC_TARGET="${REMOTE_USER}@${REMOTE_HOST}:${PIHOLE_DIR}/${CUSTOM_DNS}"
create_rsynccmd
MESSAGE="Setting Permissions on ${CUSTOM_DNS}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chmod 644 ${PIHOLE_DIR}/${CUSTOM_DNS}"
create_sshcmd
MESSAGE="Setting Ownership on ${CUSTOM_DNS}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chown root:root ${PIHOLE_DIR}/${CUSTOM_DNS}"
create_sshcmd
fi
fi
}
## Push Reload
function push_gs_reload {
MESSAGE="Inverting Tachyon Pulses"
echo_info
sleep 1
MESSAGE="Updating Remote FTLDNS Configuration"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="${RIHOLE_BIN} restartdns reloadlists"
create_sshcmd
MESSAGE="Reloading Remote FTLDNS Services"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="${RIHOLE_BIN} restartdns"
create_sshcmd
}
## Push Function
function push_gs {
previous_md5
md5_compare
backup_settime
intent_validate
push_gs_grav
push_gs_cust
push_gs_reload
md5_recheck
logs_export
exit_withchange
}

209
includes/gs-restore.sh Normal file
View File

@ -0,0 +1,209 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-restore.sh ##############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Restore Task
function task_restore {
TASKTYPE='RESTORE'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
show_target
validate_gs_folders
validate_ph_folders
validate_sqlite3
restore_gs
exit
}
## Restore Gravity
function restore_gs {
MESSAGE="This will restore your settings on $HOSTNAME with a previous version!"
echo_warn
MESSAGE="PREVIOUS BACKUPS AVAILABLE FOR RESTORATION"
echo_info
ls $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD} | grep $(date +%Y) | grep ${GRAVITY_FI} | colrm 18
MESSAGE="Select backup date to restore ${GRAVITY_FI} from"
echo_need
read INPUT_BACKUP_DATE
if [ -f $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_BACKUP_DATE}-${GRAVITY_FI}.backup ]
then
MESSAGE="Backup File Selected"
else
MESSAGE="Invalid Request"
echo_info
exit_nochange
fi
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ -f ${PIHOLE_DIR}/${CUSTOM_DNS} ]
then
ls $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD} | grep $(date +%Y) | grep ${CUSTOM_DNS} | colrm 18
MESSAGE="Select backup date to restore ${CUSTOM_DNS} from"
echo_need
read INPUT_DNSBACKUP_DATE
if [ -f $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_DNSBACKUP_DATE}-${CUSTOM_DNS}.backup ]
then
MESSAGE="Backup File Selected"
else
MESSAGE="Invalid Request"
echo_info
exit_nochange
fi
fi
fi
MESSAGE="${GRAVITY_FI} from ${INPUT_BACKUP_DATE} Selected"
echo_info
MESSAGE="${CUSTOM_DNS} from ${INPUT_DNSBACKUP_DATE} Selected"
echo_info
intent_validate
MESSAGE="Making Time Warp Calculations"
echo_info
MESSAGE="Stopping Pi-hole Services"
echo_stat
sudo service pihole-FTL stop >/dev/null 2>&1
error_validate
MESSAGE="Restoring ${GRAVITY_FI} on $HOSTNAME"
echo_stat
sudo cp $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_BACKUP_DATE}-${GRAVITY_FI}.backup ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
MESSAGE="Validating Ownership on ${GRAVITY_FI}"
echo_stat
GRAVDB_OWN=$(ls -ld ${PIHOLE_DIR}/${GRAVITY_FI} | awk 'OFS=":" {print $3,$4}')
if [ "$GRAVDB_OWN" == "$FILE_OWNER" ]
then
echo_good
else
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Setting Ownership on ${GRAVITY_FI}"
echo_stat
sudo chown ${FILE_OWNER} ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
fi
MESSAGE="Validating Permissions on ${GRAVITY_FI}"
echo_stat
GRAVDB_RWE=$(namei -m ${PIHOLE_DIR}/${GRAVITY_FI} | grep -v f: | grep ${GRAVITY_FI} | awk '{print $1}')
if [ "$GRAVDB_RWE" = "-rw-rw-r--" ]
then
echo_good
else
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Setting Ownership on ${GRAVITY_FI}"
echo_stat
sudo chmod 664 ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
fi
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ -f $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_DNSBACKUP_DATE}-${CUSTOM_DNS}.backup ]
then
MESSAGE="Restoring ${CUSTOM_DNS} on $HOSTNAME"
echo_stat
sudo cp $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_DNSBACKUP_DATE}-${CUSTOM_DNS}.backup ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
MESSAGE="Validating Ownership on ${CUSTOM_DNS}"
echo_stat
CUSTOMLS_OWN=$(ls -ld ${PIHOLE_DIR}/${CUSTOM_DNS} | awk '{print $3 $4}')
if [ "$CUSTOMLS_OWN" == "rootroot" ]
then
echo_good
else
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Setting Ownership on ${CUSTOM_DNS}"
echo_stat
sudo chown root:root ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
fi
MESSAGE="Validating Permissions on ${CUSTOM_DNS}"
echo_stat
CUSTOMLS_RWE=$(namei -m ${PIHOLE_DIR}/${CUSTOM_DNS} | grep -v f: | grep ${CUSTOM_DNS} | awk '{print $1}')
if [ "$CUSTOMLS_RWE" == "-rw-r--r--" ]
then
echo_good
else
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Setting Ownership on ${CUSTOM_DNS}"
echo_stat
sudo chmod 644 ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
fi
fi
fi
MESSAGE="Evacuating Saucer Section"
echo_info
sleep 1
MESSAGE="Restarting FTLDNS Services"
echo_stat
sudo service pihole-FTL start >/dev/null 2>&1
error_validate
MESSAGE="Updating FTLDNS Configuration"
echo_stat
${PIHOLE_BIN} restartdns reloadlists >/dev/null 2>&1
error_validate
MESSAGE="Do you want to push the restored configuration to the primary Pi-hole? (yes/no)"
echo_need
read PUSH_TO_PRIMARY
if [ "${PUSH_TO_PRIMARY}" == "Yes" ] || [ "${PUSH_TO_PRIMARY}" == "yes" ] || [ "${PUSH_TO_PRIMARY}" == "Y" ] || [ "${PUSH_TO_PRIMARY}" == "y" ]
then
push_gs
elif [ "${PUSH_TO_PRIMARY}" == "No" ] || [ "${PUSH_TO_PRIMARY}" == "no" ] || [ "${PUSH_TO_PRIMARY}" == "N" ] || [ "${PUSH_TO_PRIMARY}" == "n" ]
then
logs_export
exit_withchange
else
MESSAGE="Invalid Selection - Defaulting No"
echo_warn
logs_export
exit_withchange
fi
}

40
includes/gs-root.sh Normal file
View File

@ -0,0 +1,40 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-root.sh #################################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Sudo Creation Task
function task_sudo {
TASKTYPE='SUDO'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
MESSAGE="Creating Sudoer.d Template"
echo_stat
NEW_SUDO_USER=$(whoami)
echo -e "${NEW_SUDO_USER} ALL=(ALL) NOPASSWD: ${PIHOLE_DIR}" > $HOME/${LOCAL_FOLDR}/templates/gs-nopasswd.sudo
error_validate
MESSAGE="Installing Sudoer.d File"
echo_stat
sudo install -m 0440 $HOME/${LOCAL_FOLDR}/templates/gs-nopasswd.sudo /etc/sudoers.d/gs-nopasswd
error_validate
}
## Root Check
function root_check {
if [ ! "$EUID" -ne 0 ]
then
TASKTYPE='ROOT'
MESSAGE="${MESSAGE} ${TASKTYPE}"
echo_fail
MESSAGE="${PROGRAM} Must Not Run as Root"
echo_warn
exit_nochange
fi
}

153
includes/gs-smart.sh Normal file
View File

@ -0,0 +1,153 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-smart.sh ################################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Smart Task
function task_smart {
TASKTYPE='SMART'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
show_target
validate_gs_folders
validate_ph_folders
validate_sqlite3
validate_os_sshpass
smart_gs
exit
}
## Smart Sync Function
function smart_gs {
previous_md5
md5_compare
backup_settime
PRIDBCHANGE="0"
SECDBCHANGE="0"
PRICLCHANGE="0"
SECCLCHANGE="0"
if [ "${primaryDBMD5}" != "${last_primaryDBMD5}" ]
then
PRIDBCHANGE="1"
fi
if [ "${secondDBMD5}" != "${last_secondDBMD5}" ]
then
SECDBCHANGE="1"
fi
if [ "${PRIDBCHANGE}" == "${SECDBCHANGE}" ]
then
if [ "${PRIDBCHANGE}" != "0" ]
then
MESSAGE="Both ${GRAVITY_FI} Changed"
echo_warn
PRIDBDATE=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "stat -c %Y ${PIHOLE_DIR}/${GRAVITY_FI}")
SECDBDATE=$(stat -c %Y ${PIHOLE_DIR}/${GRAVITY_FI})
if [ "${PRIDBDATE}" -gt "$SECDBDATE" ]
then
MESSAGE="Primary ${GRAVITY_FI} Last Changed"
echo_info
pull_gs_grav
PULLRESTART="1"
else
MESSAGE="Secondary ${GRAVITY_FI} Last Changed"
echo_info
push_gs_grav
PUSHRESTART="1"
fi
fi
else
if [ "${PRIDBCHANGE}" != "0" ]
then
pull_gs_grav
PULLRESTART="1"
elif [ "${SECDBCHANGE}" != "0" ]
then
push_gs_grav
PUSHRESTART="1"
fi
fi
if [ "${primaryCLMD5}" != "${last_primaryCLMD5}" ]
then
PRICLCHANGE="1"
fi
if [ "${secondCLMD5}" != "${last_secondCLMD5}" ]
then
SECCLCHANGE="1"
fi
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ -f "${PIHOLE_DIR}/${CUSTOM_DNS}" ]
then
if [ "${PRICLCHANGE}" == "${SECCLCHANGE}" ]
then
if [ "${PRICLCHANGE}" != "0" ]
then
MESSAGE="Both ${CUSTOM_DNS} Changed"
echo_warn
PRICLDATE=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "stat -c %Y ${PIHOLE_DIR}/${CUSTOM_DNS}")
SECCLDATE=$(stat -c %Y ${PIHOLE_DIR}/${CUSTOM_DNS})
if [ "${PRICLDATE}" -gt "${SECCLDATE}" ]
then
MESSAGE="Primary ${CUSTOM_DNS} Last Changed"
echo_info
pull_gs_cust
PULLRESTART="1"
else
MESSAGE="Secondary ${CUSTOM_DNS} Last Changed"
echo_info
push_gs_cust
PUSHRESTART="1"
fi
fi
else
if [ "${PRICLCHANGE}" != "0" ]
then
pull_gs_cust
PULLRESTART="1"
elif [ "${SECCLCHANGE}" != "0" ]
then
push_gs_cust
PUSHRESTART="1"
fi
fi
else
pull_gs_cust
PULLRESTART="1"
fi
fi
if [ "$PULLRESTART" == "1" ]
then
pull_gs_reload
fi
if [ "$PUSHRESTART" == "1" ]
then
push_gs_reload
fi
md5_recheck
logs_export
exit_withchange
}

185
includes/gs-ssh.sh Normal file
View File

@ -0,0 +1,185 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-ssh.sh ##################################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Determine SSH Pathways
function create_sshcmd {
if hash ssh 2>/dev/null
then
if [ -z "$SSHPASSWORD" ]
then
timeout --preserve-status ${CMD_TIMEOUT} ${SSH_CMD} -p ${SSH_PORT} -i $HOME/${SSH_PKIF} -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST} "${CMD_REQUESTED}"
error_validate
else
timeout --preserve-status ${CMD_TIMEOUT} ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST} "${CMD_REQUESTED}"
error_validate
fi
fi
}
## Determine SSH Pathways
function create_rsynccmd {
if hash ssh 2>/dev/null
then
if [ -z "$SSHPASSWORD" ]
then
rsync --rsync-path="${RSYNC_REPATH}" -e "${SSH_CMD} -p ${SSH_PORT} -i $HOME/${SSH_PKIF}" ${RSYNC_SOURCE} ${RSYNC_TARGET} >/dev/null 2>&1
error_validate
else
rsync --rsync-path="${RSYNC_REPATH}" -e "${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i $HOME/${SSH_PKIF}" ${RSYNC_SOURCE} ${RSYNC_TARGET} >/dev/null 2>&1
error_validate
fi
fi
}
## Detect SSH-KEYGEN
function detect_sshkeygen {
MESSAGE="Validating SSH-KEYGEN install on $HOSTNAME"
echo_stat
if hash ssh-keygen >/dev/null 2>&1
then
echo_good
else
echo_fail
MESSAGE="SSH-KEYGEN is Required"
echo_info
exit_nochange
fi
}
function generate_sshkey {
if [ -z $INPUT_REMOTE_PASS ]
then
if [ -f $HOME/${SSH_PKIF} ]
then
MESSAGE="Using Existing ~/${SSH_PKIF}"
echo_info
else
if hash ssh-keygen >/dev/null 2>&1
then
MESSAGE="Generating ~/${SSH_PKIF} (SSH-KEYGEN)"
echo_stat
ssh-keygen -q -P "" -t rsa -f $HOME/${SSH_PKIF} >/dev/null 2>&1
error_validate
else
MESSAGE="No SSH Key Generator Located"
echo_warn
exit_nochange
fi
fi
fi
}
function export_sshkey {
if [ -z $REMOTE_PASS ]
then
if [ -f $HOME/${SSH_PKIF} ]
then
MESSAGE="Registering Key-Pair on ${REMOTE_HOST}"
echo_info
ssh-copy-id -f -p ${SSH_PORT} -i $HOME/${SSH_PKIF}.pub ${REMOTE_USER}@${REMOTE_HOST}
else
MESSAGE="Error Registering Key-Pair"
echo_warn
fi
fi
}
## Detect SSH & RSYNC
function detect_ssh {
MESSAGE="Validating SSH Client on $HOSTNAME"
echo_stat
if hash ssh 2>/dev/null
then
MESSAGE="${MESSAGE} (OpenSSH)"
echo_good
SSH_CMD='ssh'
elif hash dbclient 2>/dev/null
then
MESSAGE="${MESSAGE} (Dropbear)"
echo_fail
MESSAGE="Dropbear not supported in GS ${VERSION}"
echo_info
exit_nochange
else
echo_fail
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Installing SSH Client with ${PKG_MANAGER}"
echo_stat
${PKG_INSTALL} ssh-client >/dev/null 2>&1
error_validate
fi
MESSAGE="Validating RSYNC Installed on $HOSTNAME"
echo_stat
if hash rsync 2>/dev/null
then
echo_good
else
echo_fail
MESSAGE="RSYNC is Required"
echo_warn
distro_check
MESSAGE="Attempting to Compensate"
echo_warn
MESSAGE="Installing RSYNC with ${PKG_MANAGER}"
echo_stat
${PKG_INSTALL} rsync >/dev/null 2>&1
error_validate
fi
}
function detect_remotersync {
MESSAGE="Creating Test File on ${REMOTE_HOST}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="touch ~/gs.test"
create_sshcmd
MESSAGE="If pull test fails ensure RSYNC is installed on ${REMOTE_HOST}"
echo_warn
MESSAGE="Pulling Test File to $HOSTNAME"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:~/gs.test"
RSYNC_TARGET="$HOME/${LOCAL_FOLDR}/gs.test"
create_rsynccmd
MESSAGE="Cleaning Up Local Test File"
echo_stat
rm $HOME/${LOCAL_FOLDR}/gs.test
error_validate
MESSAGE="Cleaning Up Remote Test File"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="rm ~/gs.test"
create_sshcmd
}
function show_target {
MESSAGE="Targeting ${REMOTE_USER}@${REMOTE_HOST}"
echo_info
detect_ssh
}

143
includes/gs-update.sh Normal file
View File

@ -0,0 +1,143 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-update.sh ###############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Master Branch
function update_gs {
if [ -f "$HOME/${LOCAL_FOLDR}/dev" ]
then
source $HOME/${LOCAL_FOLDR}/dev
else
BRANCH='origin/master'
fi
if [ "$BRANCH" != "origin/master" ]
then
MESSAGE="Pulling from ${BRANCH}"
echo_info
fi
GIT_CHECK=$(git status | awk '{print $1}')
if [ "$GIT_CHECK" == "fatal:" ]
then
MESSAGE="Requires GitHub Installation"
echo_warn
exit_nochange
else
MESSAGE="Updating Cache"
echo_stat
git fetch --all >/dev/null 2>&1
error_validate
MESSAGE="Applying Update"
echo_stat
git reset --hard ${BRANCH} >/dev/null 2>&1
error_validate
fi
}
## Show Version
function show_version {
echo -e "========================================================"
MESSAGE="${BOLD}${PROGRAM}${NC} by ${CYAN}@vmstan${NC}"
echo_info
MESSAGE="${BLUE}https://github.com/vmstan/gravity-sync${NC}"
echo_info
if [ -f $HOME/${LOCAL_FOLDR}/dev ]
then
DEVVERSION="dev"
elif [ -f $HOME/${LOCAL_FOLDR}/beta ]
then
DEVVERSION="beta"
else
DEVVERSION=""
fi
MESSAGE="Running Version: ${GREEN}${VERSION}${NC} ${DEVVERSION}"
echo_info
GITVERSION=$(curl -sf https://raw.githubusercontent.com/vmstan/gravity-sync/master/VERSION)
if [ -z "$GITVERSION" ]
then
MESSAGE="Latest Version: ${RED}Unknown${NC}"
else
if [ "$GITVERSION" != "$VERSION" ]
then
MESSAGE="Update Available: ${PURPLE}${GITVERSION}${NC}"
else
MESSAGE="Latest Version: ${GREEN}${GITVERSION}${NC}"
fi
fi
echo_info
echo -e "========================================================"
}
## Devmode Task
function task_devmode {
TASKTYPE='DEV'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
if [ -f $HOME/${LOCAL_FOLDR}/dev ]
then
MESSAGE="Disabling ${TASKTYPE}"
echo_stat
rm -f $HOME/${LOCAL_FOLDR}/dev
error_validate
elif [ -f $HOME/${LOCAL_FOLDR}/beta ]
then
MESSAGE="Disabling BETA"
echo_stat
rm -f $HOME/${LOCAL_FOLDR}/beta
error_validate
MESSAGE="Enabling ${TASKTYPE}"
echo_stat
touch $HOME/${LOCAL_FOLDR}/dev
error_validate
else
MESSAGE="Enabling ${TASKTYPE}"
echo_stat
touch $HOME/${LOCAL_FOLDR}/dev
error_validate
git branch -r
MESSAGE="Select Branch to Update Against"
echo_need
read INPUT_BRANCH
echo -e "BRANCH='${INPUT_BRANCH}'" >> $HOME/${LOCAL_FOLDR}/dev
fi
MESSAGE="Run UPDATE to apply changes"
echo_info
exit_withchange
}
## Update Task
function task_update {
TASKTYPE='UPDATE'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
dbclient_warning
update_gs
exit_withchange
}
## Version Task
function task_version {
TASKTYPE='VERSION'
MESSAGE="${MESSAGE}: ${TASKTYPE} Requested"
echo_good
show_version
exit_nochange
}

148
includes/gs-validate.sh Normal file
View File

@ -0,0 +1,148 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-validate.sh #############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code is called from the main gravity-sync.sh file and should not execute directly!
## Validate GS Folders
function validate_gs_folders {
MESSAGE="Validating ${PROGRAM} Folders on $HOSTNAME"
echo_stat
if [ ! -d $HOME/${LOCAL_FOLDR} ]
then
MESSAGE="Unable to Find $HOME/${LOCAL_FOLDR}"
echo_fail
exit_nochange
fi
if [ ! -d $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD} ]
then
MESSAGE="Unable to Find $HOME/${LOCAL_FOLDR}/${BACKUP_FOLD}"
echo_fail
exit_nochange
fi
echo_good
}
## Validate Pi-hole Folders
function validate_ph_folders {
MESSAGE="Validating Pi-hole Configuration on $HOSTNAME"
echo_stat
if [ ! -f ${PIHOLE_BIN} ]
then
MESSAGE="Unable to Validate Pi-Hole is Installed"
echo_fail
exit_nochange
fi
if [ ! -d ${PIHOLE_DIR} ]
then
MESSAGE="Unable to Validate Pi-Hole Configuration Directory"
echo_fail
exit_nochange
fi
echo_good
}
## Validate SQLite3
function validate_sqlite3 {
MESSAGE="Validating SQLITE Installed on $HOSTNAME"
echo_stat
if hash sqlite3 2>/dev/null
then
MESSAGE="SQLITE3 Utility Detected"
echo_good
else
MESSAGE="SQLITE3 Utility Missing"
echo_warn
MESSAGE="Installing SQLLITE3 with ${PKG_MANAGER}"
echo_stat
${PKG_INSTALL} sqllite3 >/dev/null 2>&1
error_validate
fi
}
## Validate SSHPASS
function validate_os_sshpass {
SSHPASSWORD=''
if hash sshpass 2>/dev/null
then
MESSAGE="SSHPASS Utility Detected"
echo_warn
if [ -z "$REMOTE_PASS" ]
then
MESSAGE="Using SSH Key-Pair Authentication"
echo_info
else
MESSAGE="Testing Authentication Options"
echo_stat
timeout 5 ssh -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST} 'exit' >/dev/null 2>&1
if [ "$?" != "0" ]
then
SSHPASSWORD="sshpass -p ${REMOTE_PASS}"
MESSAGE="Using SSH Password Authentication"
echo_warn
else
MESSAGE="Valid Key-Pair Detected ${NC}(${RED}Password Ignored${NC})"
echo_info
fi
fi
else
SSHPASSWORD=''
MESSAGE="Using SSH Key-Pair Authentication"
echo_info
fi
MESSAGE="Validating Connection to ${REMOTE_HOST}"
echo_stat
CMD_TIMEOUT='5'
CMD_REQUESTED="exit"
create_sshcmd
}
## Detect Package Manager
function distro_check {
if hash apt-get 2>/dev/null
then
PKG_MANAGER="apt-get"
PKG_INSTALL="sudo apt-get --yes --no-install-recommends --quiet install"
elif hash rpm 2>/dev/null
then
if hash dnf 2>/dev/null
then
PKG_MANAGER="dnf"
elif hash yum 2>/dev/null
then
PKG_MANAGER="yum"
else
MESSAGE="Unable to find OS Package Manager"
echo_info
exit_nochange
fi
PKG_INSTALL="sudo ${PKG_MANAGER} install -y"
else
MESSAGE="Unable to find OS Package Manager"
echo_info
exit_nochange
fi
}
## Dropbear Warning
function dbclient_warning {
if hash dbclient 2>/dev/null
then
if hash ssh 2>/dev/null
then
NOEMPTYBASHIF="1"
else
MESSAGE="Dropbear support has been deprecated - please convert to OpenSSH"
echo_warn
fi
fi
}

117
prep/gs-install.sh Normal file
View File

@ -0,0 +1,117 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-install.sh ##############################
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# This code will be called from a curl call via installation instructions
# Run this script on your primary Pi-hole to aid in preparing for Gravity Sync installation.
set -e
# Script Colors
RED='\033[0;91m'
GREEN='\033[0;92m'
CYAN='\033[0;96m'
YELLOW='\033[0;93m'
PURPLE='\033[0;95m'
BLUE='\033[0;94m'
BOLD='\033[1m'
NC='\033[0m'
# Variables
CROSSCOUNT="0"
CURRENTUSER=$(whoami)
# Header
echo -e "${YELLOW}Gravity Sync 3.0 - Installation Script${NC}"
# Check Root
if [ ! "$EUID" -ne 0 ]
then
echo -e "[${RED}${NC}] Running as Root"
CROSSCOUNT=$((CROSSCOUNT+1))
else
echo -e "[${GREEN}${NC}] Not Running as Root"
fi
# Check Sudo
sudo --validate
if [ "$?" != "0" ]
then
echo -e "[${RED}${NC}] No Sudo Powers for ${CURRENTUSER}"
CROSSCOUNT=$((CROSSCOUNT+1))
else
echo -e "[${GREEN}${NC}] Sudo Powers Valid"
fi
# Check OpenSSH
if hash ssh
then
echo -e "[${GREEN}${NC}] OpenSSH Detected"
else
echo -e "[${RED}${NC}] OpenSSH Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check Rsync
if hash rsync
then
echo -e "[${GREEN}${NC}] RSYNC Detected"
else
echo -e "[${RED}${NC}] RSYNC Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check SQLITE3
if hash sqlite3
then
echo -e "[${GREEN}${NC}] SQLITE3 Detected"
else
echo -e "[${RED}${NC}] SQLITE3 Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check GIT
if hash git
then
echo -e "[${GREEN}${NC}] GIT Detected"
else
echo -e "[${RED}${NC}] GIT Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check Pihole
if hash pihole
then
echo -e "[${GREEN}${NC}] Pi-Hole Detected"
else
echo -e "[${RED}${NC}] Pi-hole Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Combine Outputs
if [ "$CROSSCOUNT" != "0" ]
then
echo -e "[${PURPLE}!${NC}] ${RED}${CROSSCOUNT}${NC} failures detected, correct these errors before deploying Gravity Sync!"
else
echo -e "[${CYAN}>${NC}] Creating Sudoers.d File"
touch /tmp/gs-nopasswd.sudo
echo -e "${CURRENTUSER} ALL=(ALL) NOPASSWD: /etc/pihole" > /tmp/gs-nopasswd.sudo
sudo install -m 0440 /tmp/gs-nopasswd.sudo /etc/sudoers.d/gs-nopasswd
if [ "$GS_INSTALL" != "secondary" ]
then
echo -e "[${YELLOW}i${NC}] This host is prepared to use Gravity Sync, you may log off now!"
echo -e "[${YELLOW}i${NC}] Run this script again on your secondary Pi-hole host to proceed."
echo -e "[${YELLOW}i${NC}] Visit https://github.com/vmstan/gravity-sync for more instructions."
else
echo -e "[${CYAN}>${NC}] Creating Gravity Sync Directories"
git clone https://github.com/vmstan/gravity-sync.git $HOME/gravity-sync
echo -e "[${YELLOW}i${NC}] This host is now prepared to configure Gravity Sync!"
echo -e "[${YELLOW}i${NC}] Please run './gravity-sync configure' from $HOME/gravity-sync"
echo -e "[${YELLOW}i${NC}] Visit https://github.com/vmstan/gravity-sync for more instructions."
fi
fi
exit