Compare commits

...

26 Commits

Author SHA1 Message Date
Michael Stanclift
54ddeb6666
Final commit 2024-07-26 13:45:33 -05:00
Michael Stanclift
50c786eb9d
4.0.7 (#433)
* fix: typo in dns cname permission change (#431)

This typo prevents gravity-sync from continuing and calculating hashes resulting in always considering there are changes to sync

* Update VERSION

* Branding and typos

* 4.0.7

---------

Co-authored-by: Alexandre Perrault <alexperrault@users.noreply.github.com>
2024-01-15 09:21:24 -06:00
Michael Stanclift
ccb89624f7
v4.0.6 (#424)
* Updates to respect configured options (#413)

- remote pihole detection uses configured docker/podman binaries
- file permission updates use configured local/remote file owners

Also fixes https://github.com/vmstan/gravity-sync/issues/392

---------

Co-authored-by: Eric Roch <emroch@users.noreply.github.com>
2024-01-07 12:32:39 -06:00
Sam Mingo
4402ff0d73
Update README.md (#403) 2023-10-13 22:14:14 -05:00
Michael Stanclift
ad783f1385
4.0.5 (#400)
* Simple fix for podman to work; whitespace clean up (#396)

* Fix set_pihole_exec to match full container names (#390)

Fix set_pihole_exec to match full container names, rather
than their substrings, by adding begin and end anchors to
the 'docker ps -qf name=PATTERN' being used.

Signed-off-by: William Blew <william@kulian.org>

* Fix the detect_xxx_pihole routines. (#389)

Fix the detect_xxx_pihole routines to respect the configurable
PIHOLE_CONTAINER_IMAGE variable.

The ghcr.io/pi-hole/pihole image is also released by the Pi-hole
project, just as the pihole/pihole image.

This commit enables ghcr.io image usage by adding the following
to the /etc/gravity-sync.conf file:

PIHOLE_CONTAINER_IMAGE='ghcr.io/pi-hole/pihole'

Signed-off-by: William Blew <william@kulian.org>
Co-authored-by: Michael Stanclift <mx@vmstan.com>

* Make check for sudo privileges more accurate (#375)

* Make check for sudo privileges more accurate

The existing method of checking if the Gravity Sync user has sudo rights is flawed, in that it will break if the user is not in the `sudo` group (on Debian based distros) or the `wheel` group (on CentOS/RHEL distros).

A more accurate way of checking if a user has sudo privileges is using `sudo --validate` or `sudo -n true`; both of which return `0` if the user has sudo privileges.

This commit updates the `validate_sudo_status` function to use `sudo --validate` so that Gravity Sync is actually checking if a user has sudo privileges, rather than just checking group memberships.

* Fix bug in patch

---------

Co-authored-by: llamalump <29816026+llamalump@users.noreply.github.com>

* Fix: GS_SSH_PORT can be changed now via  'gravity-sync config <NEW_PORT>' when already set in gravity-sync.conf. Fix: Initial sync of static DHCP and CNAME to 'empty pihole' now works. Enhancement: Various settings now settable via ENV vars (for Docker) (#384)

* SSH custom port: Fixed bug, where GS_SSH_PORT is overwritten by gravity-sync.conf (if set) when calling 'gravity-sync config NEW_SSH_PORT'. Docker enhancements: Made many config-variables settable via ENV vars

* Fixing initial push of CNAME and Static DHCP entries to an 'empty' remote (fixes https://github.com/vmstan/gravity-sync/issues/377)

* Removing unecessary 'export' keyword

* Fixed 'md5_recheck' for the bug https://github.com/vmstan/gravity-sync/issues/377

* Adding ENV documentation

* Fixing typo

* Fixed type and nicely formatted tables with emacs

---------

Co-authored-by: Michael Stanclift <mx@vmstan.com>

* Update VERSION

* Update gravity-sync

---------

Signed-off-by: William Blew <william@kulian.org>
Co-authored-by: Matt Woodson <mwoodson@gmail.com>
Co-authored-by: William Blew <william@kulian.org>
Co-authored-by: Seb Thomson <29816026+rst-ack@users.noreply.github.com>
Co-authored-by: llamalump <29816026+llamalump@users.noreply.github.com>
Co-authored-by: Klaus Zipfel <30482165+systemofapwne@users.noreply.github.com>
2023-07-10 11:46:11 -05:00
Michael Stanclift
183190e4bb
Update VERSION 2023-07-10 11:43:35 -05:00
Michael Stanclift
9fc48413fe
Update VERSION 2023-07-10 11:43:18 -05:00
Michael Stanclift
15867c0378
4.0.4 (#343)
* Start 4.0.4

* SDHCP replication

* Fix typo of SDHCP

* another SDHCP reference

* Update readme
2022-05-03 10:50:05 -05:00
Michael Stanclift
53bc721c50
4.0.3 (#341)
* fix hard coded pkif file on import

* 4.0.3 proper

* rename cname log

* added messages for blank values during config
2022-04-29 09:56:28 -05:00
Michael Stanclift
d3bc40e549
Create FUNDING.yml 2022-04-14 12:39:47 -05:00
Michael Stanclift
c952a427c7
Update README.md 2022-04-13 12:41:08 -05:00
Michael Stanclift
eec49c9c2a
4.0.2 (#330)
* Start 4.0.2

* automate with options

* change random range

* Use tmp to stash service timers

* make redirect silent

* sed not tee

* space

* simple

* Add ssh migration

* shuf not random

* quad

* 4.0.2 Signoff
2022-04-13 09:37:34 -05:00
Michael Stanclift
7f509fabb6
Update README.md 2022-04-12 14:48:43 -05:00
Michael Stanclift
73a6e00d8a
4.0.1 (#328)
* attempt to add custom ssh function

* sudo touch

* set port range

* $2

* maybe

* $1

* comment out last line

* $2x2

* $2x3

* $3

* i don't even know

* $2x4

* 22

* ""

* how does this work

* total rewrite of case stack

* [[ ]]

* if two is a number

* INPUT_SSH

* blank

* Add remote target port

* 4.0.1

* Fix version output

* greater than version

* test "downgrade"

* 4.0.1 Ready
2022-04-12 14:26:36 -05:00
Michael Stanclift
3720a91eeb 4.0.0(4) 2022-04-12 10:44:04 -05:00
Michael Stanclift
56650f4281 4.0.0(3) 2022-04-12 10:42:19 -05:00
Michael Stanclift
f9a0179e62
4.0.0(2) 2022-04-12 08:05:35 -05:00
Michael Stanclift
bc635e14e9 4.0.0.1 2022-04-11 19:57:28 -05:00
Michael Stanclift
41ecce4b5a
4.0.0 (#317)
* 4.0.0

* drop .sh

* chmod +x

* change pull locations

* push

* change folders

* cleanup extensions

* error with cname push

* backup purge redone

* back to the CORE!

* remove references to backup folder

* rename pihole container image variable

* rename pihole binary variables

* rename docker binary variables

* rename pihole dir variables

* data names

* remote and local

* DNSMASQ folders

* remove dnsmasq

* more variable renames

* fix config location

* fix import path

* validate gs folder fix

* remove references to LOCAL_FOLDR

* updater moving into place

* create update script

* "

* change context?

* remove git check

* add ( back

* Fix automation path

* replace standalone SQLite with FTL

* remote

* adjust docker folder locations

* fix remote location

* remove sqlite validation

* remove all references to cron

* config rewrite

* soruce config file

* remote file not dir

* hidden figures

* config file

* remove references to dropbear

* remove backup cleanup from most tasks

* remove gs folder validation

* remove ssh detection

* static set ssh

* id_rsa

* extra line

* echo lines

* retain previous config file

* isolinear

* ∞

* rearrange info

* remove bash path

* check replication status

* check timer instead

* dev mode against new repo location

* rewrite purge

* path

* add default file owner back

* simpler

* /usr/bin/bash

* fix ftl binary location

* whoami

* remote FTL

* don't delete from remote

* purge it

* remove path not name

* sudo tee

* tee off instead of echo out

* sudo sudo sudo

* sudo all the things

* Even more sudo

* how much more can you sudo

* change keyfile permissions

* remote/local

* all the sudo

* sudo in your rsync

* pull to tmp

* sudo copied

* silence tee

* New keyfile creation method

* send hash to the other side

* saving hashes

* directions are hard

* reverse hash for the other side

* remote ping test from config

* further randomize replication times

* rerandom

* fix bash call to update.sh

* Remove now-unused UI code

* remove legacy distro check code

* UI FILE PERMISSION spelling

* read -r

* GS_INTENT_VALIDATE

* remove intent validation from push

* cleanup tasks

* remove cname opt-out

* remove DNS options

* rename validation and set functions

* import_gs

* replace primary/local

* relocate file owner variables

* set variable for /tmp

* just set file permissions don't bother checking

* set file permissions

* remove extra message

* md5 variable renames

* replacing pri/sec variable names in smart sync

* .gsbackup replaced

* cleanup then

* removing compensation

* More primary and secondary references removed

* README update

* Update README.md

* new md5 variable

* multiple md5 hash logs

* gravity db listed twice

* md52 deletion at remote

* rename on sync

* move after send

* try try again

* this should work

* force it

* now for something completely different

* remove ;

* KISS

* KISS2

* fix hashing lookups

* set remote hash permissions

* vary info output

* remove unused functions

* new docs uploaded for publishing to wiki

* new system requirements

* words

* host

* rewrite install instructions

* rewrite install instructions

* rewrite all the thing

* massive variable renames

* building out dockerfile

* switch to photon

* change all if then style to single line

* cd || exit

* reformat math

* ${SSHPASSWORD} references removed

* OS_SSH_CMD set in variables

* cleanup function calls

* remove old root_check function

* cleaning up more variables

* more variable cleanup

* Line

* rewrite all of pihole detection

* echo_good

* >/dev/null 2>&1

* detecting local message

* sed?

* | sed 's/\s.*$//'

* fix sed

* no more whiches

* 2>/dev/null some more

* massive config rewrite for advanced workflow

* fix prompt

* output remote images

* echo again

* remote again

* cats?

* detect container locations

* fix space

* rewrite remote detection

* remote not local

* don't delete remote

* exec then rsync

* move lines

* enclose

* dont var

* daft

* quotes

* remove variable

* run you booger

* REMOTE

* remove echo_lines

* no config for more commands

* no config again

* shellcheck

* comment cleanup

* spell check is wonderful

* change docker container name output

* escape more quotes

* simpler command for remote side

* scape that?

* maybe less, i dunno

* try both lists again

* change spacing and line breaks

* streamline status icons for configuration

* retrieving remote settings

* error_validate

* disable task

* fix disable task

* detect_gs_peer

* task_purge doesn't use config

* remote message

* fallback

* " "

* comments

* add monitor mode

* Adds .sh script back as upgrader

* upgrader in old script

* reverse logic

* pretty upgrade script

* migration complete

* change template directory

* check for crontab hash

* user not host

* silence hash for crontab check

* warn

* warning

* reword config ending

* missing "

* os-release

* blue

* disable automation doesn't require config

* move stop

* signing off on 4.0
2022-04-11 17:06:09 -05:00
Michael Stanclift
ff32465625
3.7.0 (#315)
* add path removal to clear_cron

* 3.6.4

* add local folder to path

* templates for systemd timers

* Wantedby

* user root

* Gonna be 3.7

* Remove legacy cron code from automate function

* Core for moving replication jobs into place

* Move stop before copy

* Add Gravity Sync messages

* Service file customization

* Line break

* 10 minutes to sudo

* if active else

* Do things quietly

* Custom exec path

* clear exec start

* warning about cron

* no longer exists
2022-03-29 16:11:00 -05:00
Michael Stanclift
087550742a
3.6.3 (#313)
* remove full dns restart

* change conditions for ftl restart

* run reload for non-smart tasks

* 3.6.3

* add user path to crontab

* ""

* include path

* $

* PATH=$PATH

* add Path_Fix
2022-03-28 14:18:16 -05:00
Michael Stanclift
ac62915b5b
3.6.2 (#304)
* 3.6.2

* 3.6.2

* 3.6.2 revert
2022-03-02 10:22:59 -06:00
Michael Stanclift
7d8bde529c
3.6.1 (#302)
* 3.6.1 Start

* Remove prep directory
2022-03-02 09:40:04 -06:00
Michael Stanclift
c7a825970a
3.6.0 (#299)
* start 3.6

* Remove backup retention reference

* dbclient_warning removed

* remove extra linebreaks

* remove backup task

* Increased backup and integrity timeouts to 240

* Remove brackets from message codes

* Arrow for info

* Different arrow

* Ain't gonna restore no more

* Abortion aborted

* format change for config test

* All kinds of yes and no

* echo_grav

* Move advanced to the end

* removed custom ssh, ping check and port options from wizard

* primary address changes

* rework user input

* good clean fun

* smaller version text

* less info

* Set push commands to default 240 second timeout

* Remove reference to backup and restore tasks from log output

* Remove backup refs

* Move UI elements over to gs-ui

* Move ICMP to UI

* More UI

* More UI

* UI changes

* Add end config

* Spaces and such

* MOre UI

* UI

* UI UI UI

* UI UI

* echo_blue

* echo_blue too

* switch

* fip flop

* Too blue

* Fix path being run

* =

* Remove ()

* continued cleaning

* Almost done rewriting config

* switch CNAME defaults

* Add CNAME function
2022-03-01 09:47:22 -06:00
Michael Stanclift
3a125a2e30
3.5.0 (#296)
* Fixed typo (#269)

* Fix cache wipe (#282)

* Update gs-pull.sh

`restartdns          Full restart Pi-hole subsystems
                        Add 'reload' to update the lists and flush the cache without restarting the DNS server
                        Add 'reload-lists' to only update the lists WITHOUT flushing the cache or restarting the DNS server`
fixing typo

* Update gs-push.sh

fixing typo

* Update VERSION

* Update gravity-sync.sh

* new version

* Clear backup directory

* Cleanup after updating

* remove backup functions

* Remove reference to backup and restore functions

* Change backup references to copy

* Host

* Remove reference to backup retention

* Remove reference to backup retention

Co-authored-by: Philippe Ouellette <philippeouellette@protonmail.com>
Co-authored-by: djschnei21 <32646250+djschnei21@users.noreply.github.com>
2022-02-25 12:25:57 -06:00
Michael Stanclift
93656c29ea
3.4.8 (#283)
* Fixed typo (#269)

* Fix cache wipe (#282)

* Update gs-pull.sh

`restartdns          Full restart Pi-hole subsystems
                        Add 'reload' to update the lists and flush the cache without restarting the DNS server
                        Add 'reload-lists' to only update the lists WITHOUT flushing the cache or restarting the DNS server`
fixing typo

* Update gs-push.sh

fixing typo

* Update VERSION

* Update gravity-sync.sh

Co-authored-by: Philippe Ouellette <philippeouellette@protonmail.com>
Co-authored-by: djschnei21 <32646250+djschnei21@users.noreply.github.com>
2022-01-12 12:23:53 -06:00
36 changed files with 3195 additions and 3735 deletions

13
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,13 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: vmstan
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

12
.gitignore vendored
View File

@ -1,14 +1,6 @@
gravity-sync.log
gravity-sync.cron
gravity-sync.conf
gravity-sync.md5
backup/*.last
backup/*.backup
backup/*.push
backup/*.pull
logs/*
settings/gravity-sync.conf
dev
.vscode
.DS_Store
.nova
settings/*
logs/*

9
Dockerfile Normal file
View File

@ -0,0 +1,9 @@
FROM photon:4.0
LABEL maintainer="Michael Stanclift <https://github.com/vmstan>"
RUN tdnf update -y \
&& tdnf install -y curl git rsync openssh
RUN curl -sSL http://gravity.vmstan.com/beta | GS_DOCKER=1 && GS_DEV=4.0.0 bash
CMD gravity-sync version

85
ENV.md Normal file
View File

@ -0,0 +1,85 @@
<p align="center">
<img src="images/gs-logo.svg" width="300" alt="Gravity Sync">
</p>
<span align="center">
# Gravity Sync ENVs
</span>
These tables are a list of all Gravity Sync settings, that can be tweaked via ENVs. Keep in mind that some of them are stored in `/etc/gravity-sync/gravity-sync.conf` after running `gravity-sync configure` and that `gravity-sync.conf` has higher priority than ENVs.
### Local and remote paths & settings
These settings will determine, from where (locally) to where (remotely) will be synced and with which account/permissions
| Variable | Default | Value | Description |
|----------------------------|------------------|------------|----------------------------------------------------|
| `LOCAL_PIHOLE_DIRECTORY` | `/etc/pihole` | path | Path to local pi-hole instance in the filesystem |
| `REMOTE_PIHOLE_DIRECTORY` | `/etc/pihole` | path | Path to remote pi-hole instance in the filesystem |
| `LOCAL_DNSMASQ_DIRECTORY` | `/etc/dnsmasq.d` | path | Path to local dnsmasqd instance in the filesystem |
| `REMOTE_DNSMASQ_DIRECTORY` | `/etc/dnsmasq.d` | path | Path to remote dnsmasqd instance in the filesystem |
| `LOCAL_FILE_OWNER` | `pihole:pihole` | user:group | Local owner and group of the pi-hole config |
| `REMOTE_FILE_OWNER` | `pihole:pihole` | user:group | Remote owner and group of the pi-hole config |
### Docker specific settings
Gravity-sync will check your system for a native Pi-hole install first (on local and remote site) and if does not detect any, tests against Docker/Podman Pi-hole instances.
Here, you can specific the Docker or Podman container name, that Gravity Sync should interact with.
| Variable | Default | Value | Description |
|---------------------------|----------|----------------|--------------------------------------------|
| `LOCAL_DOCKER_CONTAINER` | `pihole` | container name | Container name of pi-hole running locally |
| `REMOTE_DOCKER_CONTAINER` | `pihole` | container name | Container name of pi-hole running remotely |
### Paths to standard files and folders
These settings are most likely the same on all systems. No need to touch them but nice to be able to touch them, if necessary.
| Variable | Default | Value | Description |
|----------------------------|-------------------------|-------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `DEFAULT_PIHOLE_DIRECTORY` | `/etc/pihole` | path | Docker/Podman: Path to Pi-hole instance within a Docker/Podman container. Don't mix up with `LOCAL_PIHOLE_DIRECTORY`, which is only used against local Pi-hole instances (non-dockerized). |
| `LOCAL_PIHOLE_BINARY` | `/usr/local/bin/pihole` | path | Path to `pihole` binary on local system |
| `REMOTE_PIHOLE_BINARY` | `/usr/local/bin/pihole` | path | Path to `pihole` binary on remote system |
| `LOCAL_FTL_BINARY` | `/usr/bin/pihole-FTL` | path | Path to `pihole-FTL` binary on local system |
| `REMOTE_FTL_BINARY` | `/usr/bin/pihole-FTL` | path | Path to `pihole-FTL` binary on remote system |
| `LOCAL_DOCKER_BINARY` | `/usr/bin/docker` | path | Path to `docker` binary on local system |
| `REMOTE_DOCKER_BINARY` | `/usr/bin/docker` | path | Path to `docker` binary on remote system |
| `LOCAL_PODMAN_BINARY` | `/usr/bin/podman` | path | Path to `podman` binary on local system |
| `REMOTE_PODMAN_BINARY` | `/usr/bin/podman` | path | Path to `podman` binary on remote system |
| `PIHOLE_CONTAINER_IMAGE` | `pihole/pihole` | path | Name of the default pi-hole docker image |
### Nitty-gritty finetuning the target files
Here, you can specifiy the Gravity, DNS (A, CNAME) and DHCP settings file of Pi-hole. It is almost certain, that these filenames do never change (except if upstream Pi-hole decides so).
| Variable | Default | Value | Description |
|-----------------|-------------------------------|-------|--------------------------------------------|
| `PH_GRAVITY_FI` | `gravity.db` | file | The gravity filename (blocklist) of pihole |
| `PH_CUSTOM_DNS` | `custom.list` | file | The custom DNS (A) filename of pihole |
| `PH_CNAME_CONF` | `05-pihole-custom-cname.conf` | file | The custom DNS (CNAME) filename of pihole |
| `PH_SDHCP_CONF` | `04-pihole-static-dhcp.conf` | file | The custom DHCP filename of pihole |
### Backup Customization
| Variable | Default | Value | Description |
|----------------------------|---------|----------------|-----------------------------------------------------------------------------------------------|
| `GS_BACKUP_TIMEOUT` | `240` | seconds | How long shall we allow a gravity.db backup task to run, before it is deemed to be timed out? |
| `GS_BACKUP_INTEGRITY_WAIT` | `5` | seconds | Some wait time, before integrity checks are performed on gravity.db |
| `GS_BACKUP_EXT` | `gsb` | file-extension | Local and remote gravity.db backup files will get this file-extension added before merge. |
### GS Folder/File Locations
| Variable | Default | Value | Description |
|-------------------------|-----------------------------------|-------|--------------------------------------------------------------------------------------------|
| `GS_ETC_PATH` | `/etc/gravity-sync` | path | Path to the gravity-sync work & config directory |
| `GS_CONFIG_FILE` | `gravity-sync.conf` | file | Name of the gravity.sync config file |
| `GS_SYNCING_LOG` | `gs-sync.log` | file | Logfile for gravity-sync |
| `GS_GRAVITY_FI_MD5_LOG` | `gs-gravity.md5` | file | Filename for storing `PH_GRAVITY_FI` hash (used for sync comparison locally and on remote) |
| `GS_CUSTOM_DNS_MD5_LOG` | `gs-clist.md5` | file | Filename for storing `PH_CUSTOM_DNS` hash (used for sync comparison locally and on remote) |
| `GS_CNAME_CONF_MD5_LOG` | `05-pihole-custom-cname.conf.md5` | file | Filename for storing `PH_CNAME_CONF` hash (used for sync comparison locally and on remote) |
| `GS_SDHCP_CONF_MD5_LOG` | `04-pihole-static-dhcp.conf.md5` | file | Filename for storing `PH_SDHCP_CONF` hash (used for sync comparison locally and on remote) |
### Remote SSH config
Customize parameters for accessing the remote end via SSH
| Variable | Default | Value | Description |
|---------------|----------------------------------|-------|---------------------------------------------------------------------------------------------------------|
| `GS_SSH_PORT` | `22` | port | Port of the remote gravity-sync container/host |
| `GS_SSH_PKIF` | `<GS_ETC_PATH>/gravity-sync.rsa` | file | Path to the local SSH private key of gravity-sync, that will be used for pubkey auth against the remote |
### Upgrade: Gravity Sync sourcecode location
Gravity Sync is locally installed as a GitHub repo. In order to upgrade your local Gravity Sync instance via `gravity-sync upgrade` to the latest version, the path to that git repo must be known and can be specified below.
| Variable | Default | Value | Description |
|-----------------|---------------------|-------|---------------------------------------------|
| `GS_LOCAL_REPO` | `<GS_ETC_PATH>/.gs` | path | Local install path of the gravity-sync repo |

View File

@ -1,5 +1,5 @@
<p align="center">
<img src="https://vmstan.com/content/images/2021/02/gs-logo.svg" width="300" alt="Gravity Sync">
<img src="images/gs-logo.svg" width="300" alt="Gravity Sync">
</p>
<span align="center">
@ -8,43 +8,45 @@
</span>
###
### Effective July 26, 2024, this project has been retired. Thank you for your use and enthusiasm for a project that began as a few lines of bash in a Slack channel and envolved into something far more complex, and used by many thousands of Pi-hole enthusiasts over the last four years.
What is better than a [Pi-hole](https://github.com/pi-hole/pi-hole) blocking trackers, advertisements, and other malicious domains on your network? That's right, **two** Pi-hole blocking all that junk on your network!
### The last released version of Gravity Sync (4.0.7) should continue to work with Pi-hole 5.x, but not with Pi-hole 6+ due to architecture changes.
What is better than a [Pi-hole](https://github.com/pi-hole/pi-hole) blocking trackers, advertisements, and other malicious domains on your network? That's right, **two** Pi-hole blocking all that junk on your network!
- [Seriously. Why two Pi-hole?](https://github.com/vmstan/gravity-sync/wiki/Frequent-Questions#why-do-i-need-more-than-one-pi-hole)
But if you have more than one Pi-hole in your network you'll want a simple way to keep the list configurations and local DNS settings identical between the two. That's where Gravity Sync comes in. With proper preparation, it should only take a few minutes to install. Ideally you setup Gravity Sync and forget about it -- and in the long term, it would be awesome if the Pi-hole team made this entire script unnecessary.
But if you have redundant Pi-hole in your network you'll want a simple way to keep the list configurations and local DNS settings identical between the two. That's where Gravity Sync comes in. Setup should only take a few minutes.
## Features
Gravity Sync replicates the Pi-hole Domain Database (`gravity.db`), which includes:
- Blocklist settings with status and comments.
- Domain whitelist and blacklist along with status with comments.
- Custom RegEx whitelist and blacklists.
- Clients and groups along with any list assignments.
Gravity Sync replicates the core of Pi-hole's ad/telemetry blocking settings, which includes:
Gravity Sync can also (optionally) replicate the Local DNS Records and CNAMEs configuration files.
- Adlist settings with status and comments.
- Domain/RegEx whitelists and blacklist along with status and comments.
- Clients and group assignments, along with status and descriptions.
Gravity Sync also replicates local network DNS/DHCP settings, which includes:
- Local DNS Records.
- Local CNAME Records.
- Static DHCP Assignments.
### Limitations
Gravity Sync will **not**:
- Overwrite device specific Pi-hole settings specific to the local network configuration.
- Change the Pi-hole admin/API passwords, nor does not leverage these at all.
- Modify the individual Pi-hole's upstream DNS resolvers.
- Sync DHCP settings or monitor device leases.
- Merge long term data, query logs, or statistics.
- Modify or sync the individual Pi-hole's upstream DNS resolvers.
- Merge query logs, statistics, long-term data, caches, or other resolution information.
- Sync individual Pi-hole DHCP scoping information or leases.
## Setup Steps
1. [Review System Requirements](https://github.com/vmstan/gravity-sync/wiki/System-Requirements)
2. [Prepare Your Pi-hole](https://github.com/vmstan/gravity-sync/wiki/Installing#primary-pi-hole)
3. [Install Gravity Sync](https://github.com/vmstan/gravity-sync/wiki/Installing#secondary-pi-hole) (or [Upgrade](https://github.com/vmstan/gravity-sync/wiki/Updating))
4. [Configure Gravity Sync](https://github.com/vmstan/gravity-sync/wiki/Installing#configuration)
5. [Execute Gravity Sync](https://github.com/vmstan/gravity-sync/wiki/Installing#execution)
6. [Automate Gravity Sync](https://github.com/vmstan/gravity-sync/wiki/Installing#automation)
7. [Profit](https://memory-alpha.fandom.com/wiki/Rules_of_Acquisition)
2. [Install Gravity Sync](https://github.com/vmstan/gravity-sync/wiki/Installing)
3. [Configure Gravity Sync](https://github.com/vmstan/gravity-sync/wiki/Installing#configuration)
4. [Execute Gravity Sync](https://github.com/vmstan/gravity-sync/wiki/Engaging)
5. [Automate Gravity Sync](https://github.com/vmstan/gravity-sync/wiki/Automation)
## Disclaimer
@ -57,5 +59,4 @@ Pi-hole is and the Pi-hole logo are [registered trademarks](https://pi-hole.net/
Please refer to the [Wiki](https://github.com/vmstan/gravity-sync/wiki) for more information:
- [Frequently Asked Questions](https://github.com/vmstan/gravity-sync/wiki/Frequent-Questions)
- [Advanced Installation Options](https://github.com/vmstan/gravity-sync/wiki/Under-The-Covers)
- [Changelog](https://github.com/vmstan/gravity-sync/wiki/Changelog)
- [Changelog](https://github.com/vmstan/gravity-sync/wiki/Changelog)

View File

@ -1 +1 @@
3.4.7
4.0.7

View File

@ -1,5 +0,0 @@
Your backup files will be stored here.
They will be ignored by any git updates.
This file is required for Git to create the folder.
It serves no other purpose.
Live long and prosper.

2501
gravity-sync Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,202 +1,454 @@
#!/bin/bash
SCRIPT_START=$SECONDS
#!/usr/bin/env bash
# GRAVITY SYNC BY VMSTAN #####################
# GS 3.x to 4.0 Upgrade Utility ##############
# Run only to upgrade your existing Gravity Sync 3.x installation to 4.0 format
PROGRAM='Gravity Sync'
VERSION='3.4.7'
# For documentation or downloading updates visit https://github.com/vmstan/gravity-sync
# Requires Pi-Hole 5.x or higher already be installed, for help visit https://pi-hole.net
GS_FILEPATH=$(realpath $0)
LOCAL_FOLDR=$(dirname $GS_FILEPATH)
# REQUIRED SETTINGS ##########################
GS_ETC_PATH="/etc/gravity-sync"
GS_GRAVITY_FI_MD5_LOG='gs-gravity.md5'
GS_CUSTOM_DNS_MD5_LOG='gs-clist.md5'
GS_CNAME_CONF_MD5_LOG='05-pihole-custom-cname.conf.md5'
# Run './gravity-sync.sh config' to get started, it will customize the script for your environment
# You should not to change the values of any variables here here to customize your install
# Add replacement variables to gravity-sync.conf, which will overwrite these defaults.
OS_DAEMON_PATH='/etc/systemd/system'
# STANDARD VARIABLES #########################
## 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'
# Installation Types
PH_IN_TYPE='default' # Pi-hole install type, `default`, `docker`, or `podman` (local)
RH_IN_TYPE='default' # Pi-hole install type, `default`, `docker`, or `podman` (remote)
## Message Codes
FAIL="${RED}${NC}"
WARN="${PURPLE}!${NC}"
GOOD="${GREEN}${NC}"
STAT="${CYAN}${NC}"
INFO="${YELLOW}»${NC}"
INF1="${CYAN}${NC}"
NEED="${BLUE}?${NC}"
LOGO="${PURPLE}${NC}"
# Pi-hole Folder/File Customization
PIHOLE_DIR='/etc/pihole' # default Pi-hole data directory (local)
RIHOLE_DIR='/etc/pihole' # default Pi-hole data directory (remote)
DNSMAQ_DIR='/etc/dnsmasq.d' # default DNSMASQ data directory (local)
RNSMAQ_DIR='/etc/dnsmasq.d' # default DNSMASQ data directory (remote)
PIHOLE_BIN='/usr/local/bin/pihole' # default Pi-hole binary directory (local)
RIHOLE_BIN='/usr/local/bin/pihole' # default Pi-hole binary directory (remote)
DOCKER_BIN='/usr/bin/docker' # default Docker binary directory (local)
ROCKER_BIN='/usr/bin/docker' # default Docker binary directory (remote)
PODMAN_BIN='/usr/bin/podman' # default Podman binary directory (local)
RODMAN_BIN='/usr/bin/podman' # default Podman binary directory (remote)
FILE_OWNER='pihole:pihole' # default Pi-hole file owner and group (local)
RILE_OWNER='pihole:pihole' # default Pi-hole file owner and group (remote)
DOCKER_CON='pihole' # default Pi-hole container name (local)
ROCKER_CON='pihole' # default Pi-hole container name (remote)
CONTAIMAGE='pihole/pihole' # official Pi-hole container image
## Echo Stack
### Informative
function echo_info {
echo -e "${INFO} ${YELLOW}${MESSAGE}${NC}"
}
GRAVITY_FI='gravity.db' # default Pi-hole database file
CUSTOM_DNS='custom.list' # default Pi-hole local DNS lookups
CNAME_CONF='05-pihole-custom-cname.conf' # default DNSMASQ CNAME alias file
GSLAN_CONF='08-gs-lan.conf' # default DNSMASQ GS managed file
function echo_prompt {
echo -e "${INF1} ${CYAN}${MESSAGE}${NC}"
}
# Interaction Customization
VERIFY_PASS='0' # replace in gravity-sync.conf to overwrite
SKIP_CUSTOM='0' # replace in gravity-sync.conf to overwrite
INCLUDE_CNAME='0' # replace in gravity-sync.conf to overwrite
DATE_OUTPUT='0' # replace in gravity-sync.conf to overwrite
PING_AVOID='0' # replace in gravity-sync.conf to overwrite
ROOT_CHECK_AVOID='0' # replace in gravity-sync.conf to overwrite
### Warning
function echo_warn {
echo -e "${WARN} ${PURPLE}${MESSAGE}${NC}"
}
# Backup Customization
BACKUP_RETAIN='3' # replace in gravity-sync.conf to overwrite
BACKUP_TIMEOUT='240' # replace in gravity-sync.conf to overwrite
BACKUP_INTEGRITY_WAIT='5' # replace in gravity-sync.conf to overwrite
### Executing
function echo_stat {
echo -en "${STAT} ${MESSAGE}"
}
# SSH Customization
SSH_PORT='22' # default SSH port
SSH_PKIF='.ssh/id_rsa' # default local SSH key
### Success
function echo_good {
echo -e "\r${GOOD} ${MESSAGE}"
}
# GS Folder/File Locations
GS_FILEPATH=$(realpath $0) # auto determined - do not change!
LOCAL_FOLDR=$(dirname $GS_FILEPATH) # auto determined - do not change!
CONFIG_FILE='gravity-sync.conf' # must exist with primary host/user configured
GS_FILENAME='gravity-sync.sh' # must exist because it's this script
BACKUP_FOLD='backup' # must exist as subdirectory in LOCAL_FOLDR
LOG_PATH="${LOCAL_FOLDR}/logs" # replace in gravity-sync.conf to overwrite
SYNCING_LOG='gravity-sync.log' # replace in gravity-sync.conf to overwrite
CRONJOB_LOG='gravity-sync.cron' # replace in gravity-sync.conf to overwrite
HISTORY_MD5='gravity-sync.md5' # replace in gravity-sync.conf to overwrite
### Success
function echo_good_clean {
echo -e "\r${GOOD} ${MESSAGE}"
}
# OS Settings
BASH_PATH='/bin/bash' # default OS bash path
### Failure
function echo_fail {
echo -e "\r${FAIL} ${MESSAGE}"
}
##############################################
### NEVER CHANGE ANYTHING BELOW THIS LINE! ###
##############################################
### Request
function echo_need {
echo -en "${NEED} ${BOLD}${MESSAGE}:${NC} "
}
# Import UI Fields
source ${LOCAL_FOLDR}/includes/gs-ui.sh
### Indent
function echo_over {
echo -e " ${MESSAGE}"
}
# Import Color/Message Includes
source ${LOCAL_FOLDR}/includes/gs-colors.sh
### Gravity Sync Logo
function echo_grav {
echo -e "${LOGO} ${BOLD}${MESSAGE}${NC}"
}
# FUNCTION DEFINITIONS #######################
### Lines
function echo_blank {
echo -e ""
}
# Core Functions
source ${LOCAL_FOLDR}/includes/gs-core.sh
## Error Validation
function error_validate {
if [ "$?" != "0" ]; then
echo_fail
exit 1
else
echo_good
fi
}
# Gravity Replication Functions
source ${LOCAL_FOLDR}/includes/gs-pull.sh
source ${LOCAL_FOLDR}/includes/gs-push.sh
source ${LOCAL_FOLDR}/includes/gs-smart.sh
source ${LOCAL_FOLDR}/includes/gs-restore.sh
source ${LOCAL_FOLDR}/includes/gs-backup.sh
function start_gs_no_config {
MESSAGE="Gravity Sync 3.x to 4.0 Migration Utility"
echo_grav
}
# Hashing & SSH Functions
source ${LOCAL_FOLDR}/includes/gs-hashing.sh
source ${LOCAL_FOLDR}/includes/gs-ssh.sh
function check_old_version {
MESSAGE="Checking for 3.x Configuration File"
echo_stat
# Logging Functions
source ${LOCAL_FOLDR}/includes/gs-logging.sh
if [ -f settings/gravity-sync.conf ]; then
echo_good
else
echo_fail
exit 1
fi
# Validation Functions
source ${LOCAL_FOLDR}/includes/gs-validate.sh
source ${LOCAL_FOLDR}/includes/gs-intent.sh
source ${LOCAL_FOLDR}/includes/gs-root.sh
}
# Configuration Management
source ${LOCAL_FOLDR}/includes/gs-config.sh
source ${LOCAL_FOLDR}/includes/gs-update.sh
source ${LOCAL_FOLDR}/includes/gs-automate.sh
source ${LOCAL_FOLDR}/includes/gs-purge.sh
function install_new_gravity {
MESSAGE="Installing Gravity Sync 4.0"
echo_info
# Exit Codes
source ${LOCAL_FOLDR}/includes/gs-exit.sh
if [ -d /etc/gravity-sync/.gs ]; then
MESSAGE="Removing existing GitHub cache"
echo_stat
sudo rm -fr /etc/gravity-sync/.gs
error_validate
fi
if [ ! -d /etc/gravity-sync ]; then
MESSAGE="Creating new configuration directory"
echo_stat
sudo mkdir /etc/gravity-sync
error_validate
fi
MESSAGE="Validating configuration directory permissions"
echo_stat
sudo chmod 775 /etc/gravity-sync
error_validate
if [ -f /usr/local/bin/gravity-sync ]; then
MESSAGE="Removing old Gravity Sync binary"
echo_stat
sudo rm -f /usr/local/bin/gravity-sync
error_validate
fi
MESSAGE="Creating new GitHub cache"
echo_prompt
sudo git clone https://github.com/vmstan/gravity-sync.git /etc/gravity-sync/.gs
# MESSAGE="Enabling beta updates"
# echo_stat
# sudo touch /etc/gravity-sync/.gs/dev
# echo -e "BRANCH='origin/4.0.0'" | sudo tee /etc/gravity-sync/.gs/dev 1> /dev/null
# error_validate
sudo cp /etc/gravity-sync/.gs/gravity-sync /usr/local/bin
}
function upgrade_to_4 {
MESSAGE="Migrating Previous Configuration"
echo_info
REMOTE_HOST=''
REMOTE_USER=''
PIHOLE_DIR=''
RIHOLE_DIR=''
DNSMAQ_DIR=''
RNSMAQ_DIR=''
FILE_OWNER=''
RILE_OWNER=''
DOCKER_CON=''
ROCKER_CON=''
SSH_PORT=''
SSH_PKIF=''
MESSAGE="Reviewing old configuration file settings"
echo_stat
source settings/gravity-sync.conf
error_validate
MESSAGE="Creating new configuration file from template"
echo_stat
sudo cp /etc/gravity-sync/.gs/templates/gravity-sync.conf.example /etc/gravity-sync/gravity-sync.conf
error_validate
LOCAL_PIHOLE_DIRECTORY=${PIHOLE_DIR}
REMOTE_PIHOLE_DIRECTORY=${RIHOLE_DIR}
LOCAL_DNSMASQ_DIRECTORY=${DNSMAQ_DIR}
REMOTE_DNSMASQ_DIRECTORY=${RNSMAQ_DIR}
LOCAL_FILE_OWNER=${FILE_OWNER}
REMOTE_FILE_OWNER=${RILE_OWNER}
LOCAL_DOCKER_CONTAINER=${DOCKER_CON}
REMOTE_DOCKER_CONTAINER=${ROCKER_CON}
CURRENTUSER=$(whoami)
MESSAGE="Transferring SSH keys"
echo_stat
if [ "${SSH_PKIF}" == "" ]; then
sudo cp $HOME/.ssh/id_rsa /etc/gravity-sync/gravity-sync.rsa
sudo cp $HOME/.ssh/id_rsa.pub /etc/gravity-sync/gravity-sync.rsa.pub
else
sudo cp ${SSH_PKIF} /etc/gravity-sync/gravity-sync.rsa
sudo cp ${SSH_PKIF}.pub /etc/gravity-sync/gravity-sync.rsa.pub
fi
error_validate
MESSAGE="Setting SSH key owner"
echo_stat
sudo chown ${CURRENTUSER}:${CURRENTUSER} /etc/gravity-sync/gravity-sync.rsa
sudo chown ${CURRENTUSER}:${CURRENTUSER} /etc/gravity-sync/gravity-sync.rsa.pub
error_validate
MESSAGE="Migrating remote host settings"
echo_stat
sudo sed -i "/REMOTE_HOST=''/c\REMOTE_HOST='${REMOTE_HOST}'" /etc/gravity-sync/gravity-sync.conf
error_validate
MESSAGE="Migrating remote user settings"
echo_stat
sudo sed -i "/REMOTE_USER=''/c\REMOTE_USER='${REMOTE_USER}'" /etc/gravity-sync/gravity-sync.conf
error_validate
if [ "${SSH_PORT}" != "" ]; then
GS_SSH_PORT=${SSH_PORT}
MESSAGE="Migrating target host SSH settings"
echo_stat
echo -e "GS_SSH_PORT='${GS_SSH_PORT}" | sudo tee -a /etc/gravity-sync/gravity-sync.conf 1> /dev/null
error_validate
fi
if [ "${LOCAL_PIHOLE_DIRECTORY}" == '' ] || [ "${LOCAL_PIHOLE_DIRECTORY}" == '/etc/pihole' ]; then
MESSAGE="Defaulting local Pi-hole directory setting"
echo_good_clean
else
MESSAGE="Migrating local Pi-hole directory setting"
echo_stat
sudo sed -i "/LOCAL_PIHOLE_DIRECTORY=''/c\LOCAL_PIHOLE_DIRECTORY='${LOCAL_PIHOLE_DIRECTORY}'" /etc/gravity-sync/gravity-sync.conf
error_validate
fi
if [ "${REMOTE_PIHOLE_DIRECTORY}" == '' ] || [ "${REMOTE_PIHOLE_DIRECTORY}" == '/etc/pihole' ]; then
MESSAGE="Defaulting remote Pi-hole directory setting"
echo_good_clean
else
MESSAGE="Migrating remote Pi-hole directory setting"
echo_stat
sudo sed -i "/REMOTE_PIHOLE_DIRECTORY=''/c\REMOTE_PIHOLE_DIRECTORY='${REMOTE_PIHOLE_DIRECTORY}'" /etc/gravity-sync/gravity-sync.conf
error_validate
fi
if [ "${LOCAL_DNSMASQ_DIRECTORY}" == '' ] || [ "${LOCAL_DNSMASQ_DIRECTORY}" == '/etc/dnsmasq.d' ]; then
MESSAGE="Defaulting local DNSMASQ directory setting"
echo_good_clean
else
MESSAGE="Migrating local DNSMASQ directory setting"
echo_stat
sudo sed -i "/LOCAL_DNSMASQ_DIRECTORY=''/c\LOCAL_DNSMASQ_DIRECTORY='${LOCAL_DNSMASQ_DIRECTORY}'" /etc/gravity-sync/gravity-sync.conf
error_validate
fi
if [ "${REMOTE_DNSMASQ_DIRECTORY}" == '' ] || [ "${REMOTE_DNSMASQ_DIRECTORY}" == '/etc/dnsmasq.d' ]; then
MESSAGE="Defaulting remote DNSMASQ directory setting"
echo_good_clean
else
MESSAGE="Migrating remote DNSMASQ directory setting"
echo_stat
sudo sed -i "/REMOTE_DNSMASQ_DIRECTORY=''/c\REMOTE_DNSMASQ_DIRECTORY='${REMOTE_DNSMASQ_DIRECTORY}'" /etc/gravity-sync/gravity-sync.conf
error_validate
fi
if [ "${LOCAL_FILE_OWNER}" == '' ]; then
MESSAGE="Defaulting local file owner setting"
echo_good_clean
else
MESSAGE="Migrating local file owner setting"
echo_stat
sudo sed -i "/LOCAL_FILE_OWNER=''/c\LOCAL_FILE_OWNER='${LOCAL_FILE_OWNER}'" /etc/gravity-sync/gravity-sync.conf
error_validate
fi
if [ "${REMOTE_FILE_OWNER}" == '' ]; then
MESSAGE="Defaulting remote file owner setting"
echo_good_clean
else
MESSAGE="Migrating remote file owner setting"
echo_stat
sudo sed -i "/REMOTE_FILE_OWNER=''/c\REMOTE_FILE_OWNER='${REMOTE_FILE_OWNER}'" /etc/gravity-sync/gravity-sync.conf
error_validate
fi
if [ "${LOCAL_DOCKER_CONTAINER}" == '' ] || [ "${LOCAL_DOCKER_CONTAINER}" == 'pihole' ]; then
MESSAGE="Defaulting local Pi-hole container setting"
echo_good_clean
else
MESSAGE="Migrating local Pi-hole container setting"
echo_stat
sudo sed -i "/LOCAL_DOCKER_CONTAINER=''/c\LOCAL_DOCKER_CONTAINER='${LOCAL_DOCKER_CONTAINER}'" /etc/gravity-sync/gravity-sync.conf
error_validate
fi
if [ "${REMOTE_DOCKER_CONTAINER}" == '' ] || [ "${REMOTE_DOCKER_CONTAINER}" == 'pihole' ]; then
MESSAGE="Defaulting remote Pi-hole container setting"
echo_good_clean
else
MESSAGE="Migrating local Pi-hole container setting"
echo_stat
sudo sed -i "/REMOTE_DOCKER_CONTAINER=''/c\REMOTE_DOCKER_CONTAINER='${REMOTE_DOCKER_CONTAINER}'" /etc/gravity-sync/gravity-sync.conf
error_validate
fi
MESSAGE="Migrating task history"
echo_stat
sudo cp logs/gravity-sync.log /etc/gravity-sync/gs-sync.log
error_validate
MESSAGE="Migrating hashing tables"
echo_stat
if [ -f "logs/gravity-sync.md5" ]; then
REMOTE_DB_MD5=$(sed "1q;d" logs/gravity-sync.md5)
LOCAL_DB_MD5=$(sed "2q;d" logs/gravity-sync.md5)
REMOTE_CL_MD5=$(sed "3q;d" logs/gravity-sync.md5)
LOCAL_CL_MD5=$(sed "4q;d" logs/gravity-sync.md5)
REMOTE_CN_MD5=$(sed "5q;d" logs/gravity-sync.md5)
LOCAL_CN_MD5=$(sed "6q;d" logs/gravity-sync.md5)
echo -e ${REMOTE_DB_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_GRAVITY_FI_MD5_LOG} 1> /dev/null
echo -e ${LOCAL_DB_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_GRAVITY_FI_MD5_LOG} 1> /dev/null
echo -e ${REMOTE_CL_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_CUSTOM_DNS_MD5_LOG} 1> /dev/null
echo -e ${LOCAL_CL_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_CUSTOM_DNS_MD5_LOG} 1> /dev/null
echo -e ${REMOTE_CN_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_CNAME_CONF_MD5_LOG} 1> /dev/null
echo -e ${LOCAL_CN_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_CNAME_CONF_MD5_LOG} 1> /dev/null
else
REMOTE_DB_MD5="0"
LOCAL_DB_MD5="0"
REMOTE_CL_MD5="0"
LOCAL_CL_MD5="0"
REMOTE_CN_MD5="0"
LOCAL_CN_MD5="0"
echo -e ${REMOTE_DB_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_GRAVITY_FI_MD5_LOG} 1> /dev/null
echo -e ${LOCAL_DB_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_GRAVITY_FI_MD5_LOG} 1> /dev/null
echo -e ${REMOTE_CL_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_CUSTOM_DNS_MD5_LOG} 1> /dev/null
echo -e ${LOCAL_CL_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_CUSTOM_DNS_MD5_LOG} 1> /dev/null
echo -e ${REMOTE_CN_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_CNAME_CONF_MD5_LOG} 1> /dev/null
echo -e ${LOCAL_CN_MD5} | sudo tee -a ${GS_ETC_PATH}/${GS_CNAME_CONF_MD5_LOG} 1> /dev/null
fi
error_validate
}
function remove_old_version {
MESSAGE="Removing Old Version & Settings"
echo_info
if hash crontab 2>/dev/null; then
MESSAGE="Clearing automation from crontab"
echo_stat
crontab -l > cronjob-old.tmp
sed "/gravity-sync.sh/d" cronjob-old.tmp > cronjob-new.tmp
crontab cronjob-new.tmp
error_validate
fi
kill_automation_service
if [ -f /etc/bash.bashrc ]; then
MESSAGE="Cleaning up bash.bashrc"
echo_info
sudo sed -i "/gravity-sync.sh/d" /etc/bash.bashrc
error_validate
fi
MESSAGE="Removing old Gravity Sync folder"
echo_stat
sudo rm -fr ${LOCAL_FOLDR}
error_validate
}
function kill_automation_service {
if systemctl is-active --quiet gravity-sync.timer; then
MESSAGE="Stopping ${PROGRAM} timer"
echo_stat
sudo systemctl stop gravity-sync
error_validate
MESSAGE="Disabling ${PROGRAM} automation service"
echo_stat
sudo systemctl disable gravity-sync --quiet
error_validate
MESSAGE="Removing systemd timer"
echo_stat
sudo rm -f ${OS_DAEMON_PATH}/gravity-sync.timer
error_validate
MESSAGE="Removing systemd service"
echo_stat
sudo rm -f ${OS_DAEMON_PATH}/gravity-sync.service
error_validate
MESSAGE="Reloading systemd daemon"
echo_stat
sudo systemctl daemon-reload --quiet
error_validate
fi
}
function end_migration {
MESSAGE="Migration Complete"
echo_info
}
# SCRIPT EXECUTION ###########################
case $# in
0)
start_gs
task_smart ;;
start_gs_no_config
check_old_version
install_new_gravity
upgrade_to_4
remove_old_version
end_migration ;;
1)
case $1 in
smart|sync)
start_gs
task_smart ;;
pull)
start_gs
task_pull ;;
push)
start_gs
task_push ;;
restore)
start_gs
task_restore ;;
version)
start_gs_noconfig
task_version ;;
update|upgrade)
start_gs_noconfig
task_update ;;
dev|devmode|development|develop)
start_gs_noconfig
task_devmode ;;
logs|log)
start_gs
task_logs ;;
compare)
start_gs
task_compare ;;
cron)
start_gs
task_cron ;;
config|configure)
start_gs_noconfig
task_configure ;;
auto|automate)
start_gs
task_automate ;;
backup)
start_gs
task_backup ;;
purge)
start_gs
task_purge ;;
sudo)
start_gs
task_sudo ;;
info)
start_gs
task_info ;;
*)
start_gs
task_invalid ;;
esac
;;
2)
case $1 in
auto|automate)
start_gs
task_automate ;;
esac
;;
3)
case $1 in
auto|automate)
start_gs
task_automate $2 ;;
start_gs_no_config
check_old_version
install_new_gravity
upgrade_to_4
remove_old_version
end_migration ;;
esac
;;
*)
start_gs
task_invalid ;;
start_gs_no_config
check_old_version
install_new_gravity
upgrade_to_4
remove_old_version
end_migration ;;
esac
# END OF SCRIPT ##############################

88
images/gs-logo.svg Normal file
View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="406px" height="180px" viewBox="0 0 406 180" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<!-- Generated by Pixelmator Pro 2.0.5 -->
<path id="Rounded-Rectangle-copy-3" d="M96.934 82.929 C93.029 86.834 93.029 93.166 96.934 97.071 L146.431 146.569 C150.337 150.474 156.668 150.474 160.574 146.569 L210.071 97.071 C213.976 93.166 213.976 86.834 210.071 82.929 L160.574 33.431 C156.668 29.526 150.337 29.526 146.431 33.431 Z" fill="#00a2ff" fill-opacity="1" stroke="none"/>
<defs>
<linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x1="1.648" y1="84.65" x2="180.328" y2="88.78">
<stop offset="0" stop-color="#0ec9b0" stop-opacity="1"/>
<stop offset="1" stop-color="#22a5fb" stop-opacity="1"/>
</linearGradient>
</defs>
<path id="Ellipse-copy-3" d="M153.503 26.36 C118.355 -8.787 61.37 -8.787 26.223 26.36 -8.924 61.508 -8.924 118.492 26.223 153.64 61.37 188.787 118.355 188.787 153.503 153.64 188.65 118.492 188.65 61.508 153.503 26.36 Z" fill-opacity="1" fill="url(#linear-gradient)" stroke="none"/>
<g id="New-Group-copy-5">
<path id="Rounded-Rectangle-copy-1" d="M96.934 82.929 C93.029 86.834 93.029 93.166 96.934 97.071 L146.431 146.569 C150.337 150.474 156.668 150.474 160.574 146.569 L210.071 97.071 C213.976 93.166 213.976 86.834 210.071 82.929 L160.574 33.431 C156.668 29.526 150.337 29.526 146.431 33.431 Z" fill="#00a2ff" fill-opacity="1" stroke="none"/>
<defs>
<linearGradient id="linear-gradient-1" gradientUnits="userSpaceOnUse" x1="1.648" y1="84.65" x2="180.328" y2="88.78">
<stop offset="0" stop-color="#0ec9b0" stop-opacity="1"/>
<stop offset="1" stop-color="#22a5fb" stop-opacity="1"/>
</linearGradient>
</defs>
<path id="Ellipse-copy" d="M153.503 26.36 C118.355 -8.787 61.37 -8.787 26.223 26.36 -8.924 61.508 -8.924 118.492 26.223 153.64 61.37 188.787 118.355 188.787 153.503 153.64 188.65 118.492 188.65 61.508 153.503 26.36 Z" fill-opacity="1" fill="url(#linear-gradient-1)" stroke="none"/>
</g>
<path id="Rounded-Rectangle-copy" d="M96.934 82.929 C93.029 86.834 93.029 93.166 96.934 97.071 L132.289 132.426 C136.195 136.332 142.526 136.332 146.431 132.426 L181.787 97.071 C185.692 93.166 185.692 86.834 181.787 82.929 L146.431 47.574 C142.526 43.668 136.195 43.668 132.289 47.574 Z" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Ellipse-copy-2" d="M139.36 40.503 C112.024 13.166 67.702 13.166 40.365 40.503 13.029 67.839 13.029 112.161 40.365 139.497 67.702 166.834 112.024 166.834 139.36 139.497 166.697 112.161 166.697 67.839 139.36 40.503 Z" fill="#ffffff" fill-opacity="1" stroke="none"/>
<g id="New-Group-copy-4">
<path id="Path" d="M96.934 82.929 C93.029 86.834 93.029 93.166 96.934 97.071 L132.289 132.426 C136.195 136.332 142.526 136.332 146.431 132.426 L181.787 97.071 C185.692 93.166 185.692 86.834 181.787 82.929 L146.431 47.574 C142.526 43.668 136.195 43.668 132.289 47.574 Z" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Path-1" d="M139.36 40.503 C112.024 13.166 67.702 13.166 40.365 40.503 13.029 67.839 13.029 112.161 40.365 139.497 67.702 166.834 112.024 166.834 139.36 139.497 166.697 112.161 166.697 67.839 139.36 40.503 Z" fill="#ffffff" fill-opacity="1" stroke="none"/>
</g>
<path id="Rounded-Rectangle-copy-2" d="M309.066 97.071 C312.971 93.166 312.971 86.834 309.066 82.929 L259.569 33.431 C255.663 29.526 249.332 29.526 245.426 33.431 L195.929 82.929 C192.024 86.834 192.024 93.166 195.929 97.071 L245.426 146.569 C249.332 150.474 255.663 150.474 259.569 146.569 Z" fill="#00a2ff" fill-opacity="1" stroke="none"/>
<defs>
<linearGradient id="linear-gradient-2" gradientUnits="userSpaceOnUse" x1="283.044" y1="86.126" x2="405.807" y2="89.926">
<stop offset="0" stop-color="#21a9ff" stop-opacity="1"/>
<stop offset="1" stop-color="#fa3ebe" stop-opacity="1"/>
</linearGradient>
</defs>
<path id="Ellipse-copy-1" d="M252.497 153.64 C287.645 188.787 344.63 188.787 379.777 153.64 414.924 118.492 414.924 61.508 379.777 26.36 344.63 -8.787 287.645 -8.787 252.497 26.36 217.35 61.508 217.35 118.492 252.497 153.64 Z" fill-opacity="1" fill="url(#linear-gradient-2)" stroke="none"/>
<g id="New-Group-copy-2">
<path id="Rounded-Rectangle-copy-1-1" d="M309.066 97.071 C312.971 93.166 312.971 86.834 309.066 82.929 L259.569 33.431 C255.663 29.526 249.332 29.526 245.426 33.431 L195.929 82.929 C192.024 86.834 192.024 93.166 195.929 97.071 L245.426 146.569 C249.332 150.474 255.663 150.474 259.569 146.569 Z" fill="#00a2ff" fill-opacity="1" stroke="none"/>
<defs>
<linearGradient id="linear-gradient-3" gradientUnits="userSpaceOnUse" x1="283.044" y1="86.126" x2="405.807" y2="89.926">
<stop offset="0" stop-color="#21a9ff" stop-opacity="1"/>
<stop offset="1" stop-color="#fa3ebe" stop-opacity="1"/>
</linearGradient>
</defs>
<path id="Ellipse-copy-1" d="M252.497 153.64 C287.645 188.787 344.63 188.787 379.777 153.64 414.924 118.492 414.924 61.508 379.777 26.36 344.63 -8.787 287.645 -8.787 252.497 26.36 217.35 61.508 217.35 118.492 252.497 153.64 Z" fill-opacity="1" fill="url(#linear-gradient-3)" stroke="none"/>
</g>
<g id="New-Group-copy-1">
<path id="Path-2" d="M309.066 97.071 C312.971 93.166 312.971 86.834 309.066 82.929 L273.711 47.574 C269.805 43.668 263.474 43.668 259.569 47.574 L224.213 82.929 C220.308 86.834 220.308 93.166 224.213 97.071 L259.569 132.426 C263.474 136.332 269.805 136.332 273.711 132.426 Z" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Path-3" d="M266.64 139.497 C293.976 166.834 338.298 166.834 365.635 139.497 392.971 112.161 392.971 67.839 365.635 40.503 338.298 13.166 293.976 13.166 266.64 40.503 239.303 67.839 239.303 112.161 266.64 139.497 Z" fill="#ffffff" fill-opacity="1" stroke="none"/>
</g>
<defs>
<linearGradient id="linear-gradient-4" gradientUnits="userSpaceOnUse" x1="217.142" y1="75.858" x2="259.569" y2="33.431">
<stop offset="0" stop-color="#00a2ff" stop-opacity="1"/>
<stop offset="1" stop-color="#003758" stop-opacity="1"/>
</linearGradient>
</defs>
<path id="Rectangle-copy" d="M224.213 82.929 L266.64 40.503 252.497 26.36 210.071 68.787 Z" fill-opacity="1" fill="url(#linear-gradient-4)" stroke="none"/>
<path id="Ellipse-copy-2" d="M267.347 25.653 C263.441 21.748 257.11 21.748 253.205 25.653 249.299 29.559 249.299 35.89 253.205 39.795 257.11 43.701 263.441 43.701 267.347 39.795 271.252 35.89 271.252 29.559 267.347 25.653 Z" fill="#003758" fill-opacity="1" stroke="none"/>
<g id="New-Group">
<defs>
<radialGradient id="radial-gradient" gradientUnits="userSpaceOnUse" cx="89.863" cy="89.707" r="70" fx="89.863" fy="89.707">
<stop offset="0" stop-color="#fdbe2e" stop-opacity="1"/>
<stop offset="1" stop-color="#fe594d" stop-opacity="1"/>
</radialGradient>
</defs>
<path id="Path-4" d="M139.153 138.997 L139.36 40.209 40.573 40.417 40.365 139.204 Z" fill-opacity="1" fill="url(#radial-gradient)" stroke="none"/>
<g id="New-Group-1">
<path id="Path-copy-3" d="M40.791 40.198 C42.655 38.558 59.617 22.823 78.978 40.198 90.941 50.554 90.349 67.616 101.174 78.441 130.199 103.448 163.051 63.9 139.383 40.232 133.482 34.301 125.463 30.964 117.097 30.958 L63.143 30.947 C54.777 30.958 46.758 34.289 40.847 40.209" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Path-copy-2" d="M40.814 138.778 C39.162 136.926 23.439 119.953 40.814 100.592 51.158 88.618 68.209 89.22 79.045 78.385 104.064 49.371 64.527 16.529 40.858 40.198 34.925 46.096 31.588 54.117 31.585 62.483 L31.563 116.449 C31.569 124.82 34.91 132.843 40.847 138.745" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Path-copy-1" d="M139.371 138.778 C137.519 140.43 120.546 156.153 101.185 138.778 89.211 128.434 89.802 111.371 78.978 100.547 49.964 75.528 17.123 115.065 40.791 138.734 46.692 144.664 54.711 148.001 63.077 148.007 L117.053 148.018 C125.417 148.002 133.432 144.666 139.338 138.745" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Path-copy" d="M139.282 40.31 C140.934 42.162 156.657 59.135 139.282 78.496 128.926 90.459 111.875 89.856 101.04 100.692 76.032 129.717 115.569 162.558 139.238 138.89 145.171 132.991 148.508 124.971 148.511 116.605 L148.522 62.628 C148.516 54.262 145.179 46.244 139.249 40.343" fill="#ffffff" fill-opacity="1" stroke="none"/>
</g>
</g>
<g id="New-Group-copy">
<defs>
<radialGradient id="radial-gradient-1" gradientUnits="userSpaceOnUse" cx="317.138" cy="89.293" r="70" fx="317.138" fy="89.293">
<stop offset="0" stop-color="#fdbe2e" stop-opacity="1"/>
<stop offset="1" stop-color="#fe594d" stop-opacity="1"/>
</radialGradient>
</defs>
<path id="Path-5" d="M267.847 40.003 L267.64 138.79 366.428 138.583 366.635 39.795 Z" fill-opacity="1" fill="url(#radial-gradient-1)" stroke="none"/>
<g id="New-Group-2">
<path id="Path-copy-3-1" d="M366.209 138.801 C364.346 140.442 347.384 156.176 328.022 138.801 316.06 128.446 316.651 111.383 305.827 100.559 276.802 75.551 243.949 115.099 267.618 138.768 273.519 144.699 281.538 148.035 289.903 148.041 L343.857 148.052 C352.223 148.042 360.242 144.71 366.153 138.79" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Path-copy-2-1" d="M366.187 40.221 C367.838 42.074 383.562 59.047 366.187 78.408 355.842 90.382 338.791 89.779 327.955 100.615 302.937 129.629 342.474 162.47 366.142 138.801 372.075 132.903 375.413 124.883 375.415 116.517 L375.438 62.551 C375.432 54.18 372.09 46.156 366.153 40.255" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Path-copy-1-1" d="M267.629 40.221 C269.481 38.57 286.454 22.847 305.816 40.221 317.789 50.566 317.198 67.628 328.022 78.453 357.036 103.472 389.878 63.935 366.209 40.266 360.308 34.335 352.289 30.999 343.924 30.993 L289.947 30.982 C281.584 30.998 273.569 34.333 267.662 40.255" fill="#ffffff" fill-opacity="1" stroke="none"/>
<path id="Path-copy-1" d="M267.718 138.69 C266.067 136.837 250.343 119.864 267.718 100.503 278.074 88.541 295.125 89.143 305.961 78.308 330.968 49.283 291.431 16.441 267.763 40.11 261.83 46.008 258.492 54.028 258.49 62.395 L258.478 116.372 C258.485 124.737 261.821 132.756 267.752 138.656" fill="#ffffff" fill-opacity="1" stroke="none"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,91 +0,0 @@
# 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}"
echo_good
CRON_EXIST='0'
CRON_CHECK=$(crontab -l | grep -q "${GS_FILENAME}" && echo '1' || echo '0')
if [ ${CRON_CHECK} == 1 ]
then
MESSAGE="${UI_AUTO_CRON_EXISTS}"
echo_warn
CRON_EXIST='1'
fi
MESSAGE="${UI_AUTO_CRON_DISPLAY_FREQ}"
echo_info
if [[ $1 =~ ^[0-9][0-9]?$ ]]
then
INPUT_AUTO_FREQ=$1
else
MESSAGE="${UI_AUTO_CRON_SELECT_FREQ}"
echo_need
read INPUT_AUTO_FREQ
INPUT_AUTO_FREQ="${INPUT_AUTO_FREQ:-15}"
fi
if [ $INPUT_AUTO_FREQ == 5 ] || [ $INPUT_AUTO_FREQ == 10 ] || [ $INPUT_AUTO_FREQ == 15 ] || [ $INPUT_AUTO_FREQ == 30 ]
then
if [ $CRON_EXIST == 1 ]
then
clear_cron
fi
if [[ ${PATH} != *"/usr/sbin"* ]]
then
CRON_ENV_PATH=$'PATH=/bin:/usr/bin:/usr/sbin\n'
else
CRON_ENV_PATH=""
fi
MESSAGE="${UI_AUTO_CRON_SAVING}"
echo_stat
(crontab -l 2>/dev/null; echo "${CRON_ENV_PATH}*/${INPUT_AUTO_FREQ} * * * * ${BASH_PATH} ${LOCAL_FOLDR}/${GS_FILENAME} smart > ${LOG_PATH}/${CRONJOB_LOG}") | crontab -
error_validate
elif [ $INPUT_AUTO_FREQ == 0 ]
then
if [ $CRON_EXIST == 1 ]
then
clear_cron
else
MESSAGE="${UI_AUTO_CRON_DISABLED}"
echo_warn
fi
else
MESSAGE="${UI_INVALID_SELECTION}"
echo_fail
exit_nochange
fi
exit_withchange
}
## Clear Existing Automation Settings
function clear_cron {
MESSAGE="${UI_AUTO_CRON_DISABLED}"
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}"
echo_good
show_crontab
}

View File

@ -1,177 +0,0 @@
# 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}"
echo_good
backup_settime
backup_local_gravity
backup_local_gravity_integrity
backup_local_custom
backup_local_cname
# backup_cleanup
logs_export
exit_withchange
}
function backup_settime() {
BACKUPTIMESTAMP=$(date +%F-%H%M%S)
}
function backup_local_gravity() {
MESSAGE="${UI_BACKUP_SECONDARY} ${UI_GRAVITY_NAME}"
echo_stat
sqlite3 ${PIHOLE_DIR}/${GRAVITY_FI} ".backup '${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${GRAVITY_FI}.backup'"
error_validate
}
function backup_local_gravity_integrity() {
MESSAGE="${UI_BACKUP_INTEGRITY}"
echo_stat
sleep $BACKUP_INTEGRITY_WAIT
secondaryIntegrity=$(sqlite3 ${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${GRAVITY_FI}.backup 'PRAGMA integrity_check;' | sed 's/\s.*$//')
error_validate
if [ "$secondaryIntegrity" != 'ok' ]
then
MESSAGE="${UI_BACKUP_INTEGRITY_FAILED} ${UI_GRAVITY_NAME}"
echo_fail
MESSAGE="${UI_BACKUP_INTEGRITY_DELETE} ${UI_GRAVITY_NAME}"
echo_stat
sudo rm ${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${GRAVITY_FI}.backup
error_validate
exit_nochange
fi
}
function backup_local_custom() {
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ -f ${PIHOLE_DIR}/${CUSTOM_DNS} ]
then
MESSAGE="${UI_BACKUP_SECONDARY} ${UI_CUSTOM_NAME}"
echo_stat
cp ${PIHOLE_DIR}/${CUSTOM_DNS} ${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${CUSTOM_DNS}.backup
error_validate
else
MESSAGE="No local ${CUSTOM_DNS} detected"
echo_info
fi
fi
}
function backup_local_cname() {
if [ "${INCLUDE_CNAME}" == '1' ]
then
if [ -f ${DNSMAQ_DIR}/${CNAME_CONF} ]
then
MESSAGE="${UI_BACKUP_SECONDARY} ${UI_CNAME_NAME}"
echo_stat
cp ${DNSMAQ_DIR}/${CNAME_CONF} ${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${CNAME_CONF}.backup
error_validate
else
MESSAGE="No local ${CNAME_CONF} detected"
echo_info
fi
fi
}
function backup_remote_gravity() {
MESSAGE="${UI_BACKUP_PRIMARY} ${UI_GRAVITY_NAME}"
echo_stat
CMD_TIMEOUT=$BACKUP_TIMEOUT
CMD_REQUESTED="sudo sqlite3 ${RIHOLE_DIR}/${GRAVITY_FI} \".backup '${RIHOLE_DIR}/${GRAVITY_FI}.backup'\""
create_sshcmd
}
function backup_remote_gravity_integrity() {
MESSAGE="${UI_BACKUP_INTEGRITY}"
echo_stat
sleep $BACKUP_INTEGRITY_WAIT
primaryIntegrity=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "sqlite3 ${RIHOLE_DIR}/${GRAVITY_FI}.backup 'PRAGMA integrity_check;'" | sed 's/\s.*$//')
error_validate
if [ "$primaryIntegrity" != 'ok' ]
then
MESSAGE="${UI_BACKUP_INTEGRITY_FAILED} ${UI_GRAVITY_NAME}"
echo_fail
MESSAGE="{UI_BACKUP_INTEGRITY_DELETE} ${UI_GRAVITY_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo rm ${RIHOLE_DIR}/${GRAVITY_FI}.backup"
create_sshcmd
exit_nochange
fi
}
function backup_remote_custom() {
if [ "$SKIP_CUSTOM" != '1' ]
then
MESSAGE="${UI_BACKUP_PRIMARY} ${UI_CUSTOM_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo cp ${RIHOLE_DIR}/${CUSTOM_DNS} ${RIHOLE_DIR}/${CUSTOM_DNS}.backup"
create_sshcmd
fi
}
function backup_remote_cname() {
if [ "$INCLUDE_CNAME" == '1' ]
then
MESSAGE="${UI_BACKUP_PRIMARY} ${UI_CNAME_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo cp ${RNSMAQ_DIR}/${CNAME_CONF} ${RIHOLE_DIR}/dnsmasq.d-${CNAME_CONF}.backup"
create_sshcmd
fi
}
function backup_cleanup() {
MESSAGE="${UI_BACKUP_PURGE}"
echo_stat
rm -f ${LOCAL_FOLDR}/${BACKUP_FOLD}/*.pull
rm -f ${LOCAL_FOLDR}/${BACKUP_FOLD}/*.push
if [ "${TASKTYPE}" != "BACKUP" ]
then
if [ "${BACKUP_RETAIN}" == '0' ]
then
rm -f ${LOCAL_FOLDR}/${BACKUP_FOLD}/*.backup
error_validate
MESSAGE="${UI_BACKUP_DELETE_ALL}"
echo_info
else
find ${LOCAL_FOLDR}/${BACKUP_FOLD}/ -name "*.backup*" -mtime +${BACKUP_RETAIN} -type f -delete
error_validate
BACKUP_FOLDER_SIZE=$(du -h ${LOCAL_FOLDR}/${BACKUP_FOLD} | sed 's/\s.*$//')
MESSAGE="${BACKUP_RETAIN} ${UI_BACKUP_REMAIN} (${BACKUP_FOLDER_SIZE})"
echo_info
fi
fi
}

View File

@ -1,78 +0,0 @@
# 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}]"
LOGO="[${PURPLE}${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}"
}
### Success
function echo_sameline {
echo -en " "
echo -en "\r"
}
### Failure
function echo_fail {
echo -e "\r${FAIL} ${MESSAGE}"
}
### Request
function echo_need {
echo -en "${NEED} ${BOLD}${MESSAGE}:${NC} "
}
### Gravity Sync Logo
function echo_grav {
echo -e "${LOGO} ${BOLD}${MESSAGE}${NC}"
}
### Lines
function echo_lines {
echo -e "========================================================"
}
### Lines
function echo_blank {
echo -e ""
}

View File

@ -1,490 +0,0 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-config.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!
## Configure Task
function task_configure {
TASKTYPE='CONFIGURE'
MESSAGE="${MESSAGE}: ${TASKTYPE}"
echo_good
relocate_config_gs
if [ -f ${LOCAL_FOLDR}/settings/${CONFIG_FILE} ]
then
config_delete
else
config_generate
fi
create_alias
exit_withchange
}
## Generate New Configuration
function config_generate {
MESSAGE="Creating New ${CONFIG_FILE} from Template"
echo_stat
cp ${LOCAL_FOLDR}/templates/${CONFIG_FILE}.example ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
echo_lines
echo -e "Welcome to the ${PURPLE}Gravity Sync${NC} Configuration Wizard"
echo -e "Please read through ${BLUE}https://github.com/vmstan/gravity-sync/wiki${NC} before you continue!"
echo_blank
echo -e "If the installer detects that you have a supported container engine (Docker or Podman) installed,"
echo -e "you will be directed to the advanced installation options. Otherwise you can manually enable this"
echo -e "to adjust settings such as custom Pi-hole binary or configuration directories, SSH options, CNAME"
echo -e "replication, and backup retention."
echo_blank
echo -e "Gravity Sync uses a primary/secondary model for replication, and normally syncs changes from the "
echo -e "primary to the secondary. The LOCAL Pi-hole where you are running this configuration script is"
echo -e "considered the the SECONDARY Pi-hole! The REMOTE Pi-hole where you will normally make configuration"
echo -e "changes is considered the PRIMARY Pi-hole."
echo_blank
echo -e "Confused? Please refer back to the documentation."
echo_lines
docker_detect
podman_detect
if [ "${DOCKERREADY}" == "1" ] || [ "${PODMANREADY}" == "1" ]
then
MESSAGE="Container Engine Detected"
echo_good
MESSAGE="Advanced Configuration Required"
echo_info
advanced_config_generate
else
MESSAGE="Use Advanced Installation Options? (Y/N, default N)"
echo_need
read INPUT_ADVANCED_INSTALL
INPUT_ADVANCED_INSTALL="${INPUT_ADVANCED_INSTALL:-N}"
if [ "${INPUT_ADVANCED_INSTALL}" == "Y" ]
then
MESSAGE="Advanced Configuration Selected"
echo_info
advanced_config_generate
elif [ "${INPUT_ADVANCED_INSTALL}" == "N" ]
then
MESSAGE="Standard Configuration Selected"
echo_info
else
MESSAGE="Invalid Selection"
echo_warn
exit_nochange
fi
fi
MESSAGE="Required Gravity Sync Settings"
echo_info
MESSAGE="Primary/Remote Pi-hole Address (IP or DNS)"
echo_need
read INPUT_REMOTE_HOST
if [ "${PING_AVOID}" != "1" ]
then
MESSAGE="Testing Network Connection (ICMP)"
echo_stat
ping -c 3 ${INPUT_REMOTE_HOST} >/dev/null 2>&1
error_validate
else
MESSAGE="Bypassing Network Testing (ICMP)"
echo_warn
fi
MESSAGE="Saving Primary/Remote Host to ${CONFIG_FILE}"
echo_stat
sed -i "/REMOTE_HOST='192.168.1.10'/c\REMOTE_HOST='${INPUT_REMOTE_HOST}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
MESSAGE="Existing SSH User for ${INPUT_REMOTE_HOST}"
echo_need
read INPUT_REMOTE_USER
MESSAGE="Saving User "${INPUT_REMOTE_USER}" to ${CONFIG_FILE}"
echo_stat
sed -i "/REMOTE_USER='pi'/c\REMOTE_USER='${INPUT_REMOTE_USER}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
generate_sshkey
MESSAGE="Importing New ${CONFIG_FILE}"
echo_stat
source ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
export_sshkey
}
## Advanced Configuration Options
function advanced_config_generate {
MESSAGE="Local/Secondary Pi-hole Instance Type? (Allowed: 'docker' or 'podman' or 'default')"
echo_need
read INPUT_PH_IN_TYPE
INPUT_PH_IN_TYPE="${INPUT_PH_IN_TYPE:-default}"
if [ "${INPUT_PH_IN_TYPE}" != "default" ]
then
if [ "${INPUT_PH_IN_TYPE}" != "docker" ] && [ "${INPUT_PH_IN_TYPE}" != "podman" ]
then
MESSAGE="Local/Secondary Container Type must either be 'docker' or 'podman'"
echo_warn
exit_withchanges
fi
MESSAGE="Saving Local/Secondary Container Type Setting to ${CONFIG_FILE}"
echo_stat
sed -i "/# PH_IN_TYPE=''/c\PH_IN_TYPE='${INPUT_PH_IN_TYPE}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
MESSAGE="Displaying Currently Running Container Images"
echo_info
echo_lines
if [ "${INPUT_PH_IN_TYPE}" == "docker" ]
then
sudo docker container ls
elif [ "${INPUT_PH_IN_TYPE}" == "podman" ]
then
sudo podman container ls
fi
echo_lines
MESSAGE="Local/Secondary Container Name? (Leave blank for default 'pihole')"
echo_need
read INPUT_DOCKER_CON
INPUT_DOCKER_CON="${INPUT_DOCKER_CON:-pihole}"
if [ "${INPUT_DOCKER_CON}" != "pihole" ]
then
MESSAGE="Saving Local/Secondary Container Name to ${CONFIG_FILE}"
echo_stat
sed -i "/# DOCKER_CON=''/c\DOCKER_CON='${INPUT_DOCKER_CON}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
MESSAGE="Local/Secondary Pi-hole 'etc' Volume Path? (Required, no trailing slash)"
echo_need
read INPUT_PIHOLE_DIR
if [ "${INPUT_PIHOLE_DIR}" != "" ]
then
MESSAGE="Saving Local/Secondary Pi-hole Volume to ${CONFIG_FILE}"
echo_stat
sed -i "/# PIHOLE_DIR=''/c\PIHOLE_DIR='${INPUT_PIHOLE_DIR}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
SKIP_PIHOLE_DIR="1"
else
MESSAGE="This setting is required!"
echo_warn
exit_withchanges
fi
MESSAGE="Local/Secondary DNSMASQ 'etc' Volume Path? (Required, no trailing slash)"
echo_need
read INPUT_DNSMAQ_DIR
if [ "${INPUT_DNSMAQ_DIR}" != "" ]
then
MESSAGE="Saving Local/Secondary DNSMASQ Volume to ${CONFIG_FILE}"
echo_stat
sed -i "/# DNSMAQ_DIR=''/c\DNSMAQ_DIR='${INPUT_DNSMAQ_DIR}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
SKIP_DNSMASQ_DIR="1"
else
MESSAGE="This setting is required!"
echo_warn
exit_withchanges
fi
MESSAGE="Saving Local/Secondary Volume Ownership to ${CONFIG_FILE}"
echo_stat
sed -i "/# FILE_OWNER=''/c\FILE_OWNER='999:999'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
MESSAGE="Primary/Remote Pi-hole Instance Type? (Allowed: 'docker' or 'podman' or 'default')"
echo_need
read INPUT_RH_IN_TYPE
INPUT_RH_IN_TYPE="${INPUT_RH_IN_TYPE:-default}"
if [ "${INPUT_RH_IN_TYPE}" != "default" ]
then
if [ "${INPUT_RH_IN_TYPE}" != "docker" ] && [ "${INPUT_RH_IN_TYPE}" != "podman" ]
then
MESSAGE="Primary/Remote Container Type must either be 'docker' or 'podman'"
echo_warn
exit_withchanges
fi
MESSAGE="Saving Primary/Remote Container Type Setting to ${CONFIG_FILE}"
echo_stat
sed -i "/# RH_IN_TYPE=''/c\RH_IN_TYPE='${INPUT_RH_IN_TYPE}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
MESSAGE="Primary/Remote Container Name? (Leave blank for default 'pihole')"
echo_need
read INPUT_ROCKER_CON
INPUT_ROCKER_CON="${INPUT_ROCKER_CON:-pihole}"
if [ "${INPUT_ROCKER_CON}" != "pihole" ]
then
MESSAGE="Saving Primary/Remote Container Name to ${CONFIG_FILE}"
echo_stat
sed -i "/# ROCKER_CON=''/c\ROCKER_CON='${INPUT_ROCKER_CON}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
MESSAGE="Primary/Remote Pi-hole 'etc' Volume Path? (Required, no trailing slash)"
echo_need
read INPUT_RIHOLE_DIR
if [ "${INPUT_RIHOLE_DIR}" != "" ]
then
MESSAGE="Saving Primary/Remote Pi-hole Volume to ${CONFIG_FILE}"
echo_stat
sed -i "/# RIHOLE_DIR=''/c\RIHOLE_DIR='${INPUT_RIHOLE_DIR}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
SKIP_RIHOLE_DIR="1"
else
MESSAGE="This setting is required!"
echo_warn
exit_withchanges
fi
MESSAGE="Primary/Remote DNSMASQ 'etc' Volume Path? (Required, no trailing slash)"
echo_need
read INPUT_RNSMAQ_DIR
if [ "${INPUT_RNSMAQ_DIR}" != "" ]
then
MESSAGE="Saving Primary/Remote DNSMASQ Volume to ${CONFIG_FILE}"
echo_stat
sed -i "/# RNSMAQ_DIR=''/c\RNSMAQ_DIR='${INPUT_RNSMAQ_DIR}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
SKIP_RNSMASQ_DIR="1"
else
MESSAGE="This setting is required!"
echo_warn
exit_withchanges
fi
MESSAGE="Saving Primary/Remote Volume Ownership to ${CONFIG_FILE}"
echo_stat
sed -i "/# RILE_OWNER=''/c\RILE_OWNER='999:999'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
if [ "$SKIP_PIHOLE_DIR" != "1" ]
then
MESSAGE="Local/Secondary Pi-hole Settings Directory Path? (Leave blank for default '/etc/pihole')"
echo_need
read INPUT_PIHOLE_DIR
INPUT_PIHOLE_DIR="${INPUT_PIHOLE_DIR:-/etc/pihole}"
if [ "${INPUT_PIHOLE_DIR}" != "/etc/pihole" ]
then
MESSAGE="Saving Local/Secondary Pi-hole Settings Directory Path to ${CONFIG_FILE}"
echo_stat
sed -i "/# PIHOLE_DIR=''/c\PIHOLE_DIR='${INPUT_PIHOLE_DIR}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
fi
if [ "$SKIP_RIHOLE_DIR" != "1" ]
then
MESSAGE="Primary/Remote Pi-hole Settings Directory Path? (Leave blank for default '/etc/pihole')"
echo_need
read INPUT_RIHOLE_DIR
INPUT_RIHOLE_DIR="${INPUT_RIHOLE_DIR:-/etc/pihole}"
if [ "${INPUT_RIHOLE_DIR}" != "/etc/pihole" ]
then
MESSAGE="Saving Primary/Remote Pi-hole Settings Directory Path to ${CONFIG_FILE}"
echo_stat
sed -i "/# RIHOLE_DIR=''/c\RIHOLE_DIR='${INPUT_RIHOLE_DIR}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
fi
if [ "$SKIP_DNSMASQ_DIR" != "1" ]
then
MESSAGE="Local/Secondary DNSMASQ Settings Directory Path? (Leave blank for default '/etc/dnsmasq.d')"
echo_need
read INPUT_DNSMASQ_DIR
INPUT_DNSMASQ_DIR="${INPUT_DNSMASQ_DIR:-/etc/dnsmasq.d}"
if [ "${INPUT_DNSMASQ_DIR}" != "/etc/dnsmasq.d" ]
then
MESSAGE="Saving Local/Secondary DNSMASQ Settings Directory Path to ${CONFIG_FILE}"
echo_stat
sed -i "/# DNSMASQ_DIR=''/c\DNSMASQ_DIR='${INPUT_DNSMASQ_DIR}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
fi
if [ "$SKIP_RNSMASQ_DIR" != "1" ]
then
MESSAGE="Primary/Remote DNSMASQ Settings Directory Path? (Leave blank for default '/etc/dnsmasq.d')"
echo_need
read INPUT_RNSMASQ_DIR
INPUT_RNSMASQ_DIR="${INPUT_RNSMASQ_DIR:-/etc/dnsmasq.d}"
if [ "${INPUT_RNSMASQ_DIR}" != "/etc/dnsmasq.d" ]
then
MESSAGE="Saving Primary/Remote DNSMASQ Settings Directory Path to ${CONFIG_FILE}"
echo_stat
sed -i "/# RNSMASQ_DIR=''/c\RNSMASQ_DIR='${INPUT_RNSMASQ_DIR}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
fi
MESSAGE="Custom SSH Port to Connect to Primary/Remote host? (Leave blank for default '22')"
echo_need
read INPUT_SSH_PORT
INPUT_SSH_PORT="${INPUT_SSH_PORT:-22}"
SSH_PORT="${INPUT_SSH_PORT}"
if [ "${INPUT_SSH_PORT}" != "22" ]
then
MESSAGE="Saving Custom SSH Port to ${CONFIG_FILE}"
echo_stat
sed -i "/# SSH_PORT=''/c\SSH_PORT='${INPUT_SSH_PORT}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
MESSAGE="Enable Ping/ICMP Check of Primary/Remote? (Y/N, default 'Y')"
echo_need
read INPUT_PING_AVOID
INPUT_PING_AVOID="${INPUT_PING_AVOID:-Y}"
if [ "${INPUT_PING_AVOID}" != "Y" ]
then
MESSAGE="Saving ICMP Avoidance to ${CONFIG_FILE}"
echo_stat
sed -i "/# PING_AVOID=''/c\PING_AVOID='1'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
PING_AVOID=1
fi
MESSAGE="Custom SSH PKIF Location? (Leave blank for default '.ssh/id_rsa')"
echo_need
read INPUT_CUSTOM_PKIF
INPUT_CUSTOM_PKIF="${INPUT_CUSTOM_PKIF:-.ssh/id_rsa}"
if [ "${INPUT_CUSTOM_PKIF}" != ".ssh/id_rsa" ]
then
MESSAGE="Saving Custom PKIF to ${CONFIG_FILE}"
echo_stat
sed -i "/# SSH_PKIF=''/c\SSH_PKIF='${INPUT_CUSTOM_PKIF}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
MESSAGE="Enable Replicate 'Local DNS Records' Feature? (Y/N, default 'Y')"
echo_need
read INPUT_SKIP_CUSTOM
INPUT_SKIP_CUSTOM="${INPUT_SKIP_CUSTOM:-Y}"
if [ "${INPUT_SKIP_CUSTOM}" != "Y" ]
then
MESSAGE="Saving Local DNS Preference to ${CONFIG_FILE}"
echo_stat
sed -i "/# SKIP_CUSTOM=''/c\SKIP_CUSTOM='1'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
if [ "${INPUT_SKIP_CUSTOM}" == "Y" ]
then
MESSAGE="Enable Replicate 'Local CNAME Records' Feature? (Y/N, default 'Y')"
echo_need
read INPUT_INCLUDE_CNAME
INPUT_INCLUDE_CNAME="${INPUT_INCLUDE_CNAME:-Y}"
if [ "${INPUT_INCLUDE_CNAME}" == "Y" ]
then
MESSAGE="Saving Local CNAME Preference to ${CONFIG_FILE}"
echo_stat
sed -i "/# INCLUDE_CNAME=''/c\INCLUDE_CNAME='1'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
fi
MESSAGE="Change Backup Retention in Days? (Leave blank for default '3')"
echo_need
read INPUT_BACKUP_RETAIN
INPUT_BACKUP_RETAIN="${INPUT_BACKUP_RETAIN:-3}"
if [ "${INPUT_BACKUP_RETAIN}" != "3" ]
then
MESSAGE="Saving Backup Retention to ${CONFIG_FILE}"
echo_stat
sed -i "/# BACKUP_RETAIN=''/c\BACKUP_RETAIN='${INPUT_BACKUP_RETAIN}'" ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
}
## Delete Existing Configuration
function config_delete {
source ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
MESSAGE="Configuration File Exists"
echo_warn
echo_lines
cat ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
echo_blank
echo_lines
MESSAGE="Are you sure you want to erase this configuration?"
echo_warn
intent_validate
MESSAGE="Erasing Existing Configuration"
echo_stat
rm -f ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
config_generate
}
## Detect Docker
function docker_detect {
if hash docker 2>/dev/null
then
FTLCHECK=$(sudo docker container ls | grep 'pihole/pihole')
if [ "$FTLCHECK" != "" ]
then
DOCKERREADY="1"
fi
fi
}
## Detect Podman
function podman_detect {
if hash podman 2>/dev/null
then
FTLCHECK=$(sudo podman container ls | grep 'pihole/pihole')
if [ "$FTLCHECK" != "" ]
then
PODMANREADY="1"
fi
fi
}
## Create Bash Alias
function create_alias {
MESSAGE="Creating Bash Alias"
echo_stat
echo -e "alias gravity-sync='${GS_FILEPATH}'" | sudo tee -a /etc/bash.bashrc > /dev/null
error_validate
}

View File

@ -1,176 +0,0 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-core.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!
# Standard Output
function start_gs {
MESSAGE="${UI_CORE_INIT}"
echo_grav
cd ${LOCAL_FOLDR}
import_gs
ph_type
MESSAGE="${UI_CORE_EVALUATING}"
echo_stat
if [ "${ROOT_CHECK_AVOID}" != "1" ]
then
new_root_check
fi
if [ "${INCLUDE_CNAME}" == "1" ] && [ "${SKIP_CUSTOM}" == "1" ]
then
MESSAGE="${UI_INVALID_DNS_CONFIG} ${CONFIG_FILE}"
echo_fail
exit_nochange
fi
}
# Standard Output No Config
function start_gs_noconfig {
MESSAGE="${UI_CORE_INIT}"
echo_grav
cd ${LOCAL_FOLDR}
MESSAGE="${UI_CORE_EVALUATING}"
echo_stat
}
## Import Settings
function import_gs {
relocate_config_gs
MESSAGE="${UI_CORE_LOADING} ${CONFIG_FILE}"
echo -en "${STAT} $MESSAGE"
if [ -f ${LOCAL_FOLDR}/settings/${CONFIG_FILE} ]
then
source ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
else
echo_fail
MESSAGE="${UI_CORE_MISSING} ${CONFIG_FILE}"
echo_info
TASKTYPE='CONFIG'
config_generate
fi
}
function relocate_config_gs {
if [ -f ${LOCAL_FOLDR}/${CONFIG_FILE} ]
then
MESSAGE="${UI_CORE_RELOCATING} ${CONFIG_FILE}"
echo -en "${STAT} $MESSAGE"
mv ${LOCAL_FOLDR}/${CONFIG_FILE} ${LOCAL_FOLDR}/settings/${CONFIG_FILE}
error_validate
fi
if [ -f ${LOCAL_FOLDR}/${SYNCING_LOG} ]
then
MESSAGE="${UI_CORE_RELOCATING} ${SYNCING_LOG}"
echo -en "${STAT} $MESSAGE"
mv ${LOCAL_FOLDR}/${SYNCING_LOG} ${LOG_PATH}/${SYNCING_LOG}
error_validate
fi
if [ -f ${LOCAL_FOLDR}/${CRONJOB_LOG} ]
then
MESSAGE="${UI_CORE_RELOCATING} ${CRONJOB_LOG}"
echo -en "${STAT} $MESSAGE"
mv ${LOCAL_FOLDR}/${CRONJOB_LOG} ${LOG_PATH}/${CRONJOB_LOG}
error_validate
fi
if [ -f ${LOCAL_FOLDR}/${HISTORY_MD5} ]
then
MESSAGE="${UI_CORE_RELOCATING} ${HISTORY_MD5}"
echo -en "${STAT} $MESSAGE"
mv ${LOCAL_FOLDR}/${HISTORY_MD5} ${LOG_PATH}/${HISTORY_MD5}
error_validate
fi
}
## Invalid Tasks
function task_invalid {
echo_fail
list_gs_arguments
}
## Error Validation
function error_validate {
if [ "$?" != "0" ]
then
echo_fail
exit 1
else
echo_good
fi
}
## Error Validation
function silent_error_validate {
if [ "$?" != "0" ]
then
echo_fail
exit 1
else
echo_sameline
fi
}
function ph_type {
if [ "$PH_IN_TYPE" == "default" ]
then
PH_EXEC="${PIHOLE_BIN}"
elif [ "$PH_IN_TYPE" == "docker" ]
then
PH_EXEC="sudo ${DOCKER_BIN} exec $(sudo ${DOCKER_BIN} ps -qf name=${DOCKER_CON}) pihole"
elif [ "$PH_IN_TYPE" == "podman" ]
then
PH_EXEC="sudo ${PODMAN_BIN} exec ${DOCKER_CON} pihole"
fi
if [ "$RH_IN_TYPE" == "default" ]
then
RH_EXEC="${RIHOLE_BIN}"
elif [ "$RH_IN_TYPE" == "docker" ]
then
RH_EXEC="sudo ${ROCKER_BIN} exec \$(sudo ${ROCKER_BIN} ps -qf name=${ROCKER_CON}) pihole"
elif [ "$RH_IN_TYPE" == "podman" ]
then
RH_EXEC="sudo ${RODMAN_BIN} exec ${ROCKER_CON} pihole"
fi
}
## Compare Task
function task_compare {
TASKTYPE='COMPARE'
MESSAGE="${MESSAGE}: ${TASKTYPE}"
echo_good
show_target
validate_gs_folders
validate_ph_folders
if [ "${INCLUDE_CNAME}" == "1" ]
then
validate_dns_folders
fi
validate_os_sshpass
previous_md5
md5_compare
backup_cleanup
exit_withchange
}

View File

@ -1,66 +0,0 @@
# 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
let SCRIPT_RUN=SCRIPT_END-SCRIPT_START
if [ "${TASKTYPE}" == "" ]
then
MESSAGE="${PROGRAM} ${UI_EXIT_ABORT} ${UI_EXIT_CALC_END} ${SCRIPT_RUN} ${UI_EXIT_CALC_TIMER}"
else
MESSAGE="${PROGRAM} ${TASKTYPE} ${UI_EXIT_ABORT} ${UI_EXIT_CALC_END} ${SCRIPT_RUN} ${UI_EXIT_CALC_TIMER}"
fi
echo_grav
exit 0
}
## Changes Made
function exit_withchange {
SCRIPT_END=$SECONDS
let SCRIPT_RUN=SCRIPT_END-SCRIPT_START
if [ "${TASKTYPE}" == "" ]
then
MESSAGE="${PROGRAM} ${UI_EXIT_COMPLETE} ${UI_EXIT_CALC_END} ${SCRIPT_RUN} ${UI_EXIT_CALC_TIMER}"
else
MESSAGE="${PROGRAM} ${TASKTYPE} ${UI_EXIT_COMPLETE} ${UI_EXIT_CALC_END} ${SCRIPT_RUN} ${UI_EXIT_CALC_TIMER}"
fi
echo_grav
exit 0
}
## List GS Arguments
function list_gs_arguments {
echo -e "Usage: $0 [options]"
echo -e "Example: '$0 pull'"
echo_lines
echo -e "Setup Options:"
echo -e " ${YELLOW}config${NC} Creates a new ${PROGRAM} configuration file"
echo -e " ${YELLOW}automate${NC} Schedules the ${PROGRAM} replication task using crontab"
echo -e " ${YELLOW}version${NC} Shows the installed version of ${PROGRAM} and check for updates"
echo -e " ${YELLOW}update${NC} Upgrades ${PROGRAM} to the latest available version using Git"
echo -e " ${YELLOW}dev${NC} Sets update command to use a development version of ${PROGRAM}"
echo -e " ${YELLOW}sudo${NC} Configures passwordless sudo for current user"
echo_blank
echo -e "Replication Options:"
echo -e " ${YELLOW}smart${NC} Detects Pi-hole changes on primary and secondary and then combines them"
echo -e " ${YELLOW}pull${NC} Brings the remote Pi-hole configuration to this server"
echo -e " ${YELLOW}push${NC} Sends the local Pi-hole configuration to the primary"
echo -e " ${YELLOW}compare${NC} Just checks for Pi-hole differences at each side without making changes"
echo -e " ${YELLOW}restore${NC} Restores the Pi-hole configuration on this server"
echo -e " ${YELLOW}backup${NC} Just backs up the Pi-hole on this server"
echo_blank
echo -e "Debug Options:"
echo -e " ${YELLOW}logs${NC} Shows the recent successful replication jobs/times"
echo -e " ${YELLOW}cron${NC} Displays the output of last crontab execution"
echo -e " ${YELLOW}info${NC} Shows information about the current configuration"
echo_lines
exit_nochange
}

View File

@ -1,237 +0,0 @@
# 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="${UI_HASHING_HASHING} ${UI_GRAVITY_NAME}"
echo_stat
primaryDBMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${RIHOLE_DIR}/${GRAVITY_FI}" | sed 's/\s.*$//')
error_validate
MESSAGE="${UI_HASHING_COMPARING} ${UI_GRAVITY_NAME}"
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="${UI_HASHING_DIFFERNCE} ${UI_GRAVITY_NAME}"
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 ${RIHOLE_DIR}/${CUSTOM_DNS}
then
REMOTE_CUSTOM_DNS="1"
MESSAGE="${UI_HASHING_HASHING} ${UI_CUSTOM_NAME}"
echo_stat
primaryCLMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${RIHOLE_DIR}/${CUSTOM_DNS} | sed 's/\s.*$//'")
error_validate
MESSAGE="${UI_HASHING_COMPARING} ${UI_CUSTOM_NAME}"
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="${UI_HASHING_DIFFERNCE} ${UI_CUSTOM_NAME}"
echo_warn
HASHMARK=$((HASHMARK+1))
fi
else
MESSAGE="${UI_CUSTOM_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_PRIMARY}"
echo_info
fi
else
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${RIHOLE_DIR}/${CUSTOM_DNS}
then
REMOTE_CUSTOM_DNS="1"
MESSAGE="${UI_CUSTOM_NAME} ${UI_HASHING_DETECTED} ${UI_HASHING_PRIMARY}"
HASHMARK=$((HASHMARK+1))
echo_info
fi
MESSAGE="${UI_CUSTOM_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_SECONDARY}"
echo_info
fi
fi
if [ "${SKIP_CUSTOM}" != '1' ]
then
if [ "${INCLUDE_CNAME}" == "1" ]
then
if [ -f ${DNSMAQ_DIR}/${CNAME_CONF} ]
then
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${RNSMAQ_DIR}/${CNAME_CONF}
then
REMOTE_CNAME_DNS="1"
MESSAGE="${UI_HASHING_HASHING} ${UI_CNAME_NAME}"
echo_stat
primaryCNMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${RNSMAQ_DIR}/${CNAME_CONF} | sed 's/\s.*$//'")
error_validate
MESSAGE="${UI_HASHING_COMPARING} ${UI_CNAME_NAME}"
echo_stat
secondCNMD5=$(md5sum ${DNSMAQ_DIR}/${CNAME_CONF} | sed 's/\s.*$//')
error_validate
if [ "$primaryCNMD5" == "$last_primaryCNMD5" ] && [ "$secondCNMD5" == "$last_secondCNMD5" ]
then
HASHMARK=$((HASHMARK+0))
else
MESSAGE="${UI_HASHING_DIFFERNCE} ${UI_CNAME_NAME}"
echo_warn
HASHMARK=$((HASHMARK+1))
fi
else
MESSAGE="${UI_CNAME_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_PRIMARY}"
echo_info
fi
else
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${RNSMAQ_DIR}/${CNAME_CONF}
then
REMOTE_CNAME_DNS="1"
MESSAGE="${UI_CNAME_NAME} ${UI_HASHING_DETECTED} ${UI_HASHING_PRIMARY}"
HASHMARK=$((HASHMARK+1))
echo_info
fi
MESSAGE="${UI_CNAME_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_SECONDARY}"
echo_info
fi
fi
fi
if [ "$HASHMARK" != "0" ]
then
MESSAGE="${UI_HASHING_REQUIRED}"
echo_warn
HASHMARK=$((HASHMARK+0))
else
MESSAGE="${UI_HASHING_NOREP}"
echo_info
backup_cleanup
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})
last_primaryCNMD5=$(sed "5q;d" ${LOG_PATH}/${HISTORY_MD5})
last_secondCNMD5=$(sed "6q;d" ${LOG_PATH}/${HISTORY_MD5})
else
last_primaryDBMD5="0"
last_secondDBMD5="0"
last_primaryCLMD5="0"
last_secondCLMD5="0"
last_primaryCNMD5="0"
last_secondCNMD5="0"
fi
}
function md5_recheck {
MESSAGE="${UI_HASHING_DIAGNOSTICS}"
echo_info
HASHMARK='0'
MESSAGE="${UI_HASHING_REHASHING} ${UI_GRAVITY_NAME}"
echo_stat
primaryDBMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${RIHOLE_DIR}/${GRAVITY_FI}" | sed 's/\s.*$//')
error_validate
MESSAGE="${UI_HASHING_RECOMPARING} ${UI_GRAVITY_NAME}"
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 ${RIHOLE_DIR}/${CUSTOM_DNS}
then
REMOTE_CUSTOM_DNS="1"
MESSAGE="${UI_HASHING_REHASHING} ${UI_CUSTOM_NAME}"
echo_stat
primaryCLMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${RIHOLE_DIR}/${CUSTOM_DNS} | sed 's/\s.*$//'")
error_validate
MESSAGE="${UI_HASHING_RECOMPARING} ${UI_CUSTOM_NAME}"
echo_stat
secondCLMD5=$(md5sum ${PIHOLE_DIR}/${CUSTOM_DNS} | sed 's/\s.*$//')
error_validate
else
MESSAGE="${UI_CUSTOM_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_PRIMARY}"
echo_info
fi
else
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${RIHOLE_DIR}/${CUSTOM_DNS}
then
REMOTE_CUSTOM_DNS="1"
MESSAGE="${UI_CUSTOM_NAME} ${UI_HASHING_DETECTED} ${UI_HASHING_PRIMARY}"
echo_info
fi
MESSAGE="${UI_CUSTOM_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_SECONDARY}"
echo_info
fi
fi
if [ "${SKIP_CUSTOM}" != '1' ]
then
if [ "${INCLUDE_CNAME}" == "1" ]
then
if [ -f ${DNSMAQ_DIR}/${CNAME_CONF} ]
then
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${RNSMAQ_DIR}/${CNAME_CONF}
then
REMOTE_CNAME_DNS="1"
MESSAGE="${UI_HASHING_REHASHING} ${UI_CNAME_NAME}"
echo_stat
primaryCNMD5=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "md5sum ${RNSMAQ_DIR}/${CNAME_CONF} | sed 's/\s.*$//'")
error_validate
MESSAGE="${UI_HASHING_RECOMPARING} ${UI_CNAME_NAME}"
echo_stat
secondCNMD5=$(md5sum ${DNSMAQ_DIR}/${CNAME_CONF} | sed 's/\s.*$//')
error_validate
else
MESSAGE="${UI_CNAME_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_PRIMARY}"
echo_info
fi
else
if ${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} test -e ${RNSMAQ_DIR}/${CNAME_CONF}
then
REMOTE_CNAME_DNS="1"
MESSAGE="${UI_CNAME_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_PRIMARY}"
echo_info
fi
MESSAGE="${UI_CNAME_NAME} ${UI_HASHING_NOTDETECTED} ${UI_HASHING_SECONDARY}"
echo_info
fi
fi
fi
}

View File

@ -1,41 +0,0 @@
# 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
}

View File

@ -1,93 +0,0 @@
# 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}"
echo_good
logs_gs
}
## Core Logging
### Write Logs Out
function logs_export {
if [ "${TASKTYPE}" != "BACKUP" ]
then
MESSAGE="${UI_LOGGING_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}
echo -e ${primaryCNMD5} >> ${LOG_PATH}/${HISTORY_MD5}
echo -e ${secondCNMD5} >> ${LOG_PATH}/${HISTORY_MD5}
error_validate
fi
MESSAGE="${UI_LOGGING_SUCCESS} ${TASKTYPE}"
echo_stat
echo -e $(date) "[${TASKTYPE}]" >> ${LOG_PATH}/${SYNCING_LOG}
error_validate
}
### Output Sync Logs
function logs_gs {
MESSAGE="${UI_LOGGING_DISPLAY}"
echo_info
echo_lines
echo -e "${UI_LOGGING_RECENT_COMPLETE} ${YELLOW}SMART${NC}"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep SMART
echo -e "${UI_LOGGING_RECENT_COMPLETE} ${YELLOW}PULL${NC}"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep PULL
echo -e "${UI_LOGGING_RECENT_COMPLETE} ${YELLOW}PUSH${NC}"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep PUSH
echo -e "${UI_LOGGING_RECENT_COMPLETE} ${YELLOW}BACKUP${NC}"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep BACKUP
echo -e "${UI_LOGGING_RECENT_COMPLETE} ${YELLOW}RESTORE${NC}"
tail -n 7 "${LOG_PATH}/${SYNCING_LOG}" | grep RESTORE
echo_lines
exit_nochange
}
## Crontab Logs
### Core Crontab Logs
function show_crontab {
MESSAGE="${UI_LOGGING_DISPLAY}"
echo_stat
if [ -f ${LOG_PATH}/${CRONJOB_LOG} ]
then
if [ -s ${LOG_PATH}/${CRONJOB_LOG} ]
echo_good
echo_lines
date -r ${LOG_PATH}/${CRONJOB_LOG}
cat ${LOG_PATH}/${CRONJOB_LOG}
echo_lines
exit_nochange
then
echo_fail
MESSAGE="${LOG_PATH}/${CRONJOB_LOG} ${UI_LOGGING_EMPTY}"
echo_info
exit_nochange
fi
else
echo_fail
MESSAGE="${LOG_PATH}/${CRONJOB_LOG} ${UI_LOGGING_MISSING}"
echo_info
exit_nochange
fi
}

View File

@ -1,135 +0,0 @@
# 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}"
echo_good
show_target
validate_gs_folders
validate_ph_folders
if [ "${INCLUDE_CNAME}" == "1" ]
then
validate_dns_folders
fi
validate_sqlite3
validate_os_sshpass
pull_gs
exit
}
## Pull Gravity
function pull_gs_grav {
backup_local_gravity
backup_remote_gravity
backup_remote_gravity_integrity
MESSAGE="${UI_PULL_PRIMARY} ${UI_GRAVITY_NAME}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${RIHOLE_DIR}/${GRAVITY_FI}.backup"
RSYNC_TARGET="${LOCAL_FOLDR}/${BACKUP_FOLD}/${GRAVITY_FI}.pull"
create_rsynccmd
MESSAGE="${UI_REPLACE_SECONDARY} ${UI_GRAVITY_NAME}"
echo_stat
sudo cp ${LOCAL_FOLDR}/${BACKUP_FOLD}/${GRAVITY_FI}.pull ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
validate_gravity_permissions
}
## Pull Custom
function pull_gs_cust {
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ "$REMOTE_CUSTOM_DNS" == "1" ]
then
backup_local_custom
backup_remote_custom
MESSAGE="${UI_PULL_PRIMARY} ${UI_CUSTOM_NAME}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${RIHOLE_DIR}/${CUSTOM_DNS}.backup"
RSYNC_TARGET="${LOCAL_FOLDR}/${BACKUP_FOLD}/${CUSTOM_DNS}.pull"
create_rsynccmd
MESSAGE="${UI_REPLACE_SECONDARY} ${UI_CUSTOM_NAME}"
echo_stat
sudo cp ${LOCAL_FOLDR}/${BACKUP_FOLD}/${CUSTOM_DNS}.pull ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
validate_custom_permissions
fi
fi
}
## Pull CNAME
function pull_gs_cname {
if [ "${INCLUDE_CNAME}" == '1' ]
then
if [ "$REMOTE_CNAME_DNS" == "1" ]
then
backup_local_cname
backup_remote_cname
MESSAGE="${UI_PULL_PRIMARY} ${UI_CNAME_NAME}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${RIHOLE_DIR}/dnsmasq.d-${CNAME_CONF}.backup"
RSYNC_TARGET="${LOCAL_FOLDR}/${BACKUP_FOLD}/${CNAME_CONF}.pull"
create_rsynccmd
MESSAGE="${UI_REPLACE_SECONDARY} ${UI_CNAME_NAME}"
echo_stat
sudo cp ${LOCAL_FOLDR}/${BACKUP_FOLD}/${CNAME_CONF}.pull ${DNSMAQ_DIR}/${CNAME_CONF} >/dev/null 2>&1
error_validate
validate_cname_permissions
fi
fi
}
## Pull Reload
function pull_gs_reload {
MESSAGE="${UI_PULL_RELOAD_WAIT}"
echo_info
sleep 1
MESSAGE="${UI_FTLDNS_CONFIG_UPDATE}"
echo_stat
${PH_EXEC} restartdns reloadlists >/dev/null 2>&1
error_validate
MESSAGE="${UI_FTLDNS_CONFIG_RELOAD}"
echo_stat
${PH_EXEC} 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_cname
pull_gs_reload
md5_recheck
backup_cleanup
logs_export
exit_withchange
}

View File

@ -1,63 +0,0 @@
# 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}"
echo_good
echo_lines
echo -e "THIS WILL RESET YOUR ENTIRE GRAVITY SYNC INSTALLATION"
echo -e "This will remove:"
echo -e "- All backups files."
echo -e "- Your ${CONFIG_FILE} file."
if [ -f "${LOCAL_FOLDR}/dev" ]
then
echo -e "- Your development branch updater."
elif [ -f "${LOCAL_FOLDR}/beta" ]
then
echo -e "- Your beta branch updater."
fi
echo -e "- All cronjob/automation tasks."
echo -e "- All job history/logs."
echo -e "- Associated SSH id_rsa keys."
echo -e ""
echo -e "This function cannot be undone!"
echo -e ""
echo -e "YOU WILL NEED TO REBUILD GRAVITY SYNC AFTER EXECUTION"
echo -e "Pi-hole binaries, configuration and services ARE NOT impacted!"
echo -e "Your device will continue to resolve and block DNS requests,"
echo -e "but your ${UI_GRAVITY_NAME} and ${UI_CUSTOM_NAME} WILL NOT sync anymore,"
echo -e "until you reconfigure Gravity Sync on this device."
echo_lines
intent_validate
MESSAGE="${UI_PURGE_CLEANING_DIR}"
echo_stat
git clean -f -X -d >/dev/null 2>&1
error_validate
clear_cron
MESSAGE="${UI_PURGE_DELETE_SSH_KEYS}"
echo_stat
rm -f $HOME/${SSH_PKIF} >/dev/null 2>&1
rm -f $HOME/${SSH_PKIF}.pub >/dev/null 2>&1
error_validate
MESSAGE="${UI_PURGE_MATRIX_ALIGNMENT}"
echo_info
sleep 1
update_gs
}

View File

@ -1,175 +0,0 @@
# 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}"
echo_good
show_target
validate_gs_folders
validate_ph_folders
if [ "${INCLUDE_CNAME}" == "1" ]
then
validate_dns_folders
fi
validate_sqlite3
validate_os_sshpass
push_gs
exit
}
## Push Gravity
function push_gs_grav {
backup_remote_gravity
backup_local_gravity
backup_local_gravity_integrity
MESSAGE="${UI_BACKUP_COPY} ${UI_GRAVITY_NAME}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${RIHOLE_DIR}/${GRAVITY_FI}.backup"
RSYNC_TARGET="${LOCAL_FOLDR}/${BACKUP_FOLD}/${GRAVITY_FI}.push"
create_rsynccmd
MESSAGE="${UI_PUSH_SECONDARY} ${UI_GRAVITY_NAME}"
echo_stat
RSYNC_REPATH="sudo rsync"
RSYNC_SOURCE="${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${GRAVITY_FI}.backup"
RSYNC_TARGET="${REMOTE_USER}@${REMOTE_HOST}:${RIHOLE_DIR}/${GRAVITY_FI}"
create_rsynccmd
MESSAGE="${UI_SET_FILE_OWNERSHIP} ${UI_GRAVITY_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chown ${RILE_OWNER} ${RIHOLE_DIR}/${GRAVITY_FI}"
create_sshcmd
MESSAGE="${UI_SET_FILE_PERMISSION} ${UI_GRAVITY_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chmod 664 ${RIHOLE_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="${UI_BACKUP_COPY} ${UI_CUSTOM_NAME}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${RIHOLE_DIR}/${CUSTOM_DNS}.backup"
RSYNC_TARGET="${LOCAL_FOLDR}/${BACKUP_FOLD}/${CUSTOM_DNS}.push"
create_rsynccmd
MESSAGE="${UI_PUSH_SECONDARY} ${UI_CUSTOM_NAME}"
echo_stat
RSYNC_REPATH="sudo rsync"
RSYNC_SOURCE="${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${CUSTOM_DNS}.backup"
RSYNC_TARGET="${REMOTE_USER}@${REMOTE_HOST}:${RIHOLE_DIR}/${CUSTOM_DNS}"
create_rsynccmd
MESSAGE="${UI_SET_FILE_OWNERSHIP} ${UI_CUSTOM_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chown root:root ${RIHOLE_DIR}/${CUSTOM_DNS}"
create_sshcmd
MESSAGE="${UI_SET_FILE_PERMISSIONS} ${UI_CUSTOM_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chmod 644 ${RIHOLE_DIR}/${CUSTOM_DNS}"
create_sshcmd
fi
fi
}
## Push Custom
function push_gs_cname {
if [ "${INCLUDE_CNAME}" == '1' ]
then
if [ "$REMOTE_CNAME_DNS" == "1" ]
then
backup_remote_cname
backup_local_cname
MESSAGE="${UI_BACKUP_COPY} ${UI_CNAME_NAME}"
echo_stat
RSYNC_REPATH="rsync"
RSYNC_SOURCE="${REMOTE_USER}@${REMOTE_HOST}:${RIHOLE_DIR}/dnsmasq.d-${CNAME_CONF}.backup"
RSYNC_TARGET="${LOCAL_FOLDR}/${BACKUP_FOLD}/${CNAME_CONF}.push"
create_rsynccmd
MESSAGE="${UI_PUSH_SECONDARY} ${UI_CNAME_NAME}"
echo_stat
RSYNC_REPATH="sudo rsync"
RSYNC_SOURCE="${LOCAL_FOLDR}/${BACKUP_FOLD}/${BACKUPTIMESTAMP}-${CNAME_CONF}.backup"
RSYNC_TARGET="${REMOTE_USER}@${REMOTE_HOST}:${RNSMAQ_DIR}/${CNAME_CONF}"
create_rsynccmd
MESSAGE="${UI_SET_FILE_OWNERSHIP} ${UI_CNAME_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chown root:root ${RNSMAQ_DIR}/${CNAME_CONF}"
create_sshcmd
MESSAGE="${UI_SET_FILE_PERMISSIONS} ${UI_CNAME_NAME}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="sudo chmod 644 ${RNSMAQ_DIR}/${CNAME_CONF}"
create_sshcmd
fi
fi
}
## Push Reload
function push_gs_reload {
MESSAGE="${UI_PUSH_RELOAD_WAIT}"
echo_info
sleep 1
MESSAGE="${UI_FTLDNS_CONFIG_PUSH_UPDATE}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="${RH_EXEC} restartdns reloadlists"
create_sshcmd
MESSAGE="${UI_FTLDNS_CONFIG_PUSH_RELOAD}"
echo_stat
CMD_TIMEOUT='15'
CMD_REQUESTED="${RH_EXEC} restartdns"
create_sshcmd
}
## Push Function
function push_gs {
previous_md5
md5_compare
backup_settime
intent_validate
push_gs_grav
push_gs_cust
push_gs_cname
push_gs_reload
md5_recheck
backup_cleanup
logs_export
exit_withchange
}

View File

@ -1,238 +0,0 @@
# 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}"
echo_good
show_target
validate_gs_folders
validate_ph_folders
if [ "${INCLUDE_CNAME}" == "1" ]
then
validate_dns_folders
fi
validate_sqlite3
restore_gs
exit
}
## Restore Gravity
function restore_gs {
MESSAGE=""
echo_warn
GRAVITY_DATE_LIST=$(ls ${LOCAL_FOLDR}/${BACKUP_FOLD} | grep $(date +%Y) | grep ${GRAVITY_FI} | colrm 18)
if [ "${GRAVITY_DATE_LIST}" != "" ]
then
MESSAGE="${UI_RESTORE_WARNING}"
echo_info
echo_lines
ls ${LOCAL_FOLDR}/${BACKUP_FOLD} | grep $(date +%Y) | grep ${GRAVITY_FI} | colrm 18
echo -e "IGNORE-GRAVITY"
echo_lines
MESSAGE="${UI_RESTORE_SELECT_DATE} ${UI_GRAVITY_NAME}"
echo_need
read INPUT_BACKUP_DATE
if [ "$INPUT_BACKUP_DATE" == "IGNORE-GRAVITY" ]
then
MESSAGE="${UI_RESTORE_SKIPPING} ${UI_GRAVITY_NAME}"
echo_warn
elif [ -f ${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_BACKUP_DATE}-${GRAVITY_FI}.backup ]
then
MESSAGE="${UI_GRAVITY_NAME} ${UI_RESTORE_BACKUP_SELECTED}"
echo_good
DO_GRAVITY_RESTORE='1'
else
MESSAGE="${UI_RESTORE_INVALID}"
echo_info
exit_nochange
fi
fi
if [ "$SKIP_CUSTOM" != '1' ]
then
if [ -f ${PIHOLE_DIR}/${CUSTOM_DNS} ]
then
CUSTOM_DATE_LIST=$(ls ${LOCAL_FOLDR}/${BACKUP_FOLD} | grep $(date +%Y) | grep ${CUSTOM_DNS} | colrm 18)
if [ "${CUSTOM_DATE_LIST}" != "" ]
then
echo_lines
ls ${LOCAL_FOLDR}/${BACKUP_FOLD} | grep $(date +%Y) | grep ${CUSTOM_DNS} | colrm 18
echo -e "IGNORE-CUSTOM"
echo_lines
MESSAGE="${UI_RESTORE_SELECT_DATE} ${UI_CUSTOM_NAME}"
echo_need
read INPUT_DNSBACKUP_DATE
if [ "$INPUT_DNSBACKUP_DATE" == "IGNORE-CUSTOM" ]
then
MESSAGE="${UI_RESTORE_SKIPPING} ${UI_CUSTOM_NAME}"
echo_warn
elif [ -f ${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_DNSBACKUP_DATE}-${CUSTOM_DNS}.backup ]
then
MESSAGE="${UI_CUSTOM_NAME} ${UI_RESTORE_BACKUP_SELECTED}"
echo_good
DO_CUSTOM_RESTORE='1'
else
MESSAGE="${UI_RESTORE_INVALID}"
echo_fail
exit_nochange
fi
else
MESSAGE="${UI_CUSTOM_NAME} ${UI_RESTORE_BACKUP_UNAVAILABLE}"
echo_info
fi
fi
fi
if [ "$INCLUDE_CNAME" == '1' ]
then
if [ -f ${DNSMAQ_DIR}/${CNAME_CONF} ]
then
CNAME_DATE_LIST=$(ls ${LOCAL_FOLDR}/${BACKUP_FOLD} | grep $(date +%Y) | grep ${CNAME_CONF} | colrm 18)
if [ "${CNAME_DATE_LIST}" != "" ]
then
echo_lines
ls ${LOCAL_FOLDR}/${BACKUP_FOLD} | grep $(date +%Y) | grep ${CNAME_CONF} | colrm 18
echo -e "IGNORE-CNAME"
echo_lines
MESSAGE="${UI_RESTORE_SELECT_DATE} ${UI_CNAME_NAME}"
echo_need
read INPUT_CNAMEBACKUP_DATE
if [ "$INPUT_CNAMEBACKUP_DATE" == "IGNORE-CNAME" ]
then
MESSAGE="${UI_RESTORE_SKIPPING} ${UI_CNAME_NAME}"
echo_warn
elif [ -f ${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_CNAMEBACKUP_DATE}-${CNAME_CONF}.backup ]
then
MESSAGE="${UI_CNAME_NAME} ${UI_RESTORE_BACKUP_SELECTED}"
echo_good
DO_CNAME_RESTORE='1'
else
MESSAGE="${UI_RESTORE_INVALID}"
echo_fail
exit_nochange
fi
else
MESSAGE="${UI_CNAME_NAME} ${UI_RESTORE_BACKUP_UNAVAILABLE}"
echo_info
fi
fi
fi
if [ "$DO_GRAVITY_RESTORE" == "1" ]
then
MESSAGE="${UI_GRAVITY_NAME} ${UI_RESTORE_FROM} ${INPUT_BACKUP_DATE}"
echo_info
else
MESSAGE="${UI_GRAVITY_NAME} ${UI_RESTORE_BACKUP_UNAVAILABLE}"
echo_info
fi
if [ "$DO_CUSTOM_RESTORE" == "1" ]
then
MESSAGE="${UI_CUSTOM_NAME} ${UI_RESTORE_FROM} ${INPUT_DNSBACKUP_DATE}"
echo_info
else
MESSAGE="${UI_CUSTOM_NAME} ${UI_RESTORE_BACKUP_UNAVAILABLE}"
echo_info
fi
if [ "$DO_CNAME_RESTORE" == "1" ]
then
MESSAGE="${UI_CNAME_NAME} ${UI_RESTORE_FROM} ${INPUT_CNAMEBACKUP_DATE}"
echo_info
else
MESSAGE="${UI_CNAME_NAME} ${UI_RESTORE_BACKUP_UNAVAILABLE}"
echo_info
fi
intent_validate
MESSAGE="${UI_RESTORE_TIME_TRAVEL}"
echo_info
if [ "$DO_GRAVITY_RESTORE" == "1" ]
then
MESSAGE="${UI_RESTORE_SECONDARY} ${UI_GRAVITY_NAME}"
echo_stat
sudo cp ${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_BACKUP_DATE}-${GRAVITY_FI}.backup ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
validate_gravity_permissions
fi
if [ "$DO_CUSTOM_RESTORE" == '1' ]
then
if [ -f ${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_DNSBACKUP_DATE}-${CUSTOM_DNS}.backup ]
then
MESSAGE="${UI_RESTORE_SECONDARY} ${UI_CUSTOM_NAME}"
echo_stat
sudo cp ${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_DNSBACKUP_DATE}-${CUSTOM_DNS}.backup ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
validate_custom_permissions
fi
fi
if [ "$DO_CNAME_RESTORE" == '1' ]
then
if [ -f ${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_CNAMEBACKUP_DATE}-${CNAME_CONF}.backup ]
then
MESSAGE="${UI_RESTORE_SECONDARY} ${UI_CNAME_NAME}"
echo_stat
sudo cp ${LOCAL_FOLDR}/${BACKUP_FOLD}/${INPUT_CNAMEBACKUP_DATE}-${CNAME_CONF}.backup ${DNSMAQ_DIR}/${CNAME_CONF} >/dev/null 2>&1
error_validate
validate_cname_permissions
fi
fi
pull_gs_reload
MESSAGE="${UI_RESTORE_PUSH_PROMPT}"
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
MESSAGE="${UI_RESTORE_PUSH_NOPUSH}"
echo_info
logs_export
exit_withchange
else
MESSAGE="${UI_INVALID_SELECTION} - ${UI_RESTORE_PUSH_NOPUSH}"
echo_warn
logs_export
exit_withchange
fi
}

View File

@ -1,71 +0,0 @@
# 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}"
echo_good
MESSAGE="Creating sudoers.d template file"
echo_stat
NEW_SUDO_USER=$(whoami)
echo -e "${NEW_SUDO_USER} ALL=(ALL) NOPASSWD: ALL" > ${LOCAL_FOLDR}/templates/gs-nopasswd.sudo
error_validate
MESSAGE="Installing sudoers.d file on $HOSTNAME"
echo_stat
sudo install -m 0440 ${LOCAL_FOLDR}/templates/gs-nopasswd.sudo /etc/sudoers.d/gs-nopasswd
error_validate
exit_withchange
}
## Root Check
function root_check {
if [ ! "$EUID" -ne 0 ]
then
TASKTYPE='ROOT'
MESSAGE="${MESSAGE} ${TASKTYPE}"
echo_fail
MESSAGE="${PROGRAM} should not run as 'root'"
echo_warn
exit_nochange
fi
}
function new_root_check {
CURRENTUSER=$(whoami)
if [ ! "$EUID" -ne 0 ]
then
LOCALADMIN=""
else
# Check Sudo
SUDOCHECK=$(groups ${CURRENTUSER} | grep -e 'sudo' -e 'wheel')
if [ "$SUDOCHECK" == "" ]
then
LOCALADMIN="nosudo"
else
LOCALADMIN="sudo"
fi
fi
if [ "$LOCALADMIN" == "nosudo" ]
then
TASKTYPE='ROOT'
MESSAGE="${MESSAGE} ${TASKTYPE}"
echo_fail
MESSAGE="${CURRENTUSER} has insufficent user rights for ${PROGRAM}"
echo_warn
exit_nochange
fi
}

View File

@ -1,219 +0,0 @@
# 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}"
echo_good
show_target
validate_gs_folders
validate_ph_folders
if [ "${INCLUDE_CNAME}" == "1" ]
then
validate_dns_folders
fi
validate_sqlite3
validate_os_sshpass
smart_gs
exit
}
## Smart Sync Function
function smart_gs {
MESSAGE="Starting ${TASKTYPE} Analysis"
echo_info
previous_md5
md5_compare
backup_settime
PRIDBCHANGE="0"
SECDBCHANGE="0"
PRICLCHANGE="0"
SECCLCHANGE="0"
PRICNCHANGE="0"
SECCNCHANGE="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} Have Changed"
echo_warn
PRIDBDATE=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "stat -c %Y ${RIHOLE_DIR}/${GRAVITY_FI}")
SECDBDATE=$(stat -c %Y ${PIHOLE_DIR}/${GRAVITY_FI})
if (( "$PRIDBDATE" >= "$SECDBDATE" ))
then
MESSAGE="Primary ${GRAVITY_FI} Last Changed"
echo_warn
pull_gs_grav
PULLRESTART="1"
else
MESSAGE="Secondary ${GRAVITY_FI} Last Changed"
echo_warn
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} Have Changed"
echo_warn
PRICLDATE=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "stat -c %Y ${RIHOLE_DIR}/${CUSTOM_DNS}")
SECCLDATE=$(stat -c %Y ${PIHOLE_DIR}/${CUSTOM_DNS})
if (( "$PRICLDATE" >= "$SECCLDATE" ))
then
MESSAGE="Primary ${CUSTOM_DNS} Last Changed"
echo_warn
pull_gs_cust
PULLRESTART="1"
else
MESSAGE="Secondary ${CUSTOM_DNS} Last Changed"
echo_warn
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 [ "${primaryCNMD5}" != "${last_primaryCNMD5}" ]
then
PRICNCHANGE="1"
fi
if [ "${secondCNMD5}" != "${last_secondCNMD5}" ]
then
SECCNCHANGE="1"
fi
if [ "$INCLUDE_CNAME" == "1" ]
then
if [ -f "${DNSMAQ_DIR}/${CNAME_CONF}" ]
then
if [ "${PRICNCHANGE}" == "${SECCNCHANGE}" ]
then
if [ "${PRICNCHANGE}" != "0" ]
then
MESSAGE="Both ${CNAME_CONF} Have Changed"
echo_warn
PRICNDATE=$(${SSHPASSWORD} ${SSH_CMD} -p ${SSH_PORT} -i "$HOME/${SSH_PKIF}" ${REMOTE_USER}@${REMOTE_HOST} "stat -c %Y ${RNSMAQ_DIR}/${CNAME_CONF}")
SECCNDATE=$(stat -c %Y ${DNSMAQ_DIR}/${CNAME_CONF})
if (( "$PRICNDATE" >= "$SECCNDATE" ))
then
MESSAGE="Primary ${CNAME_CONF} Last Changed"
echo_warn
pull_gs_cname
PULLRESTART="1"
else
MESSAGE="Secondary ${CNAME_CONF} Last Changed"
echo_warn
push_gs_cname
PUSHRESTART="1"
fi
fi
else
if [ "${PRICNCHANGE}" != "0" ]
then
pull_gs_cname
PULLRESTART="1"
elif [ "${SECCNCHANGE}" != "0" ]
then
push_gs_cname
PUSHRESTART="1"
fi
fi
else
pull_gs_cname
PULLRESTART="1"
fi
fi
if [ "$PULLRESTART" == "1" ]
then
pull_gs_reload
fi
if [ "$PUSHRESTART" == "1" ]
then
push_gs_reload
fi
md5_recheck
backup_cleanup
logs_export
exit_withchange
}

View File

@ -1,149 +0,0 @@
# 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 {
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
}
## Determine SSH Pathways
function create_rsynccmd {
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
}
## Detect SSH-KEYGEN
function detect_sshkeygen {
MESSAGE="Validating SSH-KEYGEN install"
echo_stat
if hash ssh-keygen >/dev/null 2>&1
then
echo_good
else
echo_fail
MESSAGE="SSH-KEYGEN is required on $HOSTNAME"
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} file"
echo_info
else
if hash ssh-keygen >/dev/null 2>&1
then
MESSAGE="Generating ~/${SSH_PKIF} file"
echo_stat
ssh-keygen -q -P "" -t rsa -f $HOME/${SSH_PKIF} >/dev/null 2>&1
error_validate
else
MESSAGE="No SSH-KEYGEN available"
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 to ${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 to ${REMOTE_HOST}"
echo_warn
fi
fi
}
## Detect SSH & RSYNC
function detect_ssh {
MESSAGE="${UI_VALIDATING} ${UI_CORE_OPENSSH}"
echo_stat
if hash ssh 2>/dev/null
then
echo_good
SSH_CMD='ssh'
elif hash dbclient 2>/dev/null
then
echo_fail
MESSAGE="${UI_DROPBEAR_DEP}"
echo_warn
exit_nochange
else
echo_fail
exit_nochange
fi
MESSAGE="${UI_VALIDATING} ${UI_CORE_RSYNC}"
echo_stat
if hash rsync 2>/dev/null
then
echo_good
else
echo_fail
echo_warn
exit_nochange
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="${LOCAL_FOLDR}/gs.test"
create_rsynccmd
MESSAGE="Cleaning up local test file"
echo_stat
rm ${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="${UI_CORE_UC_PRIMARY} ${UI_CORE_APP}: ${REMOTE_USER}@${REMOTE_HOST}"
echo_info
detect_ssh
}

View File

@ -1,117 +0,0 @@
# GRAVITY SYNC BY VMSTAN #####################
# gs-ui.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!
# Interface Settings
UI_GRAVITY_NAME='Domain Database'
UI_CUSTOM_NAME='Local DNS Records'
UI_CNAME_NAME='Local DNS CNAMEs'
# Core
UI_INVALID_SELECTION='Invalid selection'
UI_INVALID_DNS_CONFIG='Invalid DNS replication settings in'
UI_CORE_MISSING='Missing'
UI_CORE_LOADING='Loading'
UI_CORE_EVALUATING='Evaluating arguments'
UI_CORE_INIT="Initalizing ${PROGRAM} (${VERSION})"
UI_CORE_RELOCATING='Relocating'
UI_CORE_APP='Pi-hole'
UI_CORE_APP_DNS='DNSMASQ'
UI_CORE_APP_SQL='SQLITE3'
UI_CORE_OPENSSH='OpenSSH'
UI_CORE_RSYNC='RSYNC'
UI_CORE_UC_PRIMARY='Primary'
UI_CORE_UC_SECONDARY='Secondary'
# Exit
UI_EXIT_CALC_END='after'
UI_EXIT_ABORT='aborted'
UI_EXIT_COMPLETE='completed'
UI_EXIT_CALC_TIMER='seconds'
# Hashing
UI_HASHING_HASHING='Hashing the primary'
UI_HASHING_COMPARING='Comparing to the secondary'
UI_HASHING_DIFFERNCE='Differences detected in the'
UI_HASHING_DETECTED='has been detected on the'
UI_HASHING_NOTDETECTED='not detected on the'
UI_HASHING_PRIMARY='primary host'
UI_HASHING_SECONDARY='secondary host'
UI_HASHING_REQUIRED='Replication of Pi-hole settings is required'
UI_HASHING_NOREP='No replication is required at this time'
UI_HASHING_DIAGNOSTICS='Performing replicator diagnostics'
UI_HASHING_REHASHING='Rehashing the primary'
UI_HASHING_RECOMPARING='Recomparing to the secondary'
# Validation
UI_VALIDATING='Validating configuration of'
UI_VALIDATING_FAIL_CONTAINER='Unable to validate running container instance of'
UI_VALIDATING_FAIL_FOLDER='Unable to validate configuration folder for'
UI_VALIDATING_FAIL_BINARY='Unable to validate the availibility of'
UI_COMPENSATE='Attempting to compensate'
UI_SET_FILE_OWNERSHIP='Setting file ownership on'
UI_SET_FILE_PERMISSION='Setting file permissions on'
UI_VAL_FILE_OWNERSHIP='Validating file ownership on'
UI_VAL_FILE_PERMISSION='Validating file permissions on'
UI_VAL_GS_FOLDERS="Validating ${PROGRAM} folders on $HOSTNAME"
UI_VAL_GS_FOLDERS_FAIL="Unable to validate ${PROGRAM} folders on $HOSTNAME"
# Configuration
UI_DROPBEAR_DEP='Dropbear support has been deprecated'
# Pull/Push
UI_PULL_PRIMARY='Pulling the primary'
UI_PUSH_SECONDARY='Pushing the secondary'
UI_REPLACE_SECONDARY='Replacing the secondary'
UI_PULL_RELOAD_WAIT='Isolating regeneration pathways'
UI_PUSH_RELOAD_WAIT='Inverting tachyon pulses'
UI_FTLDNS_CONFIG_UPDATE='Updating secondary FTLDNS configuration'
UI_FTLDNS_CONFIG_RELOAD='Reloading secondary FTLDNS services'
UI_FTLDNS_CONFIG_PUSH_UPDATE='Updating primary FTLDNS configuration'
UI_FTLDNS_CONFIG_PUSH_RELOAD='Reloading primary FTLDNS services'
# Logging
UI_LOGGING_SUCCESS='Logging successful'
UI_LOGGING_HASHES='Saving the updated hashes from this replication'
UI_LOGGING_DISPLAY='Displaying output of previous jobs'
UI_LOGGING_EMPTY='is empty'
UI_LOGGING_MISSING='is missing'
UI_LOGGING_RECENT_COMPLETE='Recent complete executions of'
# Backup
UI_BACKUP_PRIMARY='Performing backup of primary'
UI_BACKUP_COPY='Pulling backup of primary'
UI_BACKUP_SECONDARY='Performing backup of secondary'
UI_BACKUP_PURGE='Purging redundant backups on secondary Pi-hole instance'
UI_BACKUP_REMAIN='days of backups remain'
UI_BACKUP_INTEGRITY="Checking ${UI_GRAVITY_NAME} backup integrity"
UI_BACKUP_INTEGRITY_FAILED='Integrity check has failed for the primary'
UI_BACKUP_INTEGRITY_DELETE='Removing failed backup'
UI_BACKUP_DELETE_ALL='All backup files purged'
# Restore
UI_RESTORE_WARNING="This will overwrite your current Pi-hole settings on $HOSTNAME with a previous version!"
UI_RESTORE_INVALID='Invalid restoration request'
UI_RESTORE_SELECT_DATE='Select backup date from which to restore the'
UI_RESTORE_SKIPPING='Skipping restore of'
UI_RESTORE_BACKUP_SELECTED='backup selected for restoration'
UI_RESTORE_BACKUP_UNAVAILABLE='backups are unavailable'
UI_RESTORE_FROM='restoring from'
UI_RESTORE_TIME_TRAVEL='Preparing calculations for time travel'
UI_RESTORE_SECONDARY='Restoring the secondary'
UI_RESTORE_PUSH_PROMPT='Do you want to push the restored configuration to the primary Pi-hole? (Y/N)'
UI_RESTORE_PUSH_NOPUSH="Configuration will not be pushed to the primaryp Pi-hole"
# Purge
UI_PURGE_MATRIX_ALIGNMENT='Realigning dilithium crystal matrix'
UI_PURGE_DELETE_SSH_KEYS='Deleting SSH key-files'
UI_PURGE_CLEANING_DIR="Purging ${PROGRAM} directory"
# Automation
UI_AUTO_CRON_EXISTS='Automation task already exists in crontab'
UI_AUTO_CRON_DISPLAY_FREQ='Select synchronization frequency (in minutes)'
UI_AUTO_CRON_SELECT_FREQ='Valid options are 5, 10, 15, 30 or 0 to disable (default: 15)'
UI_AUTO_CRON_SAVING='Saving new synchronization task to crontab'
UI_AUTO_CRON_DISABLED='Synchronization automation has been disabled'

View File

@ -1,306 +0,0 @@
# 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 "${LOCAL_FOLDR}/dev" ]
then
source ${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="Updater usage requires GitHub installation"
echo_warn
exit_nochange
else
MESSAGE="Downloading updates via GitHub"
echo_stat
git fetch --all >/dev/null 2>&1
error_validate
MESSAGE="Deploying the latest ${PROGRAM} code"
echo_stat
git reset --hard ${BRANCH} >/dev/null 2>&1
error_validate
fi
}
## Show Version
function show_version {
echo_lines
MESSAGE="${PURPLE}${PROGRAM}${NC} for Pi-hole"
echo_info
MESSAGE="${BLUE}https://github.com/vmstan/gravity-sync${NC}"
echo_info
if [ -f ${LOCAL_FOLDR}/dev ]
then
DEVVERSION="dev"
elif [ -f ${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: ${RED}${GITVERSION}${NC}"
else
MESSAGE="Latest version: ${GREEN}${GITVERSION}${NC}"
fi
fi
echo_info
echo_lines
}
function show_info() {
if [ -f ${LOCAL_FOLDR}/dev ]
then
DEVVERSION="-dev"
elif [ -f ${LOCAL_FOLDR}/beta ]
then
DEVVERSION="-beta"
else
DEVVERSION=""
fi
echo_lines
echo -e "${YELLOW}Local Software Versions${NC}"
echo -e "${PURPLE}Gravity Sync${NC} ${VERSION}${DEVVERSION}"
echo -e "${BLUE}Pi-hole${NC}"
if [ "${PH_IN_TYPE}" == "default" ]
then
pihole version
elif [ "${PH_IN_TYPE}" == "docker" ]
then
sudo docker exec -it pihole pihole -v
elif [ "${PH_IN_TYPE}" == "podman" ]
then
sudo podman exec -it pihole pihole -v
fi
uname -srm
echo -e "bash $BASH_VERSION"
ssh -V
rsync --version | grep version
SQLITE3_VERSION=$(sqlite3 --version)
echo -e "sqlite3 ${SQLITE3_VERSION}"
sudo --version | grep "Sudo version"
git --version
if hash docker 2>/dev/null
then
docker --version
fi
if hash podman 2>/dev/null
then
podman --version
fi
echo -e ""
echo -e "${YELLOW}Local/Secondary Instance Settings${NC}"
echo -e "Local Hostname: $HOSTNAME"
echo -e "Local Pi-hole Type: ${PH_IN_TYPE}"
echo -e "Local Pi-hole Config Directory: ${PIHOLE_DIR}"
echo -e "Local DNSMASQ Config Directory: ${DNSMAQ_DIR}"
echo -e "Local Gravity Sync Directory: ${LOCAL_FOLDR}"
if [ "${PH_IN_TYPE}" == "default" ]
then
echo -e "Local Pi-hole Binary Directory: ${PIHOLE_BIN}"
elif [ "${PH_IN_TYPE}" == "docker" ]
then
echo -e "Local Pi-hole Container Name: ${DOCKER_CON}"
echo -e "Local Docker Binary Directory: ${DOCKER_BIN}"
elif [ "${PH_IN_TYPE}" == "podman" ]
then
echo -e "Local Pi-hole Container Name: ${DOCKER_CON}"
echo -e "Local Podman Binary Directory: ${PODMAN_BIN}"
fi
echo -e "Local File Owner Settings: ${FILE_OWNER}"
if [ ${SKIP_CUSTOM} == '0' ]
then
echo -e "DNS Replication: Enabled (default)"
elif [ ${SKIP_CUSTOM} == '1' ]
then
echo -e "DNS Replication: Disabled (custom)"
else
echo -e "DNS Replication: Invalid Configuration"
fi
if [ ${INCLUDE_CNAME} == '1' ]
then
echo -e "CNAME Replication: Enabled (custom)"
elif [ ${INCLUDE_CNAME} == '0' ]
then
echo -e "CNAME Replication: Disabled (default)"
else
echo -e "CNAME Replication: Invalid Configuration"
fi
if [ ${VERIFY_PASS} == '1' ]
then
echo -e "Verify Operations: Enabled (default)"
elif [ ${VERIFY_PASS} == '0' ]
then
echo -e "Verify Operations: Disabled (custom)"
else
echo -e "Verify Operations: Invalid Configuration"
fi
if [ ${PING_AVOID} == '0' ]
then
echo -e "Ping Test: Enabled (default)"
elif [ ${PING_AVOID} == '1' ]
then
echo -e "Ping Test: Disabled (custom)"
else
echo -e "Ping Test: Invalid Configuration"
fi
if [ ${BACKUP_RETAIN} == '7' ]
then
echo -e "Backup Retention: 7 days (default)"
elif [ ${BACKUP_RETAIN} == '1' ]
then
echo -e "Backup Retention: 1 day (custom)"
else
echo -e "Backup Retention: ${BACKUP_RETAIN} days (custom)"
fi
BACKUP_FOLDER_SIZE=$(du -h ${LOCAL_FOLDR}/${BACKUP_FOLD} | sed 's/\s.*$//')
echo -e "Backup Folder Size: ${BACKUP_FOLDER_SIZE}"
echo -e ""
echo -e "${YELLOW}Remote/Primary Instance Settings${NC}"
echo -e "Remote Hostname/IP: ${REMOTE_HOST}"
echo -e "Remote Username: ${REMOTE_USER}"
echo -e "Remote Pi-hole Type: ${RH_IN_TYPE}"
echo -e "Remote Pi-hole Config Directory: ${RIHOLE_DIR}"
echo -e "Remote DNSMASQ Config Directory: ${RNSMAQ_DIR}"
if [ "${RH_IN_TYPE}" == "default" ]
then
echo -e "Remote Pi-hole Binary Directory: ${RIHOLE_BIN}"
elif [ "${RH_IN_TYPE}" == "docker" ]
then
echo -e "Remote Pi-hole Container Name: ${ROCKER_CON}"
echo -e "Remote Docker Binary Directory: ${ROCKER_BIN}"
elif [ "${RH_IN_TYPE}" == "podman" ]
then
echo -e "Remote Pi-hole Container Name: ${ROCKER_CON}"
echo -e "Remote Podman Binary Directory: ${RODMAN_BIN}"
fi
echo -e "Remote File Owner Settings: ${RILE_OWNER}"
echo_lines
}
## Devmode Task
function task_devmode {
TASKTYPE='DEV'
MESSAGE="${MESSAGE}: ${TASKTYPE}"
echo_good
if [ -f ${LOCAL_FOLDR}/dev ]
then
MESSAGE="Disabling ${TASKTYPE}"
echo_stat
rm -f ${LOCAL_FOLDR}/dev
error_validate
elif [ -f ${LOCAL_FOLDR}/beta ]
then
MESSAGE="Disabling BETA"
echo_stat
rm -f ${LOCAL_FOLDR}/beta
error_validate
MESSAGE="Enabling ${TASKTYPE}"
echo_stat
touch ${LOCAL_FOLDR}/dev
error_validate
else
MESSAGE="Enabling ${TASKTYPE}"
echo_stat
touch ${LOCAL_FOLDR}/dev
error_validate
MESSAGE="Checking available branches"
echo_stat
git fetch --all >/dev/null 2>&1
error_validate
git branch -r
MESSAGE="Select GitHub branch to update against"
echo_need
read INPUT_BRANCH
echo -e "BRANCH='${INPUT_BRANCH}'" >> ${LOCAL_FOLDR}/dev
fi
update_gs
exit_withchange
}
## Update Task
function task_update {
TASKTYPE='UPDATE'
MESSAGE="${MESSAGE}: ${TASKTYPE}"
echo_good
dbclient_warning
update_gs
exit_withchange
}
## Version Task
function task_version {
TASKTYPE='VERSION'
MESSAGE="${MESSAGE}: ${TASKTYPE}"
echo_good
show_version
exit_nochange
}
## Info Task
function task_info() {
TASKTYPE='INFO'
MESSAGE="${MESSAGE}: ${TASKTYPE}"
echo_good
show_info
exit_nochange
}

View File

@ -1,265 +0,0 @@
# 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="${UI_VAL_GS_FOLDERS}"
echo_stat
if [ ! -d ${LOCAL_FOLDR} ] || [ ! -d ${LOCAL_FOLDR}/${BACKUP_FOLD} ] || [ ! -d ${LOCAL_FOLDR}/settings ] || [ ! -d ${LOG_PATH} ]
then
MESSAGE="${UI_VAL_GS_FOLDERS_FAIL}"
echo_fail
exit_nochange
fi
echo_good
}
## Validate Pi-hole Folders
function validate_ph_folders {
MESSAGE="${UI_VALIDATING} ${UI_CORE_APP}"
echo_stat
if [ "$PH_IN_TYPE" == "default" ]
then
if [ ! -f ${PIHOLE_BIN} ]
then
MESSAGE="${UI_VALIDATING_FAIL_BINARY} ${UI_CORE_APP}"
echo_fail
exit_nochange
fi
elif [ "$PH_IN_TYPE" == "docker" ]
then
FTLCHECK=$(sudo docker container ls | grep "${CONTAIMAGE}")
if [ "$FTLCHECK" == "" ]
then
MESSAGE="${UI_VALIDATING_FAIL_CONTAINER} ${UI_CORE_APP}"
echo_fail
exit_nochange
fi
elif [ "$PH_IN_TYPE" == "podman" ]
then
FTLCHECK=$(sudo podman container ls | grep "${CONTAIMAGE}")
if [ "$FTLCHECK" == "" ]
then
MESSAGE="${UI_VALIDATING_FAIL_CONTAINER} ${UI_CORE_APP}"
echo_fail
exit_nochange
fi
fi
if [ ! -d ${PIHOLE_DIR} ]
then
MESSAGE="${UI_VALIDATING_FAIL_FOLDER} ${UI_CORE_APP}"
echo_fail
exit_nochange
fi
echo_good
}
## Validate DNSMASQ Folders
function validate_dns_folders {
MESSAGE="${UI_VALIDATING} ${UI_CORE_APP_DNS}"
echo_stat
if [ ! -d ${DNSMAQ_DIR} ]
then
MESSAGE="${UI_VALIDATING_FAIL_FOLDER} ${UI_CORE_APP_DNS}"
echo_fail
exit_nochange
fi
echo_good
}
## Validate SQLite3
function validate_sqlite3 {
MESSAGE="${UI_VALIDATING} ${UI_CORE_APP_SQL}"
echo_stat
if hash sqlite3 2>/dev/null
then
echo_good
else
MESSAGE="${UI_VALIDATING_FAIL_BINARY} ${UI_CORE_APP_SQL}"
echo_warn
fi
}
## Validate SSHPASS
function validate_os_sshpass {
MESSAGE="Connecting 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="${UI_DROPBEAR_DEP}"
echo_warn
fi
fi
}
## Validate Domain Database Permissions
function validate_gravity_permissions() {
MESSAGE="${UI_VAL_FILE_OWNERSHIP} ${UI_GRAVITY_NAME}"
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="${UI_COMPENSATE}"
echo_warn
MESSAGE="${UI_SET_FILE_OWNERSHIP} ${UI_GRAVITY_NAME}"
echo_stat
sudo chown ${FILE_OWNER} ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
fi
MESSAGE="${UI_VAL_FILE_PERMISSION} of ${UI_GRAVITY_NAME}"
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="${UI_COMPENSATE}"
echo_warn
MESSAGE="${UI_SET_FILE_PERMISSION} ${UI_GRAVITY_NAME}"
echo_stat
sudo chmod 664 ${PIHOLE_DIR}/${GRAVITY_FI} >/dev/null 2>&1
error_validate
fi
}
## Validate Local DNS Records Permissions
function validate_custom_permissions() {
MESSAGE="${UI_VAL_FILE_OWNERSHIP} ${UI_CUSTOM_NAME}"
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="${UI_COMPENSATE}"
echo_warn
MESSAGE="${UI_SET_FILE_OWNERSHIP} ${UI_CUSTOM_NAME}"
echo_stat
sudo chown root:root ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
fi
MESSAGE="${UI_VAL_FILE_PERMISSION} ${UI_CUSTOM_NAME}"
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="${UI_COMPENSATE}"
echo_warn
MESSAGE="${UI_SET_FILE_PERMISSION} ${UI_CUSTOM_NAME}"
echo_stat
sudo chmod 644 ${PIHOLE_DIR}/${CUSTOM_DNS} >/dev/null 2>&1
error_validate
fi
}
## Validate Local DNS CNAME Permissions
function validate_cname_permissions() {
MESSAGE="${UI_VAL_FILE_OWNERSHIP} ${UI_CNAME_NAME}"
echo_stat
CNAMELS_OWN=$(ls -ld ${DNSMAQ_DIR}/${CNAME_CONF} | awk '{print $3 $4}')
if [ "$CNAMELS_OWN" == "rootroot" ]
then
echo_good
else
echo_fail
MESSAGE="${UI_COMPENSATE}"
echo_warn
MESSAGE="${UI_SET_FILE_OWNERSHIP} ${UI_CNAME_NAME}"
echo_stat
sudo chown root:root ${DNSMAQ_DIR}/${CNAME_CONF} >/dev/null 2>&1
error_validate
fi
MESSAGE="${UI_VAL_FILE_PERMISSION} ${UI_CNAME_NAME}"
echo_stat
CNAMELS_RWE=$(namei -m ${DNSMAQ_DIR}/${CNAME_CONF} | grep -v f: | grep ${CNAME_CONF} | awk '{print $1}')
if [ "$CNAMELS_RWE" == "-rw-r--r--" ]
then
echo_good
else
echo_fail
MESSAGE="${UI_COMPENSATE}"
echo_warn
MESSAGE="${UI_SET_FILE_PERMISSION} ${UI_CNAME_NAME}"
echo_stat
sudo chmod 644 ${DNSMAQ_DIR}/${CNAME_CONF} >/dev/null 2>&1
error_validate
fi
}

View File

@ -1,5 +0,0 @@
Your log files will be stored here.
They will be ignored by any git updates.
This file is required for Git to create the folder.
It serves no other purpose.
The needs of the many, outweigh the needs of the few.

View File

@ -1,279 +0,0 @@
# 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"
PHFAILCOUNT="0"
CURRENTUSER=$(whoami)
# Header
echo -e ""
echo -e " ..::-----::.. ..::------::. "
echo -e " .:----:::::::----:. .:::--:::::---===-: "
echo -e " :---:. .:---: +##+:. .:-===-. "
echo -e " .---:. :---: -*##*: .-===: "
echo -e " .---. :---: -++*+. .==+- "
echo -e " ---. = :---: :====. - .=++."
echo -e ":--: -=-. :---::---:. -=-. :++="
echo -e "---. .:-=====-:.. ------. .:-=====-:.. .+++"
echo -e "---. .:===-. :------: .:===-. :+++"
echo -e ".--: .=: :---: :---: =: -++-"
echo -e " :--: .. .---:. :--:: .. -=+= "
echo -e " :--: .---:. :-::: -===. "
echo -e " :---: :---: ::::: .:==== "
echo -e " :---::.. ..::---:. ::::::.. ..:-===-. "
echo -e " .::-----------::. .::---------===-: "
echo -e ""
echo -e "${YELLOW}Gravity Sync by ${BLUE}@vmstan${NC}"
echo -e "${CYAN}https://github.com/vmstan/gravity-sync${NC}"
echo -e "========================================================"
echo -e "[${GREEN}${NC}] Checking Short Range Sensors"
# Check Root
echo -e "[${YELLOW}i${NC}] ${YELLOW}Validating System Authorization${NC}"
if [ ! "$EUID" -ne 0 ]
then
echo -e "[${GREEN}${NC}] Current User (${CURRENTUSER}) is ROOT"
LOCALADMIN="root"
else
if hash sudo 2>/dev/null
then
echo -e "[${GREEN}${NC}] Sudo Utility Detected"
# Check Sudo
sudo --validate
if [ "$?" != "0" ]
then
echo -e "[${RED}${NC}] Current User (${CURRENTUSER}) Cannot SUDO"
CROSSCOUNT=$((CROSSCOUNT+1))
LOCALADMIN="nosudo"
else
echo -e "[${GREEN}${NC}] Current User (${CURRENTUSER}) Has SUDO Powers"
LOCALADMIN="sudo"
fi
else
echo -e "[${RED}${NC}] Sudo Utility Not Detected"
CROSSCOUNT=$((CROSSCOUNT+1))
LOCALADMIN="nosudo"
fi
if [ "$LOCALADMIN" != "sudo" ]
then
echo -e "[${RED}${NC}] Current User (${CURRENTUSER}) Cannot SUDO"
CROSSCOUNT=$((CROSSCOUNT+1))
LOCALADMIN="nosudo"
fi
fi
echo -e "[${YELLOW}i${NC}] ${YELLOW}Scanning for Required Components${NC}"
# Check OpenSSH
if hash ssh 2>/dev/null
then
echo -e "[${GREEN}${NC}] OpenSSH Binaries Detected"
else
echo -e "[${RED}${NC}] OpenSSH Binaries Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check Rsync
if hash rsync 2>/dev/null
then
echo -e "[${GREEN}${NC}] RSYNC Binaries Detected"
else
echo -e "[${RED}${NC}] RSYNC Binaries Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check Sudo
if hash sudo 2>/dev/null
then
echo -e "[${GREEN}${NC}] SUDO Binaries Detected"
else
echo -e "[${RED}${NC}] SUDO Binaries Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check Crontab
if hash crontab 2>/dev/null
then
echo -e "[${GREEN}${NC}] CRONTAB Binaries Detected"
else
echo -e "[${RED}${NC}] CRONTAB Binaries Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check SQLITE3
if hash sqlite3 2>/dev/null
then
echo -e "[${GREEN}${NC}] SQLITE3 Binaries Detected"
else
echo -e "[${RED}${NC}] SQLITE3 Binaries Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# Check GIT
if hash git 2>/dev/null
then
echo -e "[${GREEN}${NC}] GIT Binaries Detected"
else
echo -e "[${RED}${NC}] GIT Binaries Not Installed"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
echo -e "[${YELLOW}i${NC}] ${YELLOW}Performing Warp Core Diagnostics${NC}"
# Check Pihole
if hash pihole 2>/dev/null
then
echo -e "[${GREEN}${NC}] Local Pi-hole Install Detected"
else
echo -e "[${PURPLE}!${NC}] ${PURPLE}No Local Pi-hole Install Detected${NC}"
# echo -e "[${PURPLE}!${NC}] ${PURPLE}Attempting To Compensate${NC}"
if hash docker 2>/dev/null
then
echo -e "[${GREEN}${NC}] Docker Binaries Detected"
if [ "$LOCALADMIN" == "sudo" ]
then
FTLCHECK=$(sudo docker container ls | grep 'pihole/pihole')
elif [ "$LOCALADMIN" == "nosudo" ]
then
echo -e "[${PURPLE}!${NC}] ${PURPLE}No Docker Pi-hole Container Detected (unable to scan)${NC}"
# CROSSCOUNT=$((CROSSCOUNT+1))
PHFAILCOUNT=$((PHFAILCOUNT+1))
else
FTLCHECK=$(docker container ls | grep 'pihole/pihole')
fi
if [ "$LOCALADMIN" != "nosudo" ]
then
if [ "$FTLCHECK" != "" ]
then
echo -e "[${GREEN}${NC}] Pi-Hole Docker Container Detected"
else
echo -e "[${PURPLE}!${NC}] ${PURPLE}No Docker Pi-hole Container Detected${NC}"
# CROSSCOUNT=$((CROSSCOUNT+1))
PHFAILCOUNT=$((PHFAILCOUNT+1))
fi
fi
elif hash podman 2>/dev/null
then
echo -e "[${GREEN}${NC}] Podman Binaries Detected"
if [ "$LOCALADMIN" == "sudo" ]
then
FTLCHECK=$(sudo podman container ls | grep 'pihole/pihole')
elif [ "$LOCALADMIN" == "nosudo" ]
then
echo -e "[${PURPLE}!${NC}] ${PURPLE}No Podman Pi-hole Container Detected (unable to scan)${NC}"
# CROSSCOUNT=$((CROSSCOUNT+1))
PHFAILCOUNT=$((PHFAILCOUNT+1))
else
FTLCHECK=$(podman container ls | grep 'pihole/pihole')
fi
if [ "$LOCALADMIN" != "nosudo" ]
then
if [ "$FTLCHECK" != "" ]
then
echo -e "[${GREEN}${NC}] Pi-Hole Podman Container Detected"
else
echo -e "[${PURPLE}!${NC}] ${PURPLE}No Podman Pi-hole Container Detected${NC}"
# CROSSCOUNT=$((CROSSCOUNT+1))
PHFAILCOUNT=$((PHFAILCOUNT+1))
fi
fi
else
# echo -e "[${RED}✗${NC}] No Local Pi-hole Install Detected"
echo -e "[${PURPLE}!${NC}] ${PURPLE}No Docker Pi-hole Alternative Detected${NC}"
# CROSSCOUNT=$((CROSSCOUNT+1))
PHFAILCOUNT=$((PHFAILCOUNT+1))
fi
fi
if [ "$PHFAILCOUNT" != "0" ]
then
echo -e "[${RED}${NC}] No Usable Pi-hole Install Detected"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
# echo -e "[${YELLOW}i${NC}] ${YELLOW}Target Folder Analysis${NC}"
if [ "$GS_INSTALL" == "secondary" ]
then
if [ "$LOCALADMIN" == "sudo" ]
then
THISDIR=$(pwd)
if [ "$THISDIR" != "$HOME" ]
then
echo -e "[${RED}${NC}] ${CURRENTUSER} Must Install to $HOME"
echo -e "[${PURPLE}!${NC}] ${PURPLE}Use 'root' Account to Install in $THISDIR${NC}"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
fi
fi
if [ -d gravity-sync ]
then
echo -e "[${RED}${NC}] Folder gravity-sync Already Exists"
echo -e "[${PURPLE}!${NC}] ${PURPLE}Use './gravity-sync.sh update' to Update Instead${NC}"
CROSSCOUNT=$((CROSSCOUNT+1))
fi
echo -e "[${YELLOW}i${NC}] ${YELLOW}Status Report${NC}"
# Combine Outputs
if [ "$CROSSCOUNT" != "0" ]
then
echo -e "[${RED}*${NC}] ${RED}${CROSSCOUNT} Critical Issue(s) Detected${NC}"
echo -e "[${PURPLE}!${NC}] ${PURPLE}Please Correct Failures and Re-Execute${NC}"
echo -e "[${YELLOW}i${NC}] ${YELLOW}Installation Exiting (without changes)${NC}"
else
echo -e "[${YELLOW}i${NC}] ${YELLOW}Executing Gravity Sync Deployment${NC}"
if [ "$LOCALADMIN" == "sudo" ]
then
echo -e "[${BLUE}>${NC}] Creating Sudoers.d File"
touch /tmp/gs-nopasswd.sudo
echo -e "${CURRENTUSER} ALL=(ALL) NOPASSWD: ALL" > /tmp/gs-nopasswd.sudo
sudo install -m 0440 /tmp/gs-nopasswd.sudo /etc/sudoers.d/gs-nopasswd
fi
if [ "$GS_INSTALL" != "secondary" ]
then
echo -e "[${YELLOW}i${NC}] Gravity Sync Preperation Complete"
echo -e "[${YELLOW}i${NC}] Execute on Installer on Secondary"
echo -e "[${YELLOW}i${NC}] Check Documentation for Instructions"
echo -e "[${YELLOW}i${NC}] Installation Exiting (without changes)"
else
echo -e "[${BLUE}>${NC}] Creating Gravity Sync Directories"
if [ "$GS_DEV" != "" ]
then
git clone -b ${GS_DEV} https://github.com/vmstan/gravity-sync.git
else
git clone https://github.com/vmstan/gravity-sync.git
fi
echo -e "[${BLUE}>${NC}] Starting Gravity Sync Configuration"
echo -e "========================================================"
./gravity-sync/gravity-sync.sh configure <&1
# 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

View File

@ -1,5 +0,0 @@
Your configuration file will be stored here.
It will be ignored by any git updates.
This file is required for Git to create the folder.
It serves no other purpose.
I have been, and always shall be, your friend.

View File

@ -1,64 +1,21 @@
# REQUIRED SETTINGS ######################
# REQUIRED SETTINGS ##########################
# Primary Pi-hole host (in IP or DNS name)
REMOTE_HOST='192.168.1.10'
REMOTE_HOST=''
REMOTE_USER=''
# User account on primary with SUDO rights
REMOTE_USER='pi'
# CUSTOM VARIABLES ###########################
# STANDARD VARIABLES #########################
# Pi-hole Folder/File Customization - Only need to be customized when using containers
# LOCAL_PIHOLE_DIRECTORY='' # Local Pi-hole data directory
# REMOTE_PIHOLE_DIRECTORY='' # Remote Pi-hole data directory
# LOCAL_DNSMASQ_DIRECTORY='' # Local DNSMASQ/FTL data directory
# REMOTE_DNSMASQ_DIRECTORY='' # Remote DNSMASQ/FTL data directory
# LOCAL_FILE_OWNER='' # Local file owner for Pi-hole
# REMOTE_FILE_OWNER='' # Remote file owner for Pi-hole
### Installation Types
# PH_IN_TYPE='' # Pi-hole install type, `default`, `docker`, or `podman` (local)
# RH_IN_TYPE='' # Pi-hole install type, `default`, `docker`, or `podman` (remote)
# Pi-hole Docker/Podman container name - Docker will pattern match anything set below
# LOCAL_DOCKER_CONTAINER='' # Local Pi-hole container name
# REMOTE_DOCKER_CONTAINER='' # Remote Pi-hole container name
### Pi-hole Folder/File Customization
# PIHOLE_DIR='' # default Pi-hole data directory (local)
# RIHOLE_DIR='' # default Pi-hole data directory (remote)
# DNSMAQ_DIR='' # default DNSMASQ data directory (local)
# RNSMAQ_DIR='' # default DNSMASQ data directory (remote)
# PIHOLE_BIN='' # default Pi-hole binary directory (local)
# RIHOLE_BIN='' # default Pi-hole binary directory (remote)
# DOCKER_BIN='' # default Docker binary directory (local)
# ROCKER_BIN='' # default Docker binary directory (remote)
# PODMAN_BIN='' # default Podman binary directory (local)
# RODMAN_BIN='' # default Podman binary directory (remote)
# FILE_OWNER='' # default Pi-hole file owner and group (local)
# RILE_OWNER='' # default Pi-hole file owner and group (remote)
# DOCKER_CON='' # default Pi-hole container name (local)
# ROCKER_CON='' # default Pi-hole container name (remote)
# CONTAIMAGE='' # official Pi-hole container image
# GRAVITY_FI='' # default Pi-hole database file
# CUSTOM_DNS='' # default Pi-hole local DNS lookups
# CNAME_CONF='' # default DNSMASQ CNAME alias file
# GSLAN_CONF='' # default DNSMASQ GS managed file
### Interaction Customization
# VERIFY_PASS='' # replace in gravity-sync.conf to overwrite
# SKIP_CUSTOM='' # replace in gravity-sync.conf to overwrite
# INCLUDE_CNAME='' # replace in gravity-sync.conf to overwrite
# DATE_OUTPUT='' # replace in gravity-sync.conf to overwrite
# PING_AVOID='' # replace in gravity-sync.conf to overwrite
# ROOT_CHECK_AVOID='' # replace in gravity-sync.conf to overwrite
### Backup Customization
# BACKUP_RETAIN='' # replace in gravity-sync.conf to overwrite
# BACKUP_TIMEOUT='' # replace in gravity-sync.conf to overwrite
# BACKUP_INTEGRITY_WAIT='' # time to wait after backup for integrity check
### SSH Customization
# SSH_PORT='' # default SSH port
# SSH_PKIF='' # default local SSH key
### GS Folder/File Locations
# CONFIG_FILE='' # must exist with primary host/user configured
# GS_FILENAME='' # must exist because it's this script
# BACKUP_FOLD='' # must exist as subdirectory in LOCAL_FOLDR
# LOG_PATH='' # replace in gravity-sync.conf to overwrite
# SYNCING_LOG='' # replace in gravity-sync.conf to overwrite
# CRONJOB_LOG='' # replace in gravity-sync.conf to overwrite
# HISTORY_MD5='' # replace in gravity-sync.conf to overwrite
### OS Settings
# BASH_PATH='' # default OS bash path
# HIDDEN FIGURES #############################
# See https://github.com/vmstan/gravity-sync/wiki/Hidden-Figures

View File

@ -0,0 +1,12 @@
[Unit]
Description=Synchronize Pi-hole instances
After=network-online.target
Wants=gravity-sync.timer
[Service]
Type=simple
User=unknown
ExecStart=
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
[Unit]
Description=Synchronize Pi-hole instances
RefuseManualStart=no
RefuseManualStop=no
Requires=gravity-sync.service
[Timer]
Unit=gravity-sync.service
Persistent=true
OnBootSec=120
OnUnitInactiveSec=5m
RandomizedDelaySec=5m
[Install]
WantedBy=timers.target

16
update.sh Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
GS_LOCAL_REPO='/etc/gravity-sync/.gs'
if [ -f "${GS_LOCAL_REPO}/dev" ]; then
source ${GS_LOCAL_REPO}/dev
else
BRANCH='origin/master'
fi
if [ "$BRANCH" != "origin/master" ]; then
echo -e "Pulling from ${BRANCH}"
fi
(cd ${GS_LOCAL_REPO}; sudo git fetch --all; sudo git reset --hard ${BRANCH}; sudo cp gravity-sync /usr/local/bin; sudo git clean -fq)