daily pastebin goal
57%
SHARE
TWEET

pihole-gemini - Two-way Pi-hole lists sync

GeorgeT93 Mar 12th, 2019 (edited) 138 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #! /bin/bash
  2. # Script was last updated 03-12-2019
  3.  
  4. SCRIPTVER="pihole-gemini v0.0.2.2a"
  5. # --------------------------------------------------------------------------------------------------------
  6. # This script was written to try and keep the white and black lists in sync between two Pi-holes.
  7.  
  8. # The script should be launched from /opt/pihole/gravity.sh
  9. # It should be called in the second to last line of the gravity.sh file and should be run as the user
  10. # configured for the sync process. In my case, I'm using user pi, so you would change the user from 'pi'
  11. # to the username you're using to sync the files (the user you're assigning to HAUSER in this script.)
  12.  
  13. # Example of the line to add as the second to last line of the /opt/pihole/gravity.sh file:
  14.  
  15. #       su -c '/usr/local/bin/pihole-gemini' - pi
  16.  
  17. # In the above example, you change the 'pi' at the end to your sync user, and it should appear directly
  18. # above the line that reads:
  19. #       "${PIHOLE_COMMAND}" status
  20. # in the /opt/pihole/gravity.sh file.
  21.  
  22. # --------------------------------------------------------------------------------------------------------
  23. # USER-DEFINED VARIABLES - START - Edit the values in this section to configure the script to your install.
  24.  
  25.     # User account - Should have sudo and ssh access, and a "matching" account should be set up on both Pi-hole systems
  26.         HAUSER=pi
  27.  
  28.     # Pi-hole directory (this path is expected to be the same on both Pi-holes, and should be where the FILES are located)
  29.         PIHOLEDIR=/etc/pihole
  30.  
  31.     # IP Addresses - Note that removing the value or the variable definition of either SSHPORT will cause the script to
  32.                 #    use the default SSH Port of 22 for connections to that ip address.
  33.         # Primary Pi-hole ip and ssh port
  34.             PIHOLE1=192.168.1.2
  35.             SSHPORT1=22
  36.  
  37.         # Secondary Pi-hole ip and ssh port
  38.             PIHOLE2=192.168.1.3
  39.             SSHPORT2=22
  40.  
  41.     # Define the local path to store the logfile, DO NOT include a trailing "/". Make sure this path is writeable by the user
  42.     # that runs the sync. Change this from /tmp to another folder to prevent logs from being cleared on system restart
  43.         LOGFILEPATH="/tmp"
  44.  
  45.     # How long to keep old log files (in addition to the current day's log, so a value of 6 means 7 days)
  46.         LOGKEEPDAYS=6
  47.  
  48. # USER-DEFINED VARIABLES - END - Edits made below this line may break the script.
  49. # ---------------------------------------------------------------------------------------------------------
  50.  
  51. # SCRIPT VARIABLES - START - These values are used by the script and should not be changed manually.
  52.  
  53.     # List of files to sync
  54.         FILES=(
  55.             'black.list'
  56.             'blacklist.txt'
  57.             'regex.list'
  58.             'whitelist.txt'
  59.             'lan.list'
  60.             'adlists.list'
  61.             'gravity.list'
  62.         )
  63.  
  64.     # Full logfile path and name, uncluding timestamp
  65.         LOGFILE="${LOGFILEPATH}/pihole-gemini_`date +\%Y\%m\%d`.log"
  66.  
  67.     # Flags used to determine script blocks to run.
  68.         # RUNUPDATE - 0 = Don't update; 1 = update Pi-holes
  69.         RUNUPDATE=0
  70.  
  71.         # RESTART - 0 = Don't restart; 1 = restart
  72.         RESTART=0
  73.  
  74.         # RUNGRAVITY - 0 = Don't update gravity; 1 = Update gravity (don't download lists)
  75.         RUNGRAVITY=0
  76.  
  77.         # DEFAULT SSHPORT - This value is only provided here to use the default port of 22 if a port is not defined for the specified ip address
  78.         DEFAULTSSHPORT=22
  79.  
  80.         # INITIALIZE PORT VARIABLES - This segment keeps the SSHPORT variables as set in the user-defined variables section. They are included here
  81.                                     # mainly as a fallback in case the variables are accidentally removed from the user-defined variables section.
  82.             SSHPORT1=$SSHPORT1
  83.             SSHPORT2=$SSHPORT2
  84.  
  85.         # DETERMINE IP AND PORTS TO USE - START
  86.             # This section checks the interface used to connect to the local gateway, then determines the current ip address
  87.             # based on that interface. Finally, it checks the current ip address against the two addresses the script has
  88.             # configured to determine which one is the remote Pi-hole to send commands to, and configures the appropriate port.
  89.  
  90.                 LOCALGATEWAY=$(ip -4 route | awk '{print $3}' | head -n 1)
  91.                 LOCALINTERFACE=$(ip -4 route | awk '{print $3}' | tail -n 1)
  92.                 LOCALIP=$(ip -4 -o addr show $LOCALINTERFACE | awk '{print $4}' | cut -d "/" -f 1)
  93.                     case $LOCALIP in
  94.                         $PIHOLE1)
  95.                             # echo "Local ip address matches PIHOLE1 ip, so the remote Pi-hole is PIHOLE2."
  96.                             REMOTEPI=$PIHOLE2
  97.                             if [ -z $SSHPORT2 ]; then
  98.                                 # SSHPORT2 value is empty, use the default ssh port.
  99.                                 SSHPORT=$DEFAULTSSHPORT
  100.                             else
  101.                                 # SSHPORT2 value exists, use that for connections to PIHOLE2.
  102.                                 SSHPORT=$SSHPORT2
  103.                             fi
  104.                         ;;
  105.                         $PIHOLE2)
  106.                             # echo "Local ip address matches PIHOLE2 ip, so the remote Pi-hole is PIHOLE1."
  107.                             REMOTEPI=$PIHOLE1
  108.                             if [ -z $SSHPORT1 ]; then
  109.                                 # SSHPORT1 value is empty, use the default ssh port.
  110.                                 SSHPORT=$DEFAULTSSHPORT
  111.                             else
  112.                                 # SSHPORT1 value exists, use that for connections to PIHOLE1.
  113.                                 SSHPORT=$SSHPORT1
  114.                             fi
  115.                         ;;
  116.                         *)
  117.                             echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  118.                             echo "* `date '+%Y-%m-%d %H:%M:%S'` - ERROR! - $SCRIPTVER was unable to determine the local ip address." 2>&1 | tee -a $LOGFILE
  119.                             echo "                                  This is a fatal error. Script can not continue. Please check your" 2>&1 | tee -a $LOGFILE
  120.                             echo "                                  configuration for the script, and make sure you are connected to" 2>&1 | tee -a $LOGFILE
  121.                             echo "                                  your router and have an ip address assigned." 2>&1 | tee -a $LOGFILE
  122.                             echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  123.                             REMOTEPI="Unknown"
  124.                             exit 1
  125.                         ;;
  126.                     esac
  127.  
  128.         # DETERMINE IP AND PORTS TO USE - END
  129.  
  130. # SCRIPT VARIABLES - END
  131.  
  132. # LOG HEADER START - The following echo commands are for formatting purposes in the log file.
  133.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  134.     echo "`date '+%Y-%m-%d %H:%M:%S'` - $SCRIPTVER was successfully launched as user: $USER" 2>&1 | tee -a $LOGFILE
  135.     echo "                      $LOCALIP is updating Pi-hole on $REMOTEPI"
  136.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  137. # LOG HEADER - END
  138.  
  139. # SSH CONNECTION TEST - START
  140.     echo "`date '+%Y-%m-%d %H:%M:%S'` - Testing SSH Connection to $HAUSER@$REMOTEPI. Please wait." 2>&1 | tee -a $LOGFILE
  141.  
  142.     ssh -q -p $SSHPORT $HAUSER@$REMOTEPI exit
  143.     SSHSTATUS=$?
  144.  
  145.         if [ $SSHSTATUS -eq 0 ]; then
  146.             # SSH is up
  147.             echo "`date '+%Y-%m-%d %H:%M:%S'` - SSH Connection to $HAUSER@$REMOTEPI was tested successfully." 2>&1 | tee -a $LOGFILE
  148.             RUNUPDATE=1
  149.  
  150.         else
  151.             # SSH is down
  152.             echo "* `date '+%Y-%m-%d %H:%M:%S'` - ERROR! Unable to establish SSH connection as $HAUSER@$REMOTEPI on port $SSHPORT." 2>&1 | tee -a $LOGFILE
  153.             echo "*                       This is a fatal error as SSH is required for this script. Unable to update $REMOTEPI on port $SSHPORT." 2>&1 | tee -a $LOGFILE
  154.             echo "*                       $REMOTEPI may be offline, you may have specified the wrong port, or you have not correctly configured your SSH keys." 2>&1 | tee -a $LOGFILE
  155.             echo "*                       $REMOTEPI has NOT been updated."
  156.             RUNUPDATE=0
  157.         fi
  158. # SSH CONNECTION TEST - END
  159.  
  160. # UPDATE REMOTE PIHOLE - START
  161.     if [ $RUNUPDATE -eq 1 ]; then
  162.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  163.  
  164.     # FILE SYNC - START - This section handles compares the local and remote versions of the files specified in the $FILES variable
  165.                     #     and updates the remote files if neccesary.   
  166.         for FILE in ${FILES[@]}
  167.             do
  168.                 if [[ -f $PIHOLEDIR/$FILE ]]; then
  169.                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Comparing local to remote $FILE and updating if neccesary." 2>&1 | tee -a $LOGFILE
  170.  
  171.                     RSYNC_COMMAND=$(rsync --rsync-path='/usr/bin/sudo /usr/bin/rsync' -aiu -e "ssh -l $HAUSER@$REMOTEPI -p$SSHPORT" $PIHOLEDIR/$FILE $HAUSER@$REMOTEPI:$PIHOLEDIR)
  172.  
  173.                         if [[ -n "${RSYNC_COMMAND}" ]]; then
  174.                             # rsync copied changes so restart
  175.  
  176.                             case $FILE in
  177.                                 adlists.list)
  178.                                     # Updating adlists.list requires only a gravity update
  179.                                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Updated $FILE on $REMOTEPI. Gravity will be updated on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  180.                                     RUNGRAVITY=1
  181.                                 ;;
  182.  
  183.                                 gravity.list)
  184.                                     # Updating gravity.list requires only a gravity update
  185.                                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Updated $FILE on $REMOTEPI. Gravity will be updated on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  186.                                     RUNGRAVITY=1
  187.                                 ;;
  188.  
  189.                                 *)
  190.                                     # Updating white and/or black lists (or other files) requires a remote restart but not a gravity update
  191.                                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Updated $FILE on $REMOTEPI. $REMOTEPI will be restarted." 2>&1 | tee -a $LOGFILE
  192.                                     RESTART=1
  193.                                 ;;
  194.                             esac
  195.  
  196.                         else
  197.                             # no changes so do nothing
  198.                             echo "`date '+%Y-%m-%d %H:%M:%S'` - Local file $FILE matches $FILE on $REMOTEPI. Remote file was not updated." 2>&1 | tee -a $LOGFILE
  199.                         fi
  200.  
  201.                 else
  202.                     # file does not exist, skipping
  203.                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Local file $FILE does not exist. Skipping." 2>&1 | tee -a $LOGFILE
  204.                 fi
  205.             done
  206.     # FILE SYNC - END
  207.  
  208.     # RESTART REMOTEPI (IF NEEDED) - START
  209.         if [ $RESTART -eq 1 ]; then
  210.             echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  211.             echo "`date '+%Y-%m-%d %H:%M:%S'` - Updated files have been copied to $REMOTEPI. Restarting..." 2>&1 | tee -a $LOGFILE
  212.  
  213.             echo "`date '+%Y-%m-%d %H:%M:%S'` - Sending restart command to pihole-FTL on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  214.  
  215.             ssh $HAUSER@$REMOTEPI -p $SSHPORT "sudo -S service pihole-FTL restart"
  216.             if [ $? -ne 0 ]; then
  217.                 echo "* `date '+%Y-%m-%d %H:%M:%S'` - ERROR! - Unable to restart pihole-FTL service on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  218.  
  219.             else
  220.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - Successfully restarted pihole-FTL service on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  221.             fi
  222.         fi
  223.     # RESTART REMOTEPI - END
  224.  
  225.     # UPDATE REMOTE GRAVITY (IF NEEDED) - START
  226.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  227.         case $RUNGRAVITY in
  228.             0)
  229.                 # Gravity did not need updating - do nothing
  230.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - Gravity on $REMOTEPI did not need updating." 2>&1 | tee -a $LOGFILE
  231.             ;;
  232.             1)
  233.                 # Gravity needs refreshing, but not a full update - Update gravity without redownloading lists
  234.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - Refreshing gravity on $REMOTEPI. Lists will not be redownloaded." 2>&1 | tee -a $LOGFILE
  235.                 ssh $HAUSER@$REMOTEPI -p $SSHPORT "sudo -S pihole -g --skip-download"
  236.                 if [ $? -ne 0 ]; then
  237.                     echo "* `date '+%Y-%m-%d %H:%M:%S'` - ERROR! - Unable to refresh gravity on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  238.  
  239.                 else
  240.                     echo "`date '+%Y-%m-%d %H:%M:%S'` - Success! Successfully refreshed gravity on $REMOTEPI." 2>&1 | tee -a $LOGFILE
  241.                 fi
  242.             ;;
  243.         esac
  244.     # UPDATE REMOTE GRAVITY - END
  245.  
  246.     # CLEAN OLD LOG FILES - START
  247.         # Check the LOGFILEPATH for outdated log files and delete old logs
  248.         echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  249.         echo "`date '+%Y-%m-%d %H:%M:%S'` - Checking ${LOGFILEPATH} for outdated log files." 2>&1 | tee -a $LOGFILE
  250.  
  251.         look_in="${LOGFILEPATH}/pihole-gemini_*.log"
  252.        
  253.         del_file=`find $look_in ! -name $LOGFILE -daystart -mtime +$LOGKEEPDAYS`
  254.         if [ -z "$del_file" ]; then
  255.             echo "`date '+%Y-%m-%d %H:%M:%S'` - There were no outdated log files to remove." 2>&1 | tee -a $LOGFILE
  256.  
  257.         else
  258.             echo "`date '+%Y-%m-%d %H:%M:%S'` - Outdated log file(s) found. Removing..." 2>&1 | tee -a $LOGFILE
  259.             sudo find $look_in ! -name $LOGFILE -daystart -mtime +$LOGKEEPDAYS -prune -exec rm -rv "{}" \;
  260.             if [ $? -ne 0 ]; then
  261.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - ERROR! Unable to remove outdated log files from $LOGFILEPATH." 2>&1 | tee -a $LOGFILE
  262.             else
  263.                 echo "`date '+%Y-%m-%d %H:%M:%S'` - Outdated log files successfully cleaned." 2>&1 | tee -a $LOGFILE
  264.             fi
  265.         fi
  266.     # CLEAN OLD LOG FILES - END
  267.  
  268.     fi
  269. # UPDATE REMOTE PIHOLE - END
  270.  
  271. # LOG FOOTER - START
  272.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  273.     echo "`date '+%Y-%m-%d %H:%M:%S'` - $SCRIPTVER completed update of $REMOTEPI from $LOCALIP." 2>&1 | tee -a $LOGFILE
  274.     echo "--------------------------------------------------------------------------------------------" 2>&1 | tee -a $LOGFILE
  275. # LOG FOOTER - END
  276.  
  277. # END OF SCRIPT
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top