Skip to main content
  1. Posts/

Gravity Sync Guide

·698 words·4 mins· loading · loading · ·
DNS Linux Pihole Gravity Sync
Brock Henrie
Author
Brock Henrie
A little bit about me
pihole - This article is part of a series.
Part 3: This Article

Requirements
#

Before you start this guide, make sure you have

  • 2 Piholes running on
  • Ability to SSH to Servers Container/Pihole is running on
  • If running in container, Using a Bind Mount to the host instead of a Docker Volume

In this Guide I have a Container Pihole running as primary on 12.12.12.12 and my backup will be a pihole running on a pi zero non container

Generate SSH Key
#

generate and save to ~/.ssh/gravity

ssh-keygen -t rsa -C "gravity"
cat .ssh/gravity
cat .ssh/gravity.pub 

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDeiMUeA9WVsKJHRbbPn3WIUPL9/w7N70lc1NL4hV20E7ugPcMeYACzOepSHiTDuiKx6rsrFrGR422FqZLDOLjgSMUqgU2jiFUMeNvNpM1hESn+UlEJo8JqUg9QPIU7wWBiSTv/saeFjdylhzz6CJBW5Lit7/EFxZJblHvN7vNcy8npMQyfzp9OPLhP1Bsaqlq/vmOJDb70an+ChFVje/1+CwVwMzE2buolqXYy5GlNk7xWaXUdXxPW1+Vvh4zfQ/dialUlXuyXGL06CbVTyLnPjojhWohfD5Xkr+WwckArF/tgGNcZ3J5jo4cmTaUez06fJ9kgTl92VXn+k3v++ZUAHYNZ91MAZ9pkHqf/g5GK9N61tnuyYGsd1p3wRNAwxsHFnZSrnMgma/+H+jTCdNxIKHYF+W6FRwTj4grfbR+mOAjDCbex90Axl1o5hu1i5+6s1xeWmtQ3OXXgj4AlDakYYxSDCAY4qRJdUJ4nQf+Yczsv2RYn6aUcD6jzVOQ7mFU= gravity

Add key to Primary Pihole Server
#

  1. SSH into primary pihole server. If it is running in a container, ssh into the server the container is running on.
ssh USERNAME@IP_ADDRESS
  1. Add Public Key to ~/.ssh/authorized_keys
the >> is import to add the key as a new line to the end of the file, > will replace everything in the file with the key
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDeiMUeA9WVsKJHRbbPn3WIUPL9/w7N70lc1NL4hV20E7ugPcMeYACzOepSHiTDuiKx6rsrFrGR422FqZLDOLjgSMUqgU2jiFUMeNvNpM1hESn+UlEJo8JqUg9QPIU7wWBiSTv/saeFjdylhzz6CJBW5Lit7/EFxZJblHvN7vNcy8npMQyfzp9OPLhP1Bsaqlq/vmOJDb70an+ChFVje/1+CwVwMzE2buolqXYy5GlNk7xWaXUdXxPW1+Vvh4zfQ/dialUlXuyXGL06CbVTyLnPjojhWohfD5Xkr+WwckArF/tgGNcZ3J5jo4cmTaUez06fJ9kgTl92VXn+k3v++ZUAHYNZ91MAZ9pkHqf/g5GK9N61tnuyYGsd1p3wRNAwxsHFnZSrnMgma/+H+jTCdNxIKHYF+W6FRwTj4grfbR+mOAjDCbex90Axl1o5hu1i5+6s1xeWmtQ3OXXgj4AlDakYYxSDCAY4qRJdUJ4nQf+Yczsv2RYn6aUcD6jzVOQ7mFU= gravity" >> ~/.ssh/authorized_keys

Get IDS
#

id

Take note of these, replace with your values

PRIMARY

Name Value
UID 1000
GID 1000
Groups 1000

Now lets exit and ssh into our secondary that will pull config from primary

ssh $USERNAME@IP_ADDRESS

Repeat get ids

SECONDARY

Name Value
UID 1000
GID 1003
Groups 1003

Install Gravity Sync
#

https://github.com/vmstan/gravity-sync

We will make a custom config file so dont worry, just go through setup

curl -sSL https://raw.githubusercontent.com/vmstan/gs-install/main/gs-install.sh | bash

Now lets update this file

Local is Secondary Pihole

Remote is Primary Pihole

/etc/gravity-sync/gravity-sync.conf

# REQUIRED SETTINGS ##########################

REMOTE_HOST='12.12.12.12' # IP OF PRIMARY
REMOTE_USER='neo' # PRIMARY USERNAME

# CUSTOM VARIABLES ###########################

# Pi-hole Folder/File Customization - Only need to be customized when using containers
LOCAL_PIHOLE_DIRECTORY='/etc/pihole'    # SECONDARY DATA FOLDER
REMOTE_PIHOLE_DIRECTORY='/pihole/data'  # PRIMARY DATA FOLDER
LOCAL_DNSMASQ_DIRECTORY=''
REMOTE_DNSMASQ_DIRECTORY=''
LOCAL_FILE_OWNER='1003:1003'
REMOTE_FILE_OWNER='1000:1000'

# Pi-hole Docker/Podman container name - Docker will pattern match anything set below
#LOCAL_DOCKER_CONTAINER='pihole-0'
REMOTE_DOCKER_CONTAINER='pihole-0'  # IF CONTAINER

# HIDDEN FIGURES #############################
# See https://github.com/vmstan/gravity-sync/wiki/Hidden-Figures

Setup Gravity ssh key
#

lets add the ssh key we generated to gravity sync

cat << 'EOF' > /etc/gravity-sync/gravity-sync.rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
THwxu2+qeI9FMAAAAHZ3Jhdml0eQECAwQ=
-----END OPENSSH PRIVATE KEY-----
EOF

Now it can access the primary server!

Create Sync script
#

lets make a folder called ~/cronjobs that we will save this script in

mkdir ~/cronjobs
#!/usr/bin/env bash


install_if_not_exists() {
    if ! command -v gravity-sync &> /dev/null; then
        curl -sSL https://raw.githubusercontent.com/vmstan/gs-install/main/gs-install.sh | bash
    else
        echo "gravity-sync already installed."
    fi
}


# Function to log messages to a JSON file
log() {
    mkdir -p $HOME/log
    local log_file="$HOME/log/pihole_sync.log"
    local message="$1"
    local user=$(whoami)
    local script_name=$(basename "$0")
    local metadata='{"host": "'$(hostname)'", "user": "'"$user"'", "script": "'"$script_name"'", "timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'", "message": "'"$message"'"}'
    echo "$metadata" >> "$log_file"
}

# Function to synchronize with gravity-sync and send notification
sync_and_notify() {
    # Run gravity-sync pull
    # IF command success, log success
    # IF command fail, log fail
    gravity-sync pull \
        && log "Sync Successful" \
        || log "Sync Failed" 
}

# Main script starts here
# Call the sync_and_notify function
install_if_not_exists 
sync_and_notify

Create Pull Cronjob
#

lets create a new cronjob

crontab -e

Add this line to the bottom of the file

*/5 * * * * /home/{user}/cronjobs/pihole_sync.sh

This will run the script every 5 minutes

Run Script
#

 ./cronjobs/pihole_sync.sh 

gravity-sync already installed.
∞ Initializing Gravity Sync (4.0.7)
✓ Loading gravity-sync.conf
✓ Detecting local Pi-hole installation
✓ Detecting remote Pi-hole installation - docker
✓ Gravity Sync remote peer is configured
✓ Evaluating arguments: PULL
» Remote target neo@12.12.12.12
✓ Validating pathways to Pi-hole
✓ Validating pathways to DNSMASQ
✓ Hashing the remote Gravity Database
✓ Comparing to the local Gravity Database
✓ Hashing the remote DNS Records
✓ Comparing to the local DNS Records
✓ Comparing to the local DNS Records
✓ Hashing the remote DNS CNAMEs
✓ Comparing to the local DNS CNAMEs
! Static DHCP Addresses not detected on the local Pi-hole
! No replication is required at this time
∞ Gravity Sync PULL exited after 23 seconds

Check Log

cat log/pihole_sync.log | tail -n 5
{"host": "zero", "user": "neo", "script": "pihole_sync.sh", "timestamp": "2024-05-14T01:58:59Z", "message": "Sync Successful"}
pihole - This article is part of a series.
Part 3: This Article

Related

Pihole Guide
·239 words·2 mins· loading · loading
DNS Linux DNS Linux Pihole
Terraform Pihole Records
·713 words·4 mins· loading · loading
Terraform DNS Pihole Gitops Pihole DNS Terraform Gitops