Skip to content

Commit b1e4fd8

Browse files
authored
Merge branch 'master' into xn4p4lm-host-check-formatting-update
2 parents 0671226 + 9396a89 commit b1e4fd8

27 files changed

+937
-144
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
/backup.config
22
/data
33
/dist
4+
dash
5+
parallel

backup.config-example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ GHE_DATA_DIR="data"
1616
# be available for the past N days ...
1717
GHE_NUM_SNAPSHOTS=10
1818

19+
# Pruning snapshots can be scheduled outside of the backup process. If set to 'yes'
20+
# ghe-pruning-snapshots will need to be invoked separately via cron
21+
#GHE_PRUNING_SCHEDULED=yes
22+
23+
# If GHE_SKIP_CHECKS is set to true (or if --skip-checks is used with ghe-backup) then ghe-host-check
24+
# disk space validation and software version checks on the backup-host will be disabled.
25+
#GHE_SKIP_CHECKS=false
26+
1927
# The hostname of the GitHub appliance to restore. If you've set up a separate
2028
# GitHub appliance to act as a standby for recovery, specify its IP or hostname
2129
# here. The host to restore to may also be specified directly when running

bin/ghe-backup

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
#/ the MySQL database, instance settings, GitHub Pages data, etc.
66
#/
77
#/ OPTIONS:
8-
#/ -v | --verbose Enable verbose output.
9-
#/ -h | --help Show this message.
10-
#/ --version Display version information.
8+
#/ -v | --verbose Enable verbose output.
9+
#/ -h | --help Show this message.
10+
#/ --version Display version information.
11+
#/ -i | --incremental Incremental backup
12+
#/ --skip-checks Skip storage/sw version checks
1113
#/
1214

1315
set -e
@@ -27,6 +29,14 @@ while true; do
2729
export GHE_VERBOSE=true
2830
shift
2931
;;
32+
-i|--incremental)
33+
export GHE_INCREMENTAL=true
34+
shift
35+
;;
36+
--skip-checks)
37+
export GHE_SKIP_CHECKS=true
38+
shift
39+
;;
3040
-*)
3141
echo "Error: invalid argument: '$1'" 1>&2
3242
exit 1
@@ -46,12 +56,36 @@ export CALLING_SCRIPT="ghe-backup"
4656

4757
# Setup progress tracking
4858
init-progress
59+
export PROGRESS_TOTAL=14 # Minimum number of steps in backup is 14
60+
echo "$PROGRESS_TOTAL" > /tmp/backup-utils-progress-total
4961
export PROGRESS_TYPE="Backup"
5062
echo "$PROGRESS_TYPE" > /tmp/backup-utils-progress-type
5163
export PROGRESS=0 # Used to track progress of backup
5264
echo "$PROGRESS" > /tmp/backup-utils-progress
53-
export PROGRESS_TOTAL=18 # Maximum number of steps in backup
5465

66+
OPTIONAL_STEPS=0
67+
# Backup actions+mssql
68+
if ghe-ssh "$GHE_HOSTNAME" -- 'ghe-config --true app.actions.enabled'; then
69+
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 2))
70+
fi
71+
72+
# Backup fsck
73+
if [ "$GHE_BACKUP_FSCK" = "yes" ]; then
74+
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 1))
75+
fi
76+
77+
# Backup minio
78+
if ghe-ssh "$GHE_HOSTNAME" -- 'ghe-config --true app.minio.enabled'; then
79+
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 1))
80+
fi
81+
82+
# Backup pages
83+
if [ "$GHE_BACKUP_PAGES" != "no" ]; then
84+
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 1))
85+
fi
86+
87+
PROGRESS_TOTAL=$((OPTIONAL_STEPS + PROGRESS_TOTAL)) # Minimum number of steps in backup is 14
88+
echo "$PROGRESS_TOTAL" > /tmp/backup-utils-progress-total
5589
# Check to make sure moreutils parallel is installed and working properly
5690
ghe_parallel_check
5791

@@ -149,17 +183,39 @@ if [ -f ../in-progress ]; then
149183
fi
150184
fi
151185

186+
# Perform a host connection check and establish the remote appliance version.
187+
# The version is available in the GHE_REMOTE_VERSION variable and also written
188+
# to a version file in the snapshot directory itself.
189+
ghe_remote_version_required
190+
echo "$GHE_REMOTE_VERSION" > version
191+
192+
# check that incremental settings are valid if set
193+
is_inc=$(is_incremental_backup_feature_on)
194+
195+
if [ "$is_inc" = true ]; then
196+
if [ "$GHE_VERSION_MAJOR" -lt 3 ]; then
197+
log_error "Can only perform incremental backups on enterprise version 3.10 or higher"
198+
exit 1
199+
fi
200+
if [ "$GHE_VERSION_MINOR" -lt 10 ]; then
201+
log_error "Can only perform incremental backups on enterprise version 3.10 or higher"
202+
exit 1
203+
fi
204+
205+
incremental_backup_check
206+
# If everything is ok, check if we have hit GHE_MAX_INCREMENTAL_BACKUPS, performing pruning actions if necessary
207+
check_for_incremental_max_backups
208+
# initialize incremental backup if it hasn't been done yet
209+
incremental_backup_init
210+
fi
211+
152212
echo "$GHE_SNAPSHOT_TIMESTAMP $$" > ../in-progress
153213
echo "$GHE_SNAPSHOT_TIMESTAMP $$" > "${GHE_DATA_DIR}/in-progress-backup"
154214

155215
START_TIME=$(date +%s)
156216
log_info "Starting backup of $GHE_HOSTNAME with backup-utils v$BACKUP_UTILS_VERSION in snapshot $GHE_SNAPSHOT_TIMESTAMP"
157217

158-
# Perform a host connection check and establish the remote appliance version.
159-
# The version is available in the GHE_REMOTE_VERSION variable and also written
160-
# to a version file in the snapshot directory itself.
161-
ghe_remote_version_required
162-
echo "$GHE_REMOTE_VERSION" > version
218+
163219

164220
if [ -n "$GHE_ALLOW_REPLICA_BACKUP" ]; then
165221
echo "Warning: backing up a high availability replica may result in inconsistent or unreliable backups."
@@ -269,6 +325,7 @@ echo \"$cmd_title\"
269325
ghe-backup-git-hooks || printf %s \"git-hooks \" >> \"$failures_file\"")
270326

271327
if [ "$GHE_BACKUP_STRATEGY" = "rsync" ]; then
328+
increment-progress-total-count 1
272329
cmd_title=$(log_info "Backing up Elasticsearch indices ...")
273330
commands+=("
274331
echo \"$cmd_title\"
@@ -302,7 +359,11 @@ if [ -z "$failures" ]; then
302359
rm -f "../current"
303360
ln -s "$GHE_SNAPSHOT_TIMESTAMP" "../current"
304361

305-
ghe-prune-snapshots
362+
if [[ $GHE_PRUNING_SCHEDULED != "yes" ]]; then
363+
ghe-prune-snapshots
364+
else
365+
log_info "Expired and incomplete snapshots to be pruned separately"
366+
fi
306367
else
307368
log_info "Skipping pruning snapshots, since some backups failed..."
308369
fi

bin/ghe-host-check

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,13 @@ if [ -z "$supported" ]; then
144144
exit 1
145145
fi
146146

147-
if [[ "$CALLING_SCRIPT" == "ghe-backup" ]]; then
147+
if [[ "$CALLING_SCRIPT" == "ghe-backup" && "$GHE_SKIP_CHECKS" != "true" ]]; then
148+
cat << SKIP_MSG 1>&2
149+
**You can disable the following storage & version checks by running ghe-backup with option "--skip-checks"
150+
OR updating GHE_SKIP_CHECKS to 'true' in your backup.config file.
151+
152+
SKIP_MSG
153+
148154
# Bring in the requirements file
149155
min_rsync=""
150156
min_openssh=""
@@ -178,18 +184,16 @@ if [[ "$CALLING_SCRIPT" == "ghe-backup" ]]; then
178184
echo " - Recommended Disk requirement is $recommended_disk_req MB" 1>&2
179185
echo "" 1>&2
180186

181-
cat <<DATA_TRANSFER_SIZE 1>&2
182-
### Data Transfer Sizes
183-
- repositories: $repos_disk_size MB
184-
- pages: $pages_disk_size MB
185-
- elasticsearch: $es_disk_size MB
186-
- storage: $stor_disk_size MB
187-
- minio: $minio_disk_size MB
188-
- mysql: $mysql_disk_size MB
189-
- actions: $actions_disk_size MB
190-
- mssql: $mssql_disk_size MB
191-
DATA_TRANSFER_SIZE
192-
echo "" 1>&2
187+
printf '### Data Transfer Sizes
188+
- repositories: %d MB
189+
- pages: %d MB
190+
- elasticsearch: %d MB
191+
- storage: %d MB
192+
- minio: %d MB
193+
- mysql: %d MB
194+
- actions: %d MB
195+
- mssql: %d MB\n' \
196+
"$repos_disk_size" "$pages_disk_size" "$es_disk_size" "$stor_disk_size" "$minio_disk_size" "$mysql_disk_size" "$actions_disk_size" "$mssql_disk_size" 1>&2
193197

194198
if [[ $((available_space / (1024 * 1024))) -lt $min_disk_req ]]; then
195199
echo "There is not enough disk space for the backup. Please allocate more space and continue." 1>&2

bin/ghe-restore

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ while true; do
7171
export GHE_VERBOSE=true
7272
shift
7373
;;
74+
-i|--incremental)
75+
export GHE_INCREMENTAL=true
76+
shift
77+
;;
7478
-*)
7579
echo "Error: invalid argument: '$1'" 1>&2
7680
exit 1
@@ -275,17 +279,14 @@ fi
275279
# taking into account the options passed to the script and the appliance configuration
276280
# calculate restore steps
277281
OPTIONAL_STEPS=0
278-
# Cluster restores add an additional step
279-
if $CLUSTER ; then
280-
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 1))
281-
fi
282+
282283
# Restoring UUID
283284
if [ -s "$GHE_RESTORE_SNAPSHOT_PATH/uuid" ] && ! $CLUSTER; then
284285
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 1))
285286
fi
286-
# Restoring Actions
287+
# Restoring Actions + MSSQL
287288
if ghe-ssh "$GHE_HOSTNAME" -- 'ghe-config --true app.actions.enabled'; then
288-
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 1))
289+
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 2))
289290
fi
290291
# Restoring minio
291292
if ghe-ssh "$GHE_HOSTNAME" -- 'ghe-config --true app.minio.enabled'; then
@@ -305,10 +306,16 @@ fi
305306
if ! $CLUSTER && $instance_configured; then
306307
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 1))
307308
fi
308-
# Maximum restore steps
309-
export PROGRESS_TOTAL=$((OPTIONAL_STEPS + 6))
309+
# Restoring settings + restore-chat-integration + restore-packages
310+
if $RESTORE_SETTINGS; then
311+
OPTIONAL_STEPS=$((OPTIONAL_STEPS + 3))
312+
fi
313+
314+
# Minimum number of steps is 7
315+
export PROGRESS_TOTAL=$((OPTIONAL_STEPS + 7))
310316

311317
init-progress
318+
echo "$PROGRESS_TOTAL" > /tmp/backup-utils-progress-total
312319
export PROGRESS_TYPE="Restore"
313320
echo "$PROGRESS_TYPE" > /tmp/backup-utils-progress-type
314321
export PROGRESS=0 # Used to track progress of restore
@@ -318,6 +325,29 @@ echo "$PROGRESS" > /tmp/backup-utils-progress
318325
START_TIME=$(date +%s)
319326
log_info "Starting restore of $GHE_HOSTNAME with backup-utils v$BACKUP_UTILS_VERSION from snapshot $GHE_RESTORE_SNAPSHOT"
320327

328+
if [ "$GHE_INCREMENTAL" ]; then
329+
if [ "$GHE_VERSION_MAJOR" -lt 3 ]; then
330+
log_error "Can only perform incremental restores on enterprise version 3.10 or higher"
331+
exit 1
332+
fi
333+
if [ "$GHE_VERSION_MINOR" -lt 10 ]; then
334+
log_error "Can only perform incremental restores on enterprise version 3.10 or higher"
335+
exit 1
336+
fi
337+
log_info "Incremental restore from snapshot $GHE_RESTORE_SNAPSHOT"
338+
# If we see 'inc_previous' prepended to the snapshot name, then
339+
# we set $INC_FULL_BACKUP and $INC_SNAPSHOT_DATA to $INC_PREVIOUS_FULL_BACKUP and
340+
# $INC_PREVIOUS_SNAPSHOT_DATA respectively. Otherwise, leave them at default setting
341+
# so that incremental restore is from current cycle
342+
if [[ "$GHE_RESTORE_SNAPSHOT" =~ ^inc_previous ]]; then
343+
INC_FULL_BACKUP=$INC_PREVIOUS_FULL_BACKUP
344+
INC_SNAPSHOT_DATA=$INC_PREVIOUS_SNAPSHOT_DATA
345+
log_info "Incremental restore from previous cycle snapshot. Using $INC_FULL_BACKUP"
346+
log_info "Incremental restore from previous cycle snapshot. Using $INC_SNAPSHOT_DATA"
347+
fi
348+
log_info "Validating snapshot $GHE_RESTORE_SNAPSHOT"
349+
validate_inc_snapshot_data "$GHE_RESTORE_SNAPSHOT"
350+
fi
321351
ghe_remote_logger "Starting restore from $(hostname) with backup-utils v$BACKUP_UTILS_VERSION / snapshot $GHE_RESTORE_SNAPSHOT ..."
322352
# Create an in-progress-restore file to prevent simultaneous backup or restore runs
323353
echo "${START_TIME} $$" > "${GHE_DATA_DIR}/in-progress-restore"
@@ -446,6 +476,7 @@ ghe-restore-column-encryption-keys "$GHE_HOSTNAME"
446476
# Always restore secret scanning encryption keys
447477
if [ "$(version $GHE_REMOTE_VERSION)" -ge "$(version 3.8.0)" ]; then
448478
log_info "Always restore secret scanning encryption keys on GHES verions 3.8.0+"
479+
increment-progress-total-count 1
449480
ghe-restore-secret-scanning-encryption-keys "$GHE_HOSTNAME"
450481
fi
451482

@@ -490,9 +521,12 @@ if is_external_database_target_or_snapshot && $SKIP_MYSQL; then
490521
log_info "Skipping MySQL restore."
491522
else
492523
log_info "Restoring MySQL database from ${backup_snapshot_strategy} backup snapshot on an appliance configured for ${appliance_strategy} backups ..."
524+
increment-progress-total-count 2
493525
ghe-restore-mysql "$GHE_HOSTNAME" 1>&3
494526
fi
495527

528+
529+
496530
if ghe-ssh "$GHE_HOSTNAME" -- 'ghe-config --true app.actions.enabled'; then
497531
log_info "Stopping Actions before restoring databases ..."
498532
# We mark Actions as stopped even if the `ghe-actions-stop`
@@ -596,7 +630,7 @@ fi
596630
log_info "Restarting memcached ..." 1>&3
597631
bm_start "$(basename $0) - Restarting memcached"
598632
echo "sudo restart -q memcached 2>/dev/null || true" |
599-
ghe-ssh "$GHE_HOSTNAME" -- /bin/sh
633+
ghe-ssh "$GHE_HOSTNAME" -- /bin/sh
600634
bm_end "$(basename $0) - Restarting memcached"
601635

602636
# Prevent GitHub Connect jobs running before we've had a chance to reset

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
- **[GitHub Enterprise Server version requirements](requirements.md#github-enterprise-version-requirements)**
77
- **[Getting started](getting-started.md)**
88
- **[Using the backup and restore commands](usage.md)**
9-
- **[Scheduling backups](scheduling-backups.md)**
9+
- **[Scheduling backups & snapshot pruning](scheduling-backups.md)**
1010
- **[Backup snapshot file structure](backup-snapshot-file-structure.md)**
1111
- **[How does Backup Utilities differ from a High Availability replica?](faq.md)**
1212
- **[Docker](docker.md)**

docs/scheduling-backups.md

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
# Scheduling backups
1+
# Scheduling backups & snapshot pruning
22

33
Regular backups should be scheduled using `cron(8)` or similar command
44
scheduling service on the backup host. The backup frequency will dictate the
55
worst case [recovery point objective (RPO)][1] in your backup plan. We recommend
66
hourly backups at the least.
7-
87
## Example scheduling usage
98

109
The following examples assume the Backup Utilities are installed under
@@ -19,16 +18,34 @@ storage.
1918

2019
To schedule hourly backup snapshots with verbose informational output written to
2120
a log file and errors generating an email:
21+
```
22+
2223
23-
24-
25-
0 * * * * /opt/backup-utils/bin/ghe-backup -v 1>>/opt/backup-utils/backup.log 2>&1
24+
0 * * * * /opt/backup-utils/bin/ghe-backup -v 1>>/opt/backup-utils/backup.log 2>&1
25+
```
2626

2727
To schedule nightly backup snapshots instead, use:
2828

29-
29+
```
30+
31+
32+
0 0 * * * /opt/backup-utils/bin/ghe-backup -v 1>>/opt/backup-utils/backup.log 2>&1
33+
```
34+
35+
### Example snapshot pruning
36+
37+
By default all expired and incomplete snapshots are deleted at the end of the main
38+
backup process `ghe-backup`. If pruning these snapshots takes a long time you can
39+
choose to disable the pruning process from the backup run and schedule it separately.
40+
This can be achieved by enabling the `GHE_PRUNING_SCHEDULED` option in `backup.config`.
41+
Please note that this option is only avilable for `backup-utils` >= v3.10.0, if this option is enabled you will need to schedule the pruning script `ghe-prune-snapshots` using `cron` or a similar command scheduling service on the backup host.
42+
43+
To schedule daily snapshot pruning, use:
3044

31-
0 0 * * * /opt/backup-utils/bin/ghe-backup -v 1>>/opt/backup-utils/backup.log 2>&1
45+
```
46+
3247
48+
0 3 * * * /opt/backup-utils/share/github-backup-utils/ghe-prune-snapshots 1>>/opt/backup-utils/prune-snapshots.log 2>&1
49+
```
3350

3451
[1]: https://en.wikipedia.org/wiki/Recovery_point_objective

docs/usage.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,18 @@ appliance at IP "5.5.5.5":
7373
Restore of 5.5.5.5:122 from snapshot 20180326T020444 finished.
7474
To complete the restore process, please visit https://5.5.5.5/setup/settings to review and save the appliance configuration.
7575

76-
A different backup snapshot may be selected by passing the `-s` argument and the
77-
datestamp-named directory from the backup location.
76+
A different backup snapshot may be selected by passing the `-s` argument to `ghe-restore` and specifying the
77+
datestamp-named directory from the backup location as the value.
7878

7979
The `ghe-backup` and `ghe-restore` commands also have a verbose output mode
8080
(`-v`) that lists files as they're being transferred. It's often useful to
8181
enable when output is logged to a file.
8282

83+
Every time you execute `ghe-backup` we verify the storage and software setup of the host
84+
you [installed][1] Backup Utilities on, to make sure our [requirements][2] for the host are
85+
met. You can disable this check using the `--skip-checks` argument or by
86+
adding `GHE_SKIP_CHECKS=true` to your configuration file.
87+
8388
### Restoring settings, TLS certificate, and license
8489

8590
When restoring to a new GitHub Enterprise Server instance, settings, certificate, and
@@ -107,3 +112,4 @@ GitHub Actions enabled, the following steps are required:
107112
Please refer to [GHES Documentation](https://docs.github.com/en/enterprise-server/admin/github-actions/advanced-configuration-and-troubleshooting/backing-up-and-restoring-github-enterprise-server-with-github-actions-enabled) for more details.
108113

109114
[1]: https://github.com/github/backup-utils/blob/master/docs/getting-started.md
115+
[2]: requirements.md

0 commit comments

Comments
 (0)