mirror of
https://github.com/vmstan/gravity-sync.git
synced 2024-08-30 18:22:11 +00:00
Merge branch 'master' of https://github.com/vmstan/gravity-sync
This commit is contained in:
commit
b7e50324c2
40
README.md
40
README.md
@ -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
|
||||
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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
|
2226
gravity-sync.sh
2226
gravity-sync.sh
File diff suppressed because it is too large
Load Diff
114
includes/gs-automate.sh
Normal file
114
includes/gs-automate.sh
Normal 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
75
includes/gs-backup.sh
Normal 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
54
includes/gs-colors.sh
Normal 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
15
includes/gs-compare.sh
Normal 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
|
||||
}
|
@ -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
48
includes/gs-exit.sh
Normal 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
148
includes/gs-hashing.sh
Normal 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
41
includes/gs-intent.sh
Normal 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
94
includes/gs-logging.sh
Normal 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
178
includes/gs-pull.sh
Normal 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
78
includes/gs-purge.sh
Normal 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
127
includes/gs-push.sh
Normal 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
209
includes/gs-restore.sh
Normal 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
40
includes/gs-root.sh
Normal 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
153
includes/gs-smart.sh
Normal 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
185
includes/gs-ssh.sh
Normal 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
143
includes/gs-update.sh
Normal 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
148
includes/gs-validate.sh
Normal 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
117
prep/gs-install.sh
Normal 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
|
Loading…
Reference in New Issue
Block a user